# DZPay Payment Gateway — API Documentation

**Base URL:** `https://pay.dzhost.shop`

DZPay is a personal payment gateway for Bangladesh. Other websites accept
bKash / Nagad / Rocket / Upay / Cellfin / mCash / Bangla QR payments through
this gateway with one simple API: create a payment, redirect the customer to
the hosted payment page, and receive an instant webhook when the money is
verified.

The API is Quickpaybd-compatible — the same contract used by common WHMCS
modules and the `payment-gateway` integration of the Rin Topup website.

---

## 1. Authentication

Every merchant API call requires your API key in the `API-KEY` header.
Get the key from **Dashboard → API** (login at `https://pay.dzhost.shop/login`).

```
API-KEY: YOUR_API_KEY
```

---

## 2. Create a Payment

`POST /api/payment/create`

### Request headers
| Header | Value |
|---|---|
| Content-Type | application/json |
| API-KEY | YOUR_API_KEY |

### Request body
| Field | Type | Required | Description |
|---|---|---|---|
| `cus_name` | string | optional | Customer name — shown as "Invoice To" on the payment page |
| `cus_email` | string | optional | Customer email |
| `amount` | number | **yes** | Amount in Taka (integer). Must be ≥ gateway minimum (default ৳20) |
| `webhook_url` | url | recommended | The gateway POSTs here when the payment completes |
| `success_url` | url | recommended | Browser redirect after successful payment |
| `cancel_url` | url | optional | Browser redirect when the payment is canceled/expired |
| `cus_orderid` | string | optional | Your own order reference (echoed in verify data) |

### Response — success (200)
```json
{
  "status": true,
  "payment_url": "https://pay.dzhost.shop/payment/K7QM2XZ",
  "txn_id": "K7QM2XZ",
  "amount": 500,
  "expires_at": "2026-10-19T10:30:00.000Z"
}
```

### Response — error
```json
{ "status": false, "message": "Invalid API key." }        // 401
{ "status": false, "message": "amount is required …" }    // 400
```

Redirect the customer to `payment_url` (HTTP 302 or `window.location.href`).

### cURL example
```bash
curl -X POST https://pay.dzhost.shop/api/payment/create \
  -H "Content-Type: application/json" \
  -H "API-KEY: YOUR_API_KEY" \
  -d '{
    "cus_name": "Rahim Uddin",
    "cus_email": "rahim@example.com",
    "amount": 500,
    "webhook_url": "https://yoursite.com/api/payment/callback?payment=ORDER-123",
    "success_url": "https://yoursite.com/payment/success",
    "cancel_url": "https://yoursite.com/payment/cancel"
  }'
```

---

## 3. Hosted Payment Page Flow

1. Your site calls `/api/payment/create` → redirect the customer to `payment_url`.
2. The customer selects a method (bKash / Nagad / Rocket / …) and presses **PAY**.
3. DZPay shows your receiver number + Bengali instructions; the customer sends
   money from their mobile-banking app and submits the TrxID.
4. Verification is automatic: the SMS Reader Android app forwards the merchant
   SIM's credit SMS, and DZPay matches the TrxID / amount to the pending payment.
5. On completion DZPay:
   - **POSTs the webhook** to your `webhook_url`, and
   - **redirects the browser** to `success_url` with
     `?payment=<txn_id>&status=success&transaction_id=<trx>`.
6. On expiry/cancel the browser is redirected to `cancel_url` with
   `?payment=<txn_id>&status=cancel`.

---

## 4. Payment Webhook

When a payment completes, the gateway POSTs to your `webhook_url`. Parameters
are appended to the query string **and** sent as an `application/x-www-form-urlencoded`
body (10s timeout, one automatic attempt — re-send from Dashboard → Payments
if your server missed it).

| Param | Meaning |
|---|---|
| `payment` | DZPay txn id (e.g. `K7QM2XZ`) |
| `transactionId` / `transaction_id` | The customer's Send Money TrxID |
| `paymentAmount` | Amount in Taka |
| `paymentFee` | `0` |
| `status` | `COMPLETED` |
| `method` | `bkash` · `nagad` · `rocket` · `upay` · `cellfin` · `mcash` · `banglaqr` |

**Security rule:** never trust callback parameters alone — always confirm with
the Verify API (section 5) before delivering your product.

---

## 5. Verify a Transaction

`POST /api/payment/verify` — server-to-server confirmation.
Pass either the gateway txn id (`K7QM2XZ`) or the customer's TrxID.

