Create invoices & verify status
This documentation covers the essential Create Invoice and Verify Invoice endpoints for merchant and partner developers. Follow the instructions to test transactions securely.
Overview
ZayanPay exposes two primary external REST APIs for sandbox and production testing: Create Invoice and Verify Invoice.
How to get your API key
- Login to your ZayanPay dashboard.
- Navigate to the Main Menu.
- Select Brands / API Keys.
- Copy your Brand Key / API Key.
sandbox_test_8f4c9a2e7b31
Authentication
Every request must include your API key to authenticate securely with our verification cluster.
| Method | Value | Notes |
|---|---|---|
| Preferred header | zayan-api-key: sandbox_test_8f4c9a2e7b31 |
Recommended |
| Also supported header | zayanpay-api-key: sandbox_test_8f4c9a2e7b31 |
Supported |
| Query parameter | ?apikey=sandbox_test_8f4c9a2e7b31 |
Supported |
Endpoints
| Name | Method | Path | Purpose |
|---|---|---|---|
| Create Invoice | POST | /v1/payment/create |
Create a hosted invoice and return payment_url. |
| Verify Invoice | POST | /v1/payment/verify |
Verify invoice payment status and TrxID authenticity. |
Common rules
-
Set
Content-Typetoapplication/json. - Every request must include an API key.
- Only active merchant brands are allowed.
-
redirect_urldomain must match the merchant registered website domain. -
amountmust be greater than 0 BDT. -
metadatamust be valid JSON object and stay within 1 KB.
Laravel Full Website Integration Guide
Laravel 9, 10, 11+Follow this step-by-step guide to connect your Laravel website with ZayanPay. This architecture uses native Laravel HTTP Client, handles customer checkout redirect, verifies transaction authenticity upon return, and receives instant asynchronous background Webhook (IPN) notifications.
Configure Environment (.env)
Add your ZayanPay credentials to your Laravel project's .env file. Get your live API key from Merchant Portal → Developer API Keys.
# ZayanPay Automated Gateway Configuration
ZAYANPAY_BASE_URL=https://zayanpay.com
ZAYANPAY_API_KEY=zp_live_your_secret_api_key
ZAYANPAY_CURRENCY=BDT
Create Service Class (app/Services/ZayanPayService.php)
Create a dedicated service to encapsulate communication with the ZayanPay API using Laravel's built-in Http client.
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use RuntimeException;
class ZayanPayService
{
protected string $baseUrl;
protected string $apiKey;
public function __construct()
{
$this->baseUrl = rtrim(env('ZAYANPAY_BASE_URL', 'https://zayanpay.com'), '/');
$this->apiKey = (string) env('ZAYANPAY_API_KEY');
}
/**
* Create hosted checkout session and get redirect payment URL.
*/
public function createPayment(
string $name,
string $email,
string $phone,
float $amount,
string $returnUrl,
?string $webhookUrl = null,
array $metadata = []
): array {
$response = Http::timeout(15)
->withHeaders([
'ZAYANPAY-API-KEY' => $this->apiKey,
'Accept' => 'application/json',
])
->post("{$this->baseUrl}/api/checkout/redirect", [
'full_name' => $name,
'email_address' => $email,
'mobile_number' => $phone,
'amount' => (string)$amount,
'currency' => env('ZAYANPAY_CURRENCY', 'BDT'),
'return_url' => $returnUrl,
'webhook_url' => $webhookUrl ?? '--',
'metadata' => $metadata,
]);
if ($response->failed()) {
throw new RuntimeException($response->json('error.message') ?? 'Failed to connect to ZayanPay.');
}
return $response->json(); // Returns ['pp_id' => '...', 'pp_url' => 'http://...', 'status' => 'pending']
}
/**
* Verify payment status and ensure transaction authenticity.
*/
public function verifyPayment(string $ppId): array
{
$response = Http::timeout(10)
->withHeaders([
'ZAYANPAY-API-KEY' => $this->apiKey,
'Accept' => 'application/json',
])
->post("{$this->baseUrl}/api/verify-payment", [
'pp_id' => $ppId,
]);
return $response->json();
}
}
Create Payment Controller (app/Http/Controllers/PaymentController.php)
Handles initiating the checkout, customer redirect return callback, and backend IPN webhook.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\ZayanPayService;
class PaymentController extends Controller
{
protected ZayanPayService $zayanPay;
public function __construct(ZayanPayService $zayanPay)
{
$this->zayanPay = $zayanPay;
}
/**
* 1. Initiate Checkout and redirect customer to bKash/Nagad gateway
*/
public function pay(Request $request)
{
$orderId = 'ORD-' . time();
$amount = (float) $request->input('amount', 500);
try {
$checkout = $this->zayanPay->createPayment(
name: $request->input('name', 'Tanvir Ahmed'),
email: $request->input('email', '[email protected]'),
phone: $request->input('phone', '01712345678'),
amount: $amount,
returnUrl: route('payment.callback'),
webhookUrl: url('/api/payment/webhook'),
metadata: ['order_id' => $orderId]
);
// Store pending order in session or DB
session(['pending_order' => ['order_id' => $orderId, 'pp_id' => $checkout['pp_id']]]);
// Redirect customer directly to ZayanPay hosted payment screen
return redirect()->away($checkout['pp_url']);
} catch (\Throwable $e) {
return back()->with('error', 'Unable to initiate payment: ' . $e->getMessage());
}
}
/**
* 2. Customer Return Callback (handles redirect after payment)
*/
public function callback(Request $request)
{
$trxRef = $request->query('transaction_ref');
$status = $request->query('pp_status');
// Verify transaction authenticity directly with ZayanPay API
$verification = $this->zayanPay->verifyPayment($trxRef);
if (($verification['status'] ?? '') === 'completed' || $status === 'completed') {
$trxId = $verification['transaction_id'] ?? $trxRef;
// TODO: Update your Order model status to 'paid' in DB
// Order::where('order_id', session('pending_order.order_id'))->update(['status' => 'paid', 'trx_id' => $trxId]);
return view('payment.success', compact('trxId'));
}
return redirect('/')->with('error', 'Payment was cancelled or could not be verified.');
}
/**
* 3. Asynchronous IPN Webhook (guaranteed delivery)
*/
public function webhook(Request $request)
{
$payload = $request->all();
if (($payload['status'] ?? '') === 'completed') {
$orderId = $payload['metadata']['order_id'] ?? null;
// TODO: Update Order status to 'paid'
return response()->json(['status' => 'success', 'message' => 'Order fulfilled']);
}
return response()->json(['status' => 'acknowledged']);
}
}
Register Routes (routes/web.php)
Add these routes to your routes/web.php:
use App\Http\Controllers\PaymentController;
// 1. Submit form to create payment and redirect to ZayanPay
Route::post('/payment/checkout', [PaymentController::class, 'pay'])->name('payment.checkout');
// 2. Customer Return URL after paying
Route::get('/payment/callback', [PaymentController::class, 'callback'])->name('payment.callback');
// 3. Instant Payment Notification (IPN / Webhook)
Route::post('/api/payment/webhook', [PaymentController::class, 'webhook'])->name('payment.webhook');
Exclude Webhook Route from CSRF Protection
Because server-to-server webhooks do not have a browser session, exclude the webhook URL from CSRF verification:
->withMiddleware(function (Middleware $middleware): void {
$middleware->validateCsrfTokens(except: [
'api/payment/webhook', // Exclude ZayanPay IPN
]);
})
Customers can now click checkout on your website, pay using bKash, Nagad, or Rocket, and get their purchase fulfilled automatically in real-time with 0% gateway commission.
Checkout Redirect API
Create a hosted checkout invoice session and receive the secure payment URL to redirect your customers for instant payment.
Required headers
Content-Type: application/jsonZAYANPAY-API-KEY: your_merchant_api_key
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
full_name |
string | Yes | Customer full name. |
email_address |
string | Yes | Customer email address. |
mobile_number |
string | Yes | Customer mobile phone number. |
amount |
number | Yes | Invoice amount in BDT (e.g. 500). |
currency |
string | No | Currency code (default BDT). |
return_url |
string | Yes | Customer return URL after payment completion. |
webhook_url |
string | No | Server-to-server IPN webhook notification listener. |
metadata |
object | No | Custom key-value dictionary (e.g. {"order_id": "ORD-1001"}). |
Request examples
curl -X POST "https://zayanpay.com/api/checkout/redirect" \
-H "Content-Type: application/json" \
-H "ZAYANPAY-API-KEY: your_api_key_here" \
-d '{
"full_name": "Tanvir Ahmed",
"email_address": "[email protected]",
"mobile_number": "01712345678",
"amount": "500",
"currency": "BDT",
"return_url": "https://your-site.com/payment/callback",
"webhook_url": "https://your-site.com/api/payment/webhook",
"metadata": {
"order_id": "ORD-1001"
}
}'
Success response (200 OK)
{
"pp_id": "291583772135977897208017178",
"pp_url": "https://zayanpay.com/payment/291583772135977897208017178",
"status": "pending",
"expires_at": "2026-09-16T18:30:00Z"
}
Verify Invoice / Payment Status
Verify the real-time payment status directly from your Laravel or custom backend before fulfilling an order or granting service access.
Required headers
Content-Type: application/jsonZAYANPAY-API-KEY: your_api_key_here
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
pp_id |
string | Yes | Unique Payment Invoice ID returned in callback or checkout response. |
Request examples
curl -X POST "https://zayanpay.com/api/verify-payment" \
-H "Content-Type: application/json" \
-H "ZAYANPAY-API-KEY: your_api_key_here" \
-d '{
"pp_id": "291583772135977897208017178"
}'
{
"status": "completed",
"pp_id": "291583772135977897208017178",
"trx_id": "9J8A7K210L",
"payment_method": "bkash",
"amount": "500.00",
"currency": "BDT",
"customer_mobile": "01712345678"
}
Status values
Always verify the invoice from your backend using this endpoint before fulfilling any order, delivering digital services, or sending a "Received Payment" notification.
Webhook Callback Flow
If webhook_url is sent during invoice creation, ZayanPay will automatically dispatch an asynchronous POST event after a verified payment update.
Webhook payload (JSON Body)
{
"invoice_id": "INV_9F8B27D3",
"status": "true"
}
Query parameter style
https://merchant.com/api/zayanpay/webhook?invoice_id=INV_9F8B27D3&status=true
Recommended merchant flow
Production Checklist
Before deploying to your live environment, verify these final steps to ensure a smooth transition.
Download the full API documentation for offline reference and team sharing.
Apps and Plugins
ZayanPay provides Android apps, WordPress plugins, SDKs, and ready-made modules to help you integrate faster.
ZayanPay Android APK
Official Android notification listener app for nonstop background transaction forwarding.
Download APKWooCommerce Plugin
Turnkey payment gateway plugin with instant checkout verification and order status synchronization.
Download PluginWHMCS Gateway
Automated invoice payment and service activation gateway module for web hosting providers.
Download ModuleSMM Panel Module
Instant automated wallet balance refill for SmartPanel, PerfectPanel, and custom SMM scripts.
Download ModulePHP / Laravel SDK
PSR-4 PHP library and Laravel Service Provider / Facade for checkout creation and IPN validation.
Download SDKAdvanced API
BetaProgrammatic merchant balance inquiry, automated payout triggers, and raw bank SMS event streaming for high-volume enterprise users.
The Advanced API features high-throughput socket connections, custom transaction parsing rules, and multi-SIM balancing. Contact enterprise support at [email protected] or WhatsApp for sandbox access keys.