Integrating Stripe Payments in Ionic React JS App with Capacitor and NodeJS

Integrating Stripe Payments in Ionic React JS App with Capacitor and NodeJS

ยท

5 min read

This code will show you how to setup your Ionic React application to support the Payment Sheet From Stripe using the Capacitor Community Stripe Plugin. We will also create a small server application to run locally to create the payment intent secret that is required for the application to work properly with Stripe. Finally, we will show how to package and deploy the application to a mobile device using Ionic Capacitor

You need to have a stripe account set up for this demo. See documentation for setting up your account here - stripe.com/docs/implementation-guides/core-..

Image description

Video

The React Client Application

create ionic react application

ionic start --type react

Install the Capacitor Stripe plugin using the following command:

npm install @capacitor-community/stripe

Additional plugin configuration available here stripe.capacitorjs.jp/docs/configuration

Create .env in root of project to hold the

REACT_APP_STRIPE_PUBLISHABLE_KEY='pk_test_VALUE'

Initialize the Stripe plugin with your publishable key in your App.tsx file:

import { Capacitor } from '@capacitor/core';
import { Stripe } from '@capacitor-community/stripe';

// Initialize the Stripe plugin
if (Capacitor.isPluginAvailable("Stripe")) {
  Stripe.initialize({
    publishableKey : process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY+'',
  })
}

Create a new component for a StripeCheckoutButton and add the following code.

Make sure to adjust the IP address for the API call to match the address of your computer so this can be tested appropriately on device.

This code accomplishes two things 1) make API call to get payment intent from the server 2) Present the payment sheet to get credit card information from the user and charge the user.

import React, { useState } from "react";
import { IonButton } from "@ionic/react";
import { Stripe } from "@capacitor-community/stripe";

const StripeCheckoutButton: React.FC = () => {
  const [loading, setLoading] = useState(false);

  const handleCheckout = async () => {
    setLoading(true);

    try {
      const response = await fetch(
        "http://192.168.1.56:3000/create-payment-intent",
        {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ amount: 1000, currency: "usd" }),
        }
      );

      const data = await response.json();
      console.log("PaymentIntent client secret:", data.clientSecret);

      await Stripe.createPaymentSheet({
        paymentIntentClientSecret: data.clientSecret,
        merchantDisplayName: "Inclusive Innovation Incubator",
      });

      const { paymentResult } = await Stripe.presentPaymentSheet();
      console.log(paymentResult);

    } catch (error) {
      console.error("Payment failed:", error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <IonButton onClick={handleCheckout} disabled={loading}>
      {loading ? "Loading..." : "Checkout - Payment Sheet"}
    </IonButton>
  );
};

export default StripeCheckoutButton;

When the Payment Sheet is displayed, the user can enter their payment information and submit the payment. If the payment succeeds, the paymentIntent object will contain information about the successful payment. If the payment fails, an error will be thrown.

The Server

We need to create a Payment Intent endpoint on a server to create the payment-intent client secret and pass it to the Payment Sheet.

For the purpose of this example we will create a small node server and run it locally.

First create a new directory in your project called server

mkdir server
cd server

Then initialize a node project

npm init

Then install the required libraries

npm install express body-parser cors stripe

First of all, install an npm package called dotenv using the following command in your node.js project root directory;

npm install dotenv --save

dotenv package automatically loads environment variables from .env file into process object in node.js applications.

Create a .env file in your server root directory and add the stripe key, we will use it in the createPaymentIntent method

STRIPE_SECRET_KEY='sk_test_VALUE'

Next create an file called index.js as the main file for your server; it has one route /create-payment-intent.

In this code, we're importing the createPaymentIntent method from the createPaymentIntent.js file, and setting up an Express app that listens for POST requests to the /createPaymentIntent path.

When a POST request is received at this path, the createPaymentIntent function is called with the request and response objects.

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const { createPaymentIntent } = require('./createPaymentIntent');

const app = express();

app.use(bodyParser.json());
app.use(cors());

app.post('/create-payment-intent', createPaymentIntent);

app.listen(3000, () => {
  console.log('Server listening on port 3000');
});

Then create the file that has the code for the /create-payment-intent route.

In this code, we're requiring the stripe package and creating a createPaymentIntent function that takes in a req (request) and res (response) object.

Inside the function, we're extracting the amount and currency values from the request body, and using the Stripe SDK to create a new payment intent with those values.

Once the payment intent is created, we're sending the client secret back to the client in the response body, which can then be used to complete the payment process.

Here we also use the information from the .env file to set the API key

require('dotenv').config();
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

function createPaymentIntent(req, res) {
  const { amount, currency } = req.body;

  stripe.paymentIntents.create({
    amount,
    currency,
    // You can also add additional parameters here, such as a customer ID or payment method ID
    metadata: { integration_check: 'accept_a_payment' },
  })
    .then(paymentIntent => {
      res.json({ clientSecret: paymentIntent.client_secret });
    })
    .catch(error => {
      console.error(error);
      res.status(500).send({ error: 'An error occurred while creating the payment intent' });
    });
}

module.exports = {
  createPaymentIntent,
};

To run the server, navigate to the directory where your index.js file is located, and run node index.js. This will start the server and allow you to test your payment process locally.

You can also use a client like postman or thunderclient to test the API locally

Running the Application

First start the node server

node index.js

Next launch your capacitor application, I am using IOS so I need to add capacitor ios package.

npx cap add ios

To actually build and run the project you then use the following commands

npx cap add ios
npx ionic build
npx cap copy ios;
npx cap run ios --external --no-build --no-sync
ย