NH

Using Stripe's card element: Some notes

October 09, 2020

What is the react-stripe-js package?

The react-stripe-js package enables injection of card input into the DOM via the <CardElement /> component. The form component (i.e. <CheckoutForm />) with the <CardElement /> compoment must be wrapped by the <Elements /> component

Wrap <CheckoutForm /> with <Elements />

// checkout-page.js
import React from 'react';
import { loadStripe } from '@stripe/stripe-js';
import { Elements } from '@stripe/react-stripe-js';
import CheckoutForm from '../components/checkout-form';

const Checkout = () => {
	// use real publishable key
	const promise = loadStripe('stripe_publishable_key');
	return (
        <div>
            <h1>Fakeshop</h1>
            <Elements stripe={promise}>
                <CheckoutForm />
            </Elements>
        </div>
    );
}

export { Checkout as default }

Server or Serverless Function required

In order to process payments with <CardElement /> the card details have to be sent to Stripe via the confirmCardPayment() function in the Stripe API with a clientSecret generated from the the server or serverless function using the server-side Stripe API

Stripe integration flow based on my Muffin Shop demo

Stripe integration flow diagram

Serverless Function script

Returns the clientSecret to the <CheckoutForm />, which calls the Serverless Function

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const inventory = require('./data/inventory.json');

// simplified calculateOrderAmount()
const calculateOrderAmount = (items) => {
    const totalAmount = items.reduce((total, item) => {
        // get price against inventory
        const product = inventory.find((inventory_item) => inventory_item.sku === item.sku);
        const amount = product.priceBySize.find((productSize) => productSize.size === item.size).price;
        return total + (100 * amount * item.quantity)
    }, 0);

    return totalAmount;
}

exports.handler = async function (event) {
    const { items } = JSON.parse(event.body);

    const paymentIntent = await stripe.paymentIntents.create({
        amount: calculateOrderAmount(items),
        currency: "CAD"
    });

    return {
        statusCode: 200,
        body: JSON.stringify({
            clientSecret: paymentIntent.client_secret
        })
    };
}

Notes: Stripe accepts amount in cents for currencies that use decimals (i.e. USD, CAD)

References


Hey, I'm Nancy Huynh
I'm a self-taught front-end developer relaxing in Toronto
This is a collection of new things I'm learning