Payment Gateway API Integration in Pakistan: A Step-by-Step Developer Guide

Payment Gateway API Integration in Pakistan: A Step-by-Step Developer Guide

Integrating a payment gateway API is easier than most developers expect when the gateway is built around a hosted checkout. You never touch payment details, you send one request, and you wait for a signed confirmation. This guide walks through the full ZurvaPay API integration for a Pakistani website or app.

The whole flow in one minute

  1. Your customer clicks pay. You save the order in your database as pending.
  2. Your server sends the order to ZurvaPay and receives a checkout URL.
  3. You redirect the customer to that URL and they pay on a secure, mobile-friendly page.
  4. ZurvaPay sends a signed notification (IPN) to your server. You verify it and mark the order paid.
  5. The customer lands on your success page, which only shows a message.

Everything works over standard HTTPS form posts and returns JSON, so it fits PHP, Laravel, WordPress, Python, Node.js, .NET, Java and Go.

Step 1: get your keys

After your merchant account is approved, open Api Key in your dashboard. You get a public_key, which identifies your business, and a secret_key, which verifies notifications and must stay on your server. Your notification and return URLs must be on the website domain approved for your account. Read the full API documentation for every parameter.

Step 2: create the order in your database

Always save the order before you start the payment, with a unique identifier of up to 20 characters that you never reuse. The identifier is how you will recognise the payment when the notification comes back.

Step 3: initiate the payment

Send a server-side POST request to the initiate endpoint with these fields: public_key, identifier, currency (for example PKR), amount, details, ipn_url, success_url, cancel_url, customer_name and customer_email. You can also pass a site_logo and a checkout_theme of light or dark.

<?php
$identifier = 'ORD' . time() . rand(100, 999);
$ch = curl_init('https://zurvapay.com/payment/initiate');
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_POSTFIELDS => [
    'public_key'     => 'YOUR_PUBLIC_KEY',
    'identifier'     => $identifier,
    'currency'       => 'PKR',
    'amount'         => 500,
    'details'        => 'Order #1001',
    'ipn_url'        => 'https://yourdomain.com/zurvapay/ipn.php',
    'success_url'    => 'https://yourdomain.com/payment/success',
    'cancel_url'     => 'https://yourdomain.com/payment/cancel',
    'customer_name'  => 'John Doe',
    'customer_email' => 'john@mail.com',
  ],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($result['success'] ?? '') === 'ok') {
    header('Location: ' . $result['url']);
    exit;
}
echo 'Payment could not be started: ' . ($result['message'] ?? 'unknown error');

On success you receive a url. Redirect the customer there. Call this endpoint from your server, never from the browser.

Step 4: confirm with the signed IPN

When the payment is confirmed, ZurvaPay posts the result to your ipn_url. This notification is the only trusted confirmation. Verify the signature with your secret key, find your pending order by identifier, check the amount, mark it paid once, and answer HTTP 200. We explain the signature check in detail in our IPN and webhook guide.

The customer return pages

After paying, the customer is sent to your success_url; if they cancel, to your cancel_url. Use these pages only to show a friendly message. Never mark an order as paid because someone visited a URL, since anyone can type it into a browser.

Mistakes to avoid

  • Marking an order paid from the success page instead of the verified IPN.
  • Putting the secret key in browser or mobile app code.
  • Reusing an identifier. A used identifier is rejected.
  • Crediting an order twice when the same notification arrives more than once. Update only where the status is still pending.
  • Using notification URLs on a domain that is not approved for your account.

Go-live checklist

  • Merchant account approved and API keys generated.
  • Domain registered for your account.
  • IPN endpoint answers HTTP 200 quickly and verifies both signatures.
  • Orders are updated with a single atomic update.
  • Run one small real payment, because ZurvaPay processes live payments only.

Frequently asked questions

Is there a test mode?

No. ZurvaPay works with live payments only, so use a small amount for your first test.

Which languages can I use?

Any language that can send an HTTPS form post and read JSON. The documentation has PHP, cURL, Python and Node.js samples.

What if my server is down when the notification is sent?

ZurvaPay retries the notification several times over about six hours. You can also add an optional cron job that checks the status of pending orders.

Can I use it on a mobile app or bot?

Yes. See our guide on accepting payments in apps and bots.

Start integrating

Open a ZurvaPay merchant account or contact us and we will help you get started.

Related guides

Start accepting payments with ZurvaPay

Open a merchant account, connect your website with one API and get notified the moment a customer pays.