```bash
curl -X POST https://pay.dzhost.shop/api/payment/verify \
  -H "Content-Type: application/json" \
  -H "API-KEY: YOUR_API_KEY" \
  -d '{ "transaction_id": "K7QM2XZ" }'
```

### Response (completed)
```json
{
  "status": "COMPLETED",
  "transaction_id": "8F7A2B9C1D",
  "txn_id": "K7QM2XZ",
  "amount": 500,
  "method": "bkash",
  "sender_number": "01712345678",
  "cus_name": "Rahim Uddin",
  "cus_email": "rahim@example.com",
  "order_id": "",
  "completed_at": "2026-10-19T10:21:44.000Z",
  "created_at": "2026-10-19T10:15:02.000Z"
}
```

A top-level `status` of `COMPLETED` (also accepted: `SUCCESS`, `PAID`, `DONE`)
means the money is confirmed. Other values: `PENDING`, `FAILED`, `CANCELED`.

---

## 6. Payment Statuses

| Status | Meaning |
|---|---|
| `PENDING` | Created, waiting for the customer to pay / be verified |
| `COMPLETED` | Money confirmed — webhook fired, browser redirected to success_url |
| `FAILED` | Rejected by the admin or verification failed |
| `CANCELED` | Expired (unpaid after the expiry window, default 15 min) or canceled |

---

## 7. PHP Integration Example

```php
<?php
$apiKey = "YOUR_API_KEY";

$ch = curl_init("https://pay.dzhost.shop/api/payment/create");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    "Content-Type: application/json",
    "API-KEY: $apiKey",
  ],
  CURLOPT_POSTFIELDS => json_encode([
    "cus_name"    => $customerName,
    "cus_email"   => $customerEmail,
    "amount"      => (int) $amount,
    "webhook_url" => "https://yoursite.com/api/payment/callback?payment=" . $orderId,
    "success_url" => "https://yoursite.com/payment/success",
    "cancel_url"  => "https://yoursite.com/payment/cancel",
  ]),
]);
$res = json_decode(curl_exec($ch), true);
curl_close($ch);

if (!empty($res["status"])) {
  header("Location: " . $res["payment_url"]);
  exit;
}
echo "Payment init failed: " . ($res["message"] ?? "unknown error");
```

### Webhook receiver (PHP sketch)

```php
<?php
// https://yoursite.com/api/payment/callback?payment=...&transactionId=...
$txnId  = $_GET['transactionId'] ?? $_POST['transactionId'] ?? '';
$amount = $_GET['paymentAmount'] ?? $_POST['paymentAmount'] ?? 0;

// Confirm server-to-server before delivering anything:
$ch = curl_init("https://pay.dzhost.shop/api/payment/verify");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ["Content-Type: application/json", "API-KEY: YOUR_API_KEY"],
  CURLOPT_POSTFIELDS => json_encode(["transaction_id" => $txnId]),
]);
$verify = json_decode(curl_exec($ch), true);

if (($verify["status"] ?? "") === "COMPLETED") {
  // mark order $orderId paid in your database, deliver the product …
}
```

## 8. Node.js Integration Example

```js
const res = await fetch("https://pay.dzhost.shop/api/payment/create", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "API-KEY": process.env.DZPAY_API_KEY,
  },
  body: JSON.stringify({
    cus_name: customerName,
    cus_email: customerEmail,
    amount: 500,
    webhook_url: "https://yoursite.com/api/payment/callback?payment=" + orderId,
    success_url: "https://yoursite.com/payment/success",
    cancel_url: "https://yoursite.com/payment/cancel",
  }),
});
const data = await res.json();
if (data.status === true) {
  // Redirect the customer to the hosted payment page
  window.location.href = data.payment_url;
}
```

---

## 9. Errors & Limits

| HTTP | Meaning |
|---|---|
| 401 | Missing / invalid `API-KEY` header |
| 400 | Invalid amount or URLs (amount ≥ minimum; absolute http(s) URLs) |
| 404 | Transaction not found (verify) |
| 429 | Rate limit — max 30 create calls per minute per IP |

---

## 10. Auto-Verification (SMS Reader App)

Install the **SMS Reader** Android app on the phone holding the merchant SIM:

1. Server URL: `https://pay.dzhost.shop`
2. Username / Password: your gateway panel credentials (download the APK
   from the Dashboard → **SMS App** tab)
3. Press **Login and Test** then **START**.

Every credit SMS on that SIM (bKash / Nagad / Rocket / Upay / Cellfin /
mCash) is pushed to the gateway and completes matching payments automatically:
exact TrxID matches first, then the oldest pending payment of the same method
and amount within the last 15 minutes.
