Paystack Integration Made Easy: A Beginner's Tutorial for Your First Ecommerce App
Receive payments in your app seamlessly

Every e-commerce app needs a reliable way to accept payments. For developers in Africa, Paystack is a fantastic solution. In this article, I'll show you exactly how I integrated it into my project. To make this article platform agnostic, I would not be talking about Node.js or Nest.js or Golang, just Paystack and the concepts, as it is all the same across server-side languages.
1. Paystack Dashboard
Before you can use any service, you need to create an account with them; Paystack is no different. You can create one here.
Take note of the following requirements:
Your test secret key
Callback Url
Paystack Base Url
Webhook Url
2. Server Endpoints
Whatever backend language you use, be it Node, Golang, or Java, for the simplest start, you would need an initialize transaction endpoint and a verify transaction endpoint on your app’s server. Basically, your frontend (say a user clicks on the checkout button) tells your app’s server that a payment/order is about to be made. It then tells the Paystack server (via a POST request) that your app wants to initiate a transaction using this URL: It takes 2 fields in the request body, the customer’s email and the amount.
"https://api.paystack.co/transaction/initialize"
// Req Body
{
"email": "osasgames@gmail.com",
"amount": "20000" //in kobo, so that is 200 naira.
}
A Sample from my own APP (Nest.JS)
async initializeTransaction(email: string, amount: number) {
try {
const response = await fetch(
`${this.configService.get("PAYSTACK_BASE_URL")}/transaction/initialize`,
{
method: "POST",
headers: {
Authorization: `Bearer ${this.configService.get("TEST_SECRET_KEY")}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
email,
amount: amount * 100, // Paystack expects amount in kobo
callback_url: `${this.configService.get("REMIX_APP_URL")}/payments/callback`,
}),
}
);
const data = await response.json();
console.log("Transaction initialized:", data);
return data;
} catch (error) {
throw new HttpException(error.response?.data || "Paystack error", 400);
}
}
Notice the TEST_SECRET_KEY, callback_url, and “Paystack expects the amount in kobo” comment and my use of env variables. Use env variables for your API keys or secrets.
A crucial principle in software development is to never use floating-point numbers for money. To ensure precision, Paystack works with integers representing the smallest currency unit in Nigeria—in this case, kobo. For those in the USA, cents.
The TEST_SECRET_KEY is what Paystack uses to tell which of its merchants is using its service, so without it, the call wouldn’t work.
The callback_url passed along with the req body. This URL is where the frontend should redirect on a successful payment on Paystack. More on this later on.
A Sample JSON Response:
{
"status": true,
"message": "Authorization URL created",
"data": {
"authorization_url": "https://checkout.paystack.com/obwa46io3rsfm9t",
"access_code": "obwa46io3rsfm9t",
"reference": "253952dumk"
}
}
3. Checkout Experience (Your FrontEnd).
From the data returned by Paystack, the authorization_url and reference are key to completing the transaction. While Paystack offers a feature-rich inline popup library that uses the access_code, I opted for a more direct approach: using the authorization_url.
This URL leads directly to the standard Paystack checkout page. My implementation simply redirects the user to this link, presenting them with the payment interface without requiring the integration of an additional JavaScript library. You can explore the popup method in their official documentation here.
useEffect(() => {
// Only proceed if we have fetcher.data and it has a data property
if (!fetcher.data?.data?.data) {
// console.log("No nested data yet");
return;
}
const authUrl = fetcher.data.data.data.authorization_url;
const isNotSubmitting = fetcher.state !== "submitting";
if (authUrl && isNotSubmitting) {
console.log("Redirecting to:", authUrl);
try {
window.location.href = authUrl;
} catch (error) {
console.error("Redirect failed:", error);
// Fallback: open in new tab
window.open(authUrl, '_self');
}
}
}, [fetcher.state, fetcher.data?.data?.data]);
While the full component is outside the scope of this article, the key piece of logic is window.location.href = authUrl;. This is the standard browser command that programmatically navigates the user to a new page.
We place this inside a useEffect hook to control when the redirect happens. The hook is set up to listen for our data from the server and, as soon as the authUrl is available, useEffect triggers the redirect.
4. Verify Transaction
After a customer attempts a payment, Paystack communicates the result in two distinct ways: one for your frontend application and one for your backend server.
Callback URL (For the Frontend): The Callback URL page is where your frontend gets the final confirmation from your backend. The process involves these three key steps:
Extract the Transaction Reference: Paystack automatically adds a unique
referenceto the Callback URL as a query parameter (e.g.,.../callback?reference=xyz123). The first task is to capture this value. While I used hooks from React Router, any frontend technology has a standard way to read URL parameters.Verify with Your Backend: Next, send this
referencein an API call to your backend's verification endpoint (e.g.,/api/payment/verify). This server-side check is crucial for security, as the frontend should never be trusted to confirm a payment on its own.Display the Result: Finally, use the response from your backend to show the user the appropriate page. If successful, display a "Thank you for your purchase!" message with order details and delivery information. If it failed, show an error message.
Webhook URL (For the Backend): This is the server-to-server part. It's a private URL that Paystack sends a secure, automated message to, confirming the transaction's status. This is the most reliable method for your backend to verify a payment and update your database (like decrementing stock quantity and updating the status for the order) and also send receipt emails.
Important Note: You can set a default callback URL on your Paystack dashboard, but any URL you provide in your API request will always override it.
In Summary
I detailed how to integrated Paystack, a robust payment solution ideal for developers in Africa, into any e-commerce app. The process involves setting up a Paystack account, creating server endpoints to initialize and verify transactions, redirecting users to Paystack's checkout via an authorization URL, and finally verifying transactions using backend webhooks and callback URLs. Again, I emphasize using environment variables for security and the importance of precise currency handling. I hope this guide provides a clear, platform-agnostic approach to implementing Paystack's powerful payment system.
