How to Integrate PawaPay Into Your Web App[NextJs & NodeJs]

Joel Fickson
TechMalawi
3 min readFeb 2, 2024

--

This is a simple tutorial that guides you on how to use PawaPay Payment Gateway on your web app for payments.

Prerequisites

To follow along, make sure you have already registered and gotten your JWT here https://dashboard.sandbox.pawapay.cloud/#/system/api-token.

For this tutorial, I am going to create a very simple 1-page site that will have a pay button. When

Let's Create The FrontEnd

Since we are going to use NextJs, I advise you to go ahead and create a new app. Here are the steps.

mkdir pawapay-tutorial
cd pawapay-tutorial
npx create-next-app@latest frontend

Now go into the frontend folder. Remove everything you have inside `app/page.tsx`. Add the following code.

"use client";
import Image from "next/image";
import {useState} from "react";

interface PurchaseState {
isLoading: boolean;
}

export default function Home() {
const [purchaseState, setIsLoading] = useState<PurchaseState>({ isLoading: false });

const handlePurchase = async () => {
const fakePaymentData = {
depositId: "6a13259e-ff31-452f-844c-e4ce6e9d25dc",
amount: "40000",
};
setIsLoading({ isLoading: true });
const response = await fetch("http://localhost:9000/payments/initiate", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(fakePaymentData),
});

if (response.ok) {
setIsLoading({ isLoading: false });

const paymentResponse = await response.json();
window.location.href = paymentResponse.redirectUrl;
} else {
setIsLoading({ isLoading: false });
alert("Payment Failed");
}
};

return (
<div className="h-screen flex items-center justify-center">
<div className="gap-4 text-white md:w-2/4 p-4 rounded flex-col flex items-center">
<h4 className="text-slate-700 text-2xl">Pawapay Payment Gateway Tutorial</h4>
<p className="text-slate-700"> Buy This Art</p>

<Image
src="https://images.unsplash.com/photo-1599124140547-b4d1e8c39548?q=80&w=4074&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
height={500}
width={500}
alt="Image of a painting"
/>
<button disabled={purchaseState.isLoading} onClick={handlePurchase} className="bg-orange-500 w-32 rounded p-2 hover:bg-orange-200 hover:text-orange-500">
{purchaseState.isLoading ? <span>Processing</span> : <span>Buy Me</span>}
</button>
</div>
</div>
);
}



The code above shows this

The code above will trigger an API call to the backend(which we will create) that will initiate a payment. The call to the backend will return a redirect URL that you need your user to be automatically redirected to.

The Backend

The backend is a NodeJs Express Server that has one file and the following code. I will link the GitHub repo so you don't have to go a whole lot. But let me show you the simple TS code.


import express from 'express';
import axios from "axios";
import cors from 'cors';

const server = express();
server.use(express.json({limit: '50mb'}));

server.use(cors());

server.get('/', (_req, res) => {
res.json({
message: 'Welcome to Payment API 🚀',
error: false,
});
}).post('/payments/initiate', async (req, res) => {
const {depositId, amount} = req.body;//TODO:: Add validation here

if (!depositId || !amount) {
return res.status(400).json({
error: true,
message: 'Invalid request. depositId and amount are required',
});
}



const response = await axios.post(
'https://api.sandbox.pawapay.cloud/v1/widget/sessions',
{
depositId,
amount,
returnUrl: 'https://merchant.com/paymentProcessed', //TODO:: Replace with your own return URL
},
{
headers: {
'Content-Type': 'application/json',
Authorization:
'Bearer JWT_TOKEN_HERE',
},
},
);

const { redirectUrl } = response.data;

return res.status(200).json({
error: false,
redirectUrl,
});

})


server.listen(9000, () => {
console.log('Server is running on port 9000');
});

What we are doing here is exposing a payment endpoint that internally calls PawaPay Sandbox API. This will return a redirectUrl that we get in the frontend and send the user to. There are a couple of improvements you can do in the above code. Keep the secrets in an environment variable file or my favorite Google Secrets Manager.

GitHub Repo

https://github.com/JoelFickson/pawapay-payment-tutorial

--

--

Joel Fickson
TechMalawi

Startup Founder — Part Time Writer — Full Stack Developer.