Beginner's Guide to Stripe Integration in React

September 8, 2020

All online stores need a payment gateway, irrespective of the service or product being sold. As such, it is important for developers to ensure the implementation is successful and that payments are secure for customers. In this article, we will learn how to set up the Stripe API for all payment purposes. Stripe is the go-to payment processor for developers thanks to its developer-friendly API, highest grade of payment processing security, and detailed documentation.

Integration With React

Let’s assume that we run an online store and have enough information to process the order: order details, order total, and user details. We will focus on the following:

  1. Creating a Stripe Account
  2. Switching to Test Mode on Stripe
  3. Obtaining Stripe Access Token from Dashboard
  4. Integrating with React using react-stripe-checkout

Before we get started with the implementation, let’s understand the flow of payment information.

How does Stripe help us secure financial transactions?

  1. Card details are entered on the website using the dialog box that is generated by the React component that we will build.
  2. The web application sends a request to the Stripe API with card details in it. The role of the web application is limited to forwarding of the card details. Web apps never store any payment information.
  3. Stripe API stores the card details securely and sends a token to the web application.
  4. The token is a point of reference to identify the card. Note that once the card details have been sent to Stripe and stored securely, they are never shared with anyone and only the token is used from that point on for security reasons.
  5. The backend application makes a request to the API with the token in place. The token contains information about the total price to be charged, which is calculated in the frontend part of the application. When we add products to the cart, the price is calculated in the browser, and the API call is made. Any computation on the browser is insecure as developers can easily access the price computed and change its value to 0, before the API call is made. Therefore, it’s a good practice to recalculate the price at the backend. With the help of cart items present, we should access the prices of items from databases and recalculate the price and make the API call from the backend.
    Payment Flow Image Source

With this information in mind, we can understand the important role Stripe plays. Payment gateways such as Stripe and PayPal garner the trust of millions of users by providing seamlessly integrated solutions.

Creating a Stripe Account

To create an account, register for an account and provide your account details (email, mobile number, name, and password). Upon successful registration, a confirmation email is sent to the registered email account. Click on the email link to activate your new Stripe account.

If already registered, log in to your dashboard with your credentials.

Switching to Test Mode on Stripe

This step is important to ensure we are in testing mode. This enables us to test aspects of payments such as receiving payments, sending payments, or approving refunds. On the bottom left of your dashboard, you should find the Viewing test data button. Enable that by toggling the button provided. The dashboard is shown for your reference.

Dashboard View Dashboard View

Obtain a Stripe Access Token

On the Stripe dashboard you will find a section called Get your test API keys. Under there, you will find two keys, a Publishable key, and a Secret key. As the name suggests, we need to keep these keys secure. The publishable key is used to send requests, whereas the secret key is stored in the .env file at the backend. Let us talk about the .env file before we proceed.

Config Keys

The cloud services and APIs provide keys for accessing their services. But mentioning these keys in the code is a security threat to the entire application. Hackers can easily use the keys to access your data. Therefore, a .env file is created which includes all the secret keys in it. When we upload the code base to be deployed, .env files are ignored. This is because they are added in the .gitignore file. Any file mentioned in the .gitignore file will not be uploaded. While building an web application that involves both frontend and backend components, we store all the secret information in these .env files. We will look at an example that demonstrates the use of .env file below.

API Test Keys API Keys on Dashboard

Stripe Integration using react-stripe-checkout

There are many libraries available for integrating React with stripe. We will be using the react-stripe-checkout library in this tutorial.

Install the library using the following command:

npm install react-stripe-checkout

Once installed, create a new component called CheckoutWithStripe.js and add it to your main component list. Insert the appropriate details and create your custom functions to add more details to the API call.

Here is an example function that you can modify using your custom store details:

import React from 'react';
import StripeCheckout from 'react-stripe-checkout';

// sample function defined to compute total quantity of cart
function computeQuantity(cart) {
    return cart.reduce((count, itemInCart) => count + itemInCart.quantity, 0);
}
// similar functions can be defined to compute total price, email of the user, etc.

class CheckoutWithStripe extends React.Component {
    onToken = (res) => {
        fetch('/save-stripe-token', {
            method: 'POST',
            body: JSON.stringify(token),
        }).then(res => {
            res.json().then(data => {
                console.log(`Payment token generated, ${data.name}`)
            })
        })
    };

    render() {
        return (
            <StripeCheckout
                amount = '10.00'
                name="STRIPE_INTEGRATION"
                // functions defined above can be used to add more information while making the API call.
                // description={`Order of ${computeQuantity(cart)} items!`}
                image='LINKTOIMAGE'
                stripeKey="PUBLISHABLE_STRIPE_KEY"
                currency="INR"
                email='USER_EMAIL'
                token={this.onToken}/>          
        );
    }
}

export default CheckoutWithStripe

Call the component CheckoutWithStripe from the payment page. The ${data.name} displayed on the console is the token generated, which is sent to the backend.

