Skip to content

Instantly share code, notes, and snippets.

@dayhaysoos
Last active March 15, 2021 22:40
Show Gist options
  • Save dayhaysoos/fb8998c9a1eeadfafa71c780c9bdf0cf to your computer and use it in GitHub Desktop.
Save dayhaysoos/fb8998c9a1eeadfafa71c780c9bdf0cf to your computer and use it in GitHub Desktop.

Nick's SA Take home project

Spinning it up:

  • After cloning this repo, run: npm install

    • Add a .env file with your Stripe API secret key, there's a .env.example file for you to refer to. Feel free to change that file name to .env and add your Stripe API secret key there.

    npm start

  • Click on one of the "Purchase" buttons under the books and it should take you to the checkout page. Fill in the inputs, make sure you have a valid email ([email protected]). Fill in the card info with 4242424242424242 and hit Enter or click "Pay". You should see the success screen with some details of your purchase going through.

The Challenge

The goal of this challenge was to create a simple e-commerce flow of fulfilling a purchase, using Stripe Elements and displaying the charge ID and total amount after.

  1. My solution uses Stripe Elements for collecting card data from a users input, and creates a Charge using that token for Stripe's Charge API. The Card information the user input on the form is used to create a token. That token is passed to an express backend, where we use the create Charge API to fulfil the Charge. We use Stripe Elements because it's a safe and secure way for buyers to input their credit card information while also saving tons of work for the developer.

  2. For the most part, I was able to use a lot of the code from the examples provided on the Stripe website. More specifically the Accept a Card Payment walk through (linked below this paragraph). There's a list of things I'd like to bring attention to that helped me get to my solution:

  • Added shipping inputs to the form since the user is purchasing physical books
  • Added an itemId value to /checkout get request, that way I could pass it as a query param to the server.
  • I created a map called ITEM_DATA to refer to the selected products via itemId (which gets passed as a query param).
  • I created a function for formatting the data to display with proper currency format on the backend before returning it.
   var formatter = new Intl.NumberFormat("en-US", {
      style: "currency",
      currency: "USD",
    });

Usage:

formatter.format(result.amount / 100)

For example: ITEM_DATA[3] refers to the data associated with the Working In Public Book.

This way I was able to dynamically access the appropriate data per item.

  • The success page has the title of the book, Charge id, and the amount as well as a URL to see more details about the purchase.

Challenges

It's pretty weird navigating basic HTML/CSS/JS and an express server after living life on the cutting edge for 2-3 years straight. Fortunately, I used to teach these kind of implementations at Resilient Coders so it wasn't so bad. One cool thing that I learned is that body-parser is deprecated and express has something for encoding urls now.

Another challenge was figuring out the best way to dynamically send the token info to the Charge API. My initial idea was to create another hidden input on the client side with information on each product and sending the whole thing through req.body, but it didn't feel right. I saw that in the set up of this project, each product was referred to in the switch statement by numbers 1-3, so I figured that'd be a great opportunity to use that number and refer to an object on the server side. This is much more secure approach anyway, since no one can pass any fake values to the server this way.

Links that helped me get to the solution: Stripe Charge API Docs

Accept a Card Payment

Accept a Card Payment walk-through is where I learned to use Stripe Elements.

  1. As far as extending this, I definitely would have preferred seeing this in React, with Gatsby or Next JS and serverless functions to take care of handling the tokens and Charge API securely. That isn't exactly extending the current application, though. If I were to entertain the idea of staying on this HTML/CSS/Node set up only, I would handle getting the products differently.

I'd migrate to the Payments API. Instead of using the server to process charges, we'd use it to set up Payment Intents. The Charge API is deprecated and limited anyway, so switching to the Payments API is recommended. It would look similar to the way Charges are made:

  const paymentIntents = await stripe.paymentIntents.create({
    amount,
    currency: "usd",
  });

Depending on who I'm talking to, I might suggest using Stripe Checkout (very unlikely since the in-house card collection is usually the preferred experience) but I would recommend this to anyone who might not want to manage their own server or the payment process itself and they could create products using the Product and Price APIs.

Another thing that might be considering more "robust" is manage error handling. Right now, if you submit an e-mail with an invalid email format, you get an error but you don't get a nice page that lets you know there was an error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment