Stripe Connect using Paystack

Stripe Connect is an awesome Stripe feature that automates a payment collection system. Let's say you are creating a platform that links creators with customers, i.e (Udemy), you will need to collect the creators bank details that way when a customer makes a purchase, the amount is automatically split between you the owner of the platform and the creator who made the product (depending on the percentages you agree of course).

This is very useful. However, Stripe is not available in every country which means those countries without stripe have to find an alternative payment system like PayStack. That is exactly what we are doing in this article. I will show you how to set up the same feature (Stripe Connect) using Paystack.

Prerequisites

To get started, you must have:

  • Paystack Business Account - Ensure you create an account with Paystack before proceeding.
  • Basic Understanding of Javascript and Node

Note:

Paystack does not have a service that functions exactly similar to Stripe connect. However, we can use the API's and tools that Paystack offers to intergrate a similar payment processing system into the platform you are making. Let's see how.

Create an Express Server

Start by creating an express server. You can refer to this article to learn more about creating a simpler server using express

How to Create a NodeJS Server Using Express
Learn how to create a node.js server using the Express framework and define different routes to handle the GET requests.

Recap:

  • Create an empty directory for your project. Give it a name of your choosing

  • Create a file in that directory called "app.js". This will be the entry file.

  • Initialize a new node project in that directory using npm init command - this will create a package.json file in the root directory

  • Install the required dependencies. In this demo, we are using express, nodemon, dotenv and paystack api.

Install them using the command below:

npm install express nodemon dotenv paystack-api

Inside the app.js file add the code below.

const express = require('express');
require("dotenv").config();
const paystack = require("paystack-api");

const app = express();
const port = 3000;

app.listen(port, () => console.log(`Server is running on port: ${port}`));

Make sure you require the dependencies in your file as shown above. Once done, start your server using npm start command in the terminal.

npm start

You should see something similar to this in your terminal if everything went correctly.

Img 3.png

If you are getting errors, refer to the article above so that we are on the same page.

Get Public Key and Secret Key

Before proceeding, we need to get Paystacks' Public and Secret Keys. To do so:

  • Login to your Paystack account and ensure you are in Test mode when in development mode.

  • Select the settings tab on the bottom left.

    Img 1.png

  • On the settings page, head over to the API Keys & Webhooks. You should find your public and secret keys there.

    img 2.png

After getting the keys, go back to your project folder and create a file in the root directory with the name .env. This is where we will store Paystack's Secret key and public key. Inside the file, add the following and paste the keys from your Paystack account inside the quotation marks.

PUBLIC_KEY = "Add your Public key here"
SECRET_KEY = "Add your Secret key here"

Paystack Subaccounts

The next step is to initialize a paystack client with the secret key stored in the .env file. Here is how we do that.

const paystackClient = paystack(process.env.SECRET_KEY);

With paystack initialized, we get access to different methods made available to us by paystack. One of those methods is Subaccounts. Subaccounts allow us to create the onboarding process in a slightly different way compared to Stripe onboarding.

In-order to use Subaccounts, we need some data collected from the user. You can get this data from the client side of your application. I am not going to create the client side. But in the real sense, you will have a form in the client side that collects data from the user. When they click the submit button, this data is sent to the backend and we get access to that data in the request body.

So, create a form with the following fields. "User Name, business, email, bank, and account number". then send this data to the backend. You can add more fields in the form depending on your preference. For demonstration purposes, I will hardcode the data and assume I got them from the client. This is the data we will feed to the subaccount method.

const info = {
    name: "hoi polloi",
    email: "[email protected]",
    bank: "Zenith Bank",
    accountNumber: "0000000000"
}

So far here is the code we have:

const express = require("express");
require("dotenv").config();
const paystack = require("paystack-api");

const app = express();
const port = process.env.PORT;

const paystackClient = paystack(process.env.SECRET_KEY);

const info = {
    name: "hoi polloi",
    email: "[email protected]",
    bank: "Zenith Bank",
    accountNumber: "0000000000"
}



app.listen(port,  ()=> {
    console.log(`Server is running on port: ${port}.`);
});

Handling the GET Request to "/" Route

Under the info data, create the home route as shown below.