You should see a button which says Pay With Card.

An example is given below: Paywithcard stripe Intermediate Output

Finally, a dialog box should appear to enter card details:

Final Output Final Output

The error says that the API key is invalid.

To resolve the error, you may enter your publishable API key. I haven’t included the PUBLISHABLE_KEY in the code for security reasons.

To resolve the error, you must enter your publishable API key. We have discussed about entering the publishable key which is available on the dashboard. Enter the PUBLISHABLE_KEY in the stripeKey parameter under CheckoutWithStripe.js component.

To verify that the application is in test mode, you will get an alert on the top right corner as shown in the image above.

Backend Integration

On the backend, there are three steps that we need to implement. We save the secret key in a file called variables.env. Let us look at the steps involved in the backend.

  1. Create a file called variables.env. It should contain the following:
STRIPE_SECRET = "YOUR_STRIPE_SECRET_KEY"
  1. Load the stripe module. Install the stripe module at the backend using the command:
npm i stripe

Once installed, load the module using the code below:

const require = require('stripe')(process.env.STRIPE_SECRET);
  1. Charge the card by making an API call with the token information and amount to be charged, to the Stripe charges API. The source parameter takes in the token generated at the frontend as the input. For reference, I have mentioned it as ${data.name}.

There are various Stripe Charges API endpoints. They are as follows:

POST /v1/charges
GET /v1/charges/:id
POST /v1/charges/:id
POST /v1/charges/:id/capture
GET /v1/charges
        const charge = await stripe.charges.create({
        amount=1000,
        source: `${data.name}`,
        currency: 'INR',
        description: "First Test Charge"

        });

The JSON response, stored in variable charge, upon successful transaction is given as follows:

{
  "id": "ch_1Go3g4AWIeoDa33qQC9MzAa6",
  "object": "charge",
  "amount": 1000,
  "amount_refunded": 0,
  "application": null,
  "application_fee": null,
  "application_fee_amount": null,
  "balance_transaction": "txn_1Go3g5AWIeoDa33qAkDzey8K",
  "billing_details": {
    "address": {
      "city": null,
      "country": null,
      "line1": null,
      "line2": null,
      "postal_code": null,
      "state": null
    },
    "email": null,
    "name": "lalith1403@gmail.com",
    "phone": null
  },
  "calculated_statement_descriptor": "YOUR_NAME_HERE",
  "captured": true,
  "created": 1590741296,
  "currency": "inr",
  "customer": null,
  "description": "First Test Charge",
  "disputed": false,
  "failure_code": null,
  "failure_message": null,
  "fraud_details": {},
  "invoice": null,
  "livemode": false,
  "metadata": {},
  "on_behalf_of": null,
  "order": null,
  "outcome": {
    "network_status": "approved_by_network",
    "reason": null,
    "risk_level": "normal",
    "risk_score": 53,
    "seller_message": "Payment complete.",
    "type": "authorized"
  },
  "paid": true,
  "payment_intent": null,
  "payment_method": "card_1Go3fzAWIeoDa33qffuWbgvx",
  "payment_method_details": {
    "card": {
      "brand": "visa",
      "checks": {
        "address_line1_check": null,
        "address_postal_code_check": null,
        "cvc_check": "pass"
      },
      "country": "US",
      "exp_month": 2,
      "exp_year": 2022,
      "fingerprint": "9AF2uqkMQ9vYnLtB",
      "funding": "credit",
      "installments": null,
      "last4": "4242",
      "network": "visa",
      "three_d_secure": null,
      "wallet": null
    },
    "type": "card"
  },
  "receipt_email": null,
  "receipt_number": null,
  "refunded": false,
  "refunds": {
    "object": "list",
    "data": [],
    "has_more": false,
    "url": "/v1/charges/ch_1Go3g4AWIeoDa33qQC9MzAa6/refunds"
  },
  "review": null,
  "shipping": null,
  "source_transfer": null,
  "statement_descriptor": null,
  "statement_descriptor_suffix": null,
  "status": "succeeded",
  "transfer_data": null,
  "transfer_group": null,
  "source": "tok_visa"
}

Additional Resources

  1. Stripe Documentation
  2. Detailed Description of Transaction Process.
  3. React Boilerplate with Stripe integration code

Conclusion

We have walked through the entire process of accepting payments with Stripe. After setting up an account and obtaining API keys, we are able to integrate it seamlessly into our application. Stripe has made payments easy and we encourage you to build your applications with integrated payment gateways.


Peer Review Contributions by: Sophia Raji


About the author

Lalithnarayan C

Lalithnaryan C is an ambitious and creative engineer pursuing his Masters in Artificial Intelligence at Defense Institute of Advanced Technology, DRDO, Pune. He is passionate about building tech products that inspire and make space for human creativity to flourish. He is on a quest to understand the infinite intelligence through technology, philosophy, and meditation.

This article was contributed by a student member of Section's Engineering Education Program. Please report any errors or innaccuracies to enged@section.io.