Broadleaf Microservices
  • v1.0.0-latest-prod

Stripe Payment Element Integration

Frontend Project Setup

To integrate the frontend with the Stripe Elements load the Stripe.js as an ECMAScript module.

import { loadStripe } from '@stripe/stripe-js';
import { Elements } from '@stripe/react-stripe-js';

// Use the public key to load the Stripe.js
const stripePromise = await loadStripe('pk_...');

function MyApp(...) {
    // ...
    return (
        <Elements stripe={stripePromise}>
          ...
        </Elements>
    )
}

Example Integration

import { useState } from 'react';
import {
  CardNumberElement,
  CardCvcElement,
  CardExpiryElement,
  useElements,
  useStripe,
} from '@stripe/react-stripe-js';

export const StripePaymentForm = () => {
    ...

    const { error, onSubmit } = useHandleSubmit();

    return (
      <div>
        <h1>Payment Form</h1>
         <Formik
           initialValues={...}
           onSubmit={onSubmit}
           validateOnBlur
           validateOnChange={false}
         >
           {props => (
             <FormikForm>
               <CheckboxField name="savePaymentForFutureUse" label="Save new payment?" />
               <CardNumberElement ... />
               <InputField name="nameOnAccount" autoComplete="cc-name" />
               <CardCvcElement ... />
               <CardExpiryElement ... />
                ...
               <button type="submit">Submit</button>
             </FormikForm>
           )}
         </Formik>
      </div>
    )
}


const useHandleSubmit = () => {
  const stripe = useStripe();
  const elements = useElements();
  const [error, setError] = useState();
  const [stripeError, setStripeError] = useState();

  const onSubmit = async (data, actions): Promise<void> => {
    const { savePaymentForFutureUse, ...billingAddress } = data;

    const billing_details = {
      ...billingAddress,
      email: emailAddress,
    };

    let paymentMethod;
    let displayAttributes= {};
    let paymentName;

    // selectedSavedPaymentMethod - one of the created saved payment method from PaymentTransactionServices
    if (!isEmpty(selectedSavedPaymentMethod)) {
      paymentMethod = {
        id: selectedSavedPaymentMethod.id,
      };

      displayAttributes = selectedSavedPaymentMethod.displayAttributes;

      paymentName = selectedSavedPaymentMethod.name;
    } else {
      const stripeResponse = await stripe.createPaymentMethod({
        type: 'card',
        card: elements.getElement(CardNumberElement),
        billing_details,
      });

      if (!isEmpty(stripeResponse.error)) {
        setStripeError(stripeResponse.error);
        return;
      }

      paymentMethod = stripeResponse.paymentMethod;

      // these are optional and only support displaying info about the card on the frontend
      displayAttributes = {
        creditCardType: paymentMethod.card.brand.toUpperCase(),
        creditCardNumber: maskCardNumber(paymentMethod.card.last4),
        creditCardExpDateMonth: padStart(
          `${paymentMethod.card.exp_month}`,
          2,
          '0'
        ),
        creditCardExpDateYear: `${paymentMethod.card.exp_year}`,
      };

      paymentName = `${displayAttributes.creditCardType} | ${displayAttributes.creditCardNumber} ${displayAttributes.creditCardExpDateMonth}/${displayAttributes.creditCardExpDateYear}`;
    }

    // these are required to pass to the backend as part of the payment
    const paymentMethodProperties = {
      PAYMENT_METHOD_ID: paymentMethod.id,
      CUSTOMER_ID: paymentMethod.customer
    };

    const paymentRequest = {
      name: paymentName,
      savedPaymentMethodId: selectedSavedPaymentMethod.id,
      type: 'CREDIT_CARD',
      gatewayType: 'STRIPE',
      amount: { amount: 11, currency: 'USD' },
      subtotal: cart.cartPricing.subtotal,
      adjustmentsTotal: cart.cartPricing.adjustmentsTotal,
      fulfillmentTotal: cart.cartPricing.fulfillmentTotal,
      taxTotal: cart.cartPricing.totalTax,
      billingAddress,
      shouldSavePaymentForFutureUse: savePaymentForFutureUse,
      paymentMethodProperties,
      displayAttributes,
    };

    try {
        // submit the payment request
        // "handleSubmitPaymentInfo" - can be obtained from our payment SDK - useSubmitPaymentRequest(). It creates a Payment in PaymentTransactionServices
        const paymentSummary = await handleSubmitPaymentInfo(paymentRequest);
        ...
    } catch (err) {
      setError(err);
    } finally {
      ...
    }
  };

  return { error, onSubmit, stripeError };
};