app.get("/", async (req,res) => {
    // Add your code here
}

Let's now organize the data in a format that aligns with paystacks' requirements. Inside the curly braces, add the code below.

app.get("/", async (req,res) => {
    const data = {
        business_name: info.name,
        primary_contact_email: info.email,
        settlement_bank: info.bank,
        account_number: info.accountNumber,
        percentage_charge: 1.5,
    }
}

Notice, in this data object, we are filling the keys with values that I hardcoded (data from the client side).

We can now create the subaccount in Paystack. to do so, we'll use a try catch block to get the error if there is any.

app.get("/", async (req,res) => {
    const data = {
        business_name: info.name,
        primary_contact_email: info.email,
        settlement_bank: info.bank,
        account_number: info.accountNumber,
        percentage_charge: 1.5,
    }
    
    try {
        const subAccount = await paystackClient.subaccount.create(data);
        res.send(subAccount);
    } catch (err) {
        console.log(err);
    }
}

In the try block, we have used the paystackClient with the subaccount method to create the account with the data we organized above. I have then sent a response to the home route so that we can see the data we get back from paystack. If everything goes correctly, you should see the following when you visit "http://localhost:3000/".

Img 4.png

Notice: From the JSON object, you get the status, message, and data holding the information about the user we created. The message value says the Subaccount has been created as shown above. You can also confirm the account creation was successful by going to the subaccount section in Paystack. You should see the account that has been created.

Img 5.png

With the subaccount data, you can get the id which is under the "data" key and save it in your database. That way you can use that ID to confirm if the creator has submitted bank details. Let's see how to do that.

Getting the ID when Saving the Subaccount

We need to make a little change to the code so that we can get the ID.

app.get("/", async (req,res) => {
    const data = {
        business_name: info.name,
        primary_contact_email: info.email,
        settlement_bank: info.bank,
        account_number: info.accountNumber,
        percentage_charge: 1.5,
    }
    
    try {
        const subAccount = await paystackClient.subaccount.create(data);
        
        const ID = subAccount.data.id;
        res.send({ID});
    } catch (err) {
        console.log(err);
    }
}

If you visit "http://localhost:3000/" again, you should see the ID.

Img 6.png

You can now save this ID to your database rather than send it as a response to the GET request.

Retrieving Data from Paystack using the ID

Let's create an endpoint that the creator can only access if his\her paystack account status is true.

Below the home route, create another endpoint as shown below.

app.get("/accountStatus", async (req, res) => {
    const ID = "1007199"; // retireive this from the database.
    
    try {
        const accountInfo = await paystackClient.subaccount.get({id: ID});

        res.send(accountInfo);
    } catch (err) {
        console.log(err);
    }
})

Inside the curly braces, retrieve the ID from the database assuming you did save it in the database. In my case I will just hardcode it for demonstration purposes.

We then use the paystackClient accompanied with the subaccount method to get the information from paystack of the ID we provide .

If everything goes correctly, we should see the ID user's information when we head to this endpoint "http://localhost:3000/accountStatus".

Img 7.png

Notice the message says that the Subaccount has been retrieved.

Bonus: Locking "/accountStatus" endpoint.

Let's now lock this endpoint so that it is only accessible by a verified creator/user.

From the JSON data, the status is true. Which means we can use this information to lock our endpoint. Here is how we do that using conditional statements.

app.get("/accountStatus", async (req, res) => {
    const ID = "1007199" // retireive this from the database.

    try {
        const accountInfo = await paystackClient.subaccount.get({id: ID});

        if(!accountInfo.status){
            return res.status(401).send("Unauthorized");
        } else {
            res.send("Welcome: You are verified");
        }
    } catch (err) {
        console.log(err);
    }
})

We are using if statement to decide whether the user is authorized or not.When you visit the accountStatus endpoint again with a valid ID, you should see this:

Img 8.png

That is all for this tutorial. If you have any questions, drop them in the comments below. Here is the whole code,

const express = require("express");
require("dotenv").config();
const paystack = require("paystack-api");

const app = express();
const port = process.env.PORT;

const paystackClient = paystack(process.env.SECRET_KEY);

const info = {
    name: "hoi polloi",
    email: "[email protected]",
    bank: "Zenith Bank",
    accountNumber: "0000000000"
}


app.get("/", async (req, res) => {

    const data = {
        business_name: info.name,
        primary_contact_email: info.email,
        settlement_bank: info.bank,
        account_number: info.accountNumber,
        percentage_charge: 1.5,
    }

    try {
        const subAccount = await paystackClient.subaccount.create(data);

        const ID = subAccount.data.id;

        res.send({ ID });
    } catch (err) {
        console.log(err);
    }
})


app.get("/accountStatus", async (req, res) => {
    const ID = "1007199" // retireive this from the database.

    try {
        const accountInfo = await paystackClient.subaccount.get({id: ID});

        if(!accountInfo.status){
            return res.status(401).send("Unauthorized");
        } else {
            res.send("Welcome: You are verified");
        }
    } catch (err) {
        console.log(err);
    }
})


app.listen(port, () => {
    console.log(`Server is running on port: ${port}.`);
});

Conclusion

While Paystack doesn't offer a feature identical to Stripe Connect, you can leverage its API and tools to implement a similar payment processing system. With the steps outlined above, you can create subaccounts for creators and handle transactions on your platform seamlessly using Paystack. Remember to secure your API keys and implement error handling to ensure a robust payment system.

Thank you for reading : )

Table of Contents
Great! Next, complete checkout for full access to GeekBits.
Welcome back! You've successfully signed in.
You've successfully subscribed to GeekBits.
Success! Your account is fully activated, you now have access to all content.
Success! Your billing info has been updated.
Your billing was not updated.