Accepting Payments with Paystack API in Node.js and Express.js: Implementation and Best Practices

Leveraging the Paystack API within a Node.js environment to facilitate payment acceptance and verification — while ensuring a clean and scalable code.

Chiboy
Published in
7 min readMay 22, 2023

--

Hello and welcome!

If you’re reading this, you’re in for an exciting tutorial. Today, I’ll guide you through the process of leveraging the Paystack API within a Node.js environment to facilitate payment acceptance and verification. But that’s not all! We’ll also dive into the realm of clean architecture, ensuring that our code is not only functional but also highly readable, maintainable, and scalable.

Before we go further into writing the code let's have a breakthrough of Paystack payment API. To receive payment using Paystack API you will need to make API calls to these three endpoints:

  1. Initialize endpoint: The API expects the customer’s email, transaction amount in Kobo, and additional parameters. It will return a transaction reference, an access code for the SDK charge, and an authorization URL.
  2. Verify endpoint: After a successful payment, call the endpoint to confirm the payment status. The response will provide an authorization code, allowing you to charge the user in future transactions.
  3. Charge authorization: This endpoint is used to charge returning customers in the future without collecting their payment details after collecting them the first time.

Since this tutorial is centered around receiving payments through the Paystack API, we will be focusing on sending requests to the initialize endpoint. Additionally, for testing purposes, we will be using POSTMAN to interact with our application on the server side.

Let’s get started on this journey of exploration and implementation!

  1. To get started, create a Paystack account by visiting the registration page. If you don’t have an account yet, simply sign up to create one.
  2. Once you have signed up and logged into your Paystack dashboard, navigate to the Settings section and click on “API Keys and Webhooks”. From there, locate the Test Secret Key and make sure to securely save it. This key will be used to authenticate your application during API requests.
  3. Let’s kickstart our project by creating a new folder. Open your command prompt or Git Bash terminal and run the following command to create a new project directory:
mkdir paystack-nodejs-app

This command will create a folder named “paystack-nodejs-app” which will serve as the root directory for our application. Feel free to replace “paystack-nodejs-app” with your preferred folder name.

4. To initialize a new Node.js project, navigate to the project folder and run this command.

cd paystack-nodejs-app
npm init -y

5. Install the required modules for this application by running the following command:

npm install express body-parser dotenv 

6. Next we need to create an index.js file in the root of our application, then add the following code.

// index.js file

require('dotenv').config();
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const router = require('./Router/route')



const port = process.env.PORT || 3001;
// Parse incoming requests with JSON payloads
app.use(bodyParser.json());

// Call the routers
app.use(router);



// Start the server
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});

7. Now, let’s create the controller file. In the root directory of your project, create a new folder called “controllers”. Inside the “controllers” folder, create a file named contollers.js.

// controllers/controllers.js file

require('dotenv').config();
const express = require('express');
const https = require('https');


const payStack = {

acceptPayment: async(req, res) => {
try {
// request body from the clients
const email = req.body.email;
const amount = req.body.amount;
// params
const params = JSON.stringify({
"email": email,
"amount": amount * 100
})
// options
const options = {
hostname: 'api.paystack.co',
port: 443,
path: '/transaction/initialize',
method: 'POST',
headers: {
Authorization: process.env.PUBLIC_KEY, // where you place your secret key copied from your dashboard
'Content-Type': 'application/json'
}
}
// client request to paystack API
const clientReq = https.request(options, apiRes => {
let data = ''
apiRes.on('data', (chunk) => {
data += chunk
});
apiRes.on('end', () => {
console.log(JSON.parse(data));
return res.status(200).json(data);
})
}).on('error', error => {
console.error(error)
})
clientReq.write(params)
clientReq.end()

} catch (error) {
// Handle any errors that occur during the request
console.error(error);
res.status(500).json({ error: 'An error occurred' });
}
},
}

const initializePayment = payStack;
module.exports = initializePayment;

So, basically, the acceptPayment function is a controller that handles the payment acceptance process using the Paystack API. It extracts the email and amount from the request body, creates a JSON string with the parameters, and initiates a client request to the Paystack API using the provided options. The API response data is collected and logged and then sent back to the client with a status code of 200.

💡 If you find yourself using this acceptPayment function over and over for different projects, consider using an open-source toolchain like Bit to extract it into a component which you can test, document, and version independently and then share across multiple projects with a simple bit import your.username/acceptPaymentComponent command.

Learn more:

NOTE: All calls to Paystack from your server are authenticated by sending your secret key in the Authorization header in this format Authorization: Bearer sk_live_bl3xyzbl3xyz. Also, Do not commit your secret keys to git, or use them in client-side code.

8. Next, we need to create our route handlers. Create a routes folder in the root directory, and inside that folder, create a routes.js file, then add the following codes.

// routes/routes.js file

const express = require('express');
const router = express.Router();
const initializePayment = require('../Controllers/controllers'); // import the controller


router.post('/acceptpayment', initializePayment.acceptPayment);

module.exports = router

You can see how we have adhered to the fundamental principle of building each system in a separate module, with each module having a specific and independent responsibility. This is just one example of the many good practices to follow when building a Node.js project.

8. Next, to run and test the application, simply use the command “node index” in the terminal. This will start the server and allow you to test the functionality of the application on this Url: http://localhost:3001/acceptpayment

9. Go to your POSTMAN and make a POST request to this url: http://localhost:3001/acceptpayment. below is the Json sample request

{
"email": "johndoe@gmail.com",
"amount": 500000
}SAm

Sample response

{
"status": true,
"message": "Authorization URL created",
"data": {
"authorization_url": "https://checkout.paystack.com/0peioxfhpn",
"access_code": "0peioxfhpn",
"reference": "7PVGX8MEk85tgeEpVDtD"
}
}

10. The “authorization_url” obtained from the response will redirect users to the Paystack popup checkout page, where they can securely make the payment.

Paystack popup checkout

Finally, by following these steps, you will be able to seamlessly integrate the Paystack API into your Node.js application for accepting payments. For more advanced and detailed functionalities, I recommend referring to the Paystack API Documentation, which provides extensive resources on building exceptional payment experiences. Feel free to explore and utilize the provided source code to enhance your project further. Happy coding!

Build Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--