Making a Payment Using a Credit Card

Learn how to purchase books and make a Stripe payment with a credit card.

The previous lesson taught us how to set up Stripe integration by generating a payment intent from Stripe. Let’s pick up from where we left off. Open the imports/ui/MakePayment.jsx file. On lines 2–6, we import useStripe, useElements, and PaymentElement from @stripe/react-stripe-js. The useStripe hook is used to load Stripe into the component, while useElements is used to load a Stripe Elements tag. The MakePaments component must be wrapped by a Stripe Elements tag because we’ll use a Stripe PaymentElement.

The PaymentElement component

The PaymentElement is a component from Stripe that displays a form on the page so that users to enter their credit card details for processing. The component in which the PaymentElement is contained should be wrapped with a Stripe Elements tag so that it has access to the Stripe library and client secret.

Open App.jsx to see how Elements is used to wrap the MakePayment component. On lines 84–88, the Element component from Stripe is used to wrap MakePayment. If a user navigates to the /make_payment route, the component is rendered. In the MakePayment.jsx file on lines 10–11, we extract stripe and elements from the hooks function. On line 52, we load the PaymentElement component.

Submitting the PaymentElement form

We have a “submit” button defined on line 54. With a click of this button, the handleSubmit function is called. The “submit” button is disabled if stripe is null, which means that we were unable to load the Stripe library on the component.

The handleSubmit function is an async function, and we’ll need to await the value. On line 15, we check if stripe and elements are loaded. If it’s not, we return from the function.

On line 21, we call the confirmPayment function of stripe. This function is an async function, and we need to await the result. We pass in the elements and confirmParams, which is an object with a key of return_url. If the payment was successfully confirmed, Stripe pushes the user to the URL defined in the object key, return_url. We use the Meteor.absoluteUrl function that returns the root of the application. Upon successful payment confirmation, we want to push the user to the /complete route.

If Stripe was unable to confirm the payment, the error destructured from the method stripe.confirmPayment on line 21 won’t be null. Stripe uses the client secret to confirm if the payment the user is about to make is a valid payment intent. This information is available in the elements variable that was passed to the Stripe payment confirmation method.

The setErrorMessage function is called when an error is encountered by passing in the message property of the error object. We also remove the client_secret from local storage and could decide to push the user to the component to restart the payment process, if we want.

Payment Confirmation

Stripe pushes the user to the /complete route. Let’s take a look at the /complete route. Open the App.jsx file. On lines 90–94, we have a route defined that Stripe pushes us to. The /complete route is wrapped with a Stripe Elements tag that renders the CheckPaymentStatus. The CheckPaymentStatus checks the status returned from Stripe to see if the payment was successful.

Open the imports/ui/CheckPaymentStatus.jsx file. On lines 11–51, we define a function called checkStatus. This function performs a check on the payment status. It does that by calling the stripe.retrievePaymentIntent function and passing in the client_secret. On line 12, we retrieve the clientSecret from the URL using the URLSearchParams function. The search parameter of the URL is retrieved after the ? symbol in the URL. We get the search parameter using window.location.search. The get function of URLSearchParams is used to retrieve the payment_intent_client_secret key from the search parameter.

On line 16, we check if we were able to retrieve a clientSecret from the URL. If the clientSecret is null, we push the user to the home route. We await the result of the payment confirmation check with Stripe on line 22. We’re only interested in the paymentIntent, which we destructured from the return value.

On line 28, we check the status property of the paymentIntent using a switch statement. The showMessage function is updated with the status of the payment. The showMessage is a function used to change the message state. On line 48, we call a Meteor Method called stripe.completePayment to update the payment status in our database. We also remove the client_secret key from local storage.

Calling the checkStatus function

The checkStatus function is called as soon as stripe is loaded on the page. On lines 56–60, we define a useEffect function that has a dependency of stripe. This means that this function only executes when the value of stripe changes. Inside the useEffect function, we also check if stripe isn’t null. If the check succeeds, the checkStatus function executes, and the result of the Stripe confirmation is displayed on the page.

Task

Run the application, and purchase some books. Use the following credit card details to make the payment:
Card number: “4242 4242 4242 4242
Exp date: Any valid future date
CVV: Any valid three-digit number

Get hands-on with 1200+ tech skills courses.