Backend & Gateway Config
src/payment-gateway/*) which in turn talks to 911Pay,
plus an optional "Direct 911Pay API" tab that calls https://api.911pay.asia/nineoneonepay_api/ directly
(see CORS caveat in that tab).
1. Login (obtain JWT)
2. Create Deposit — POST /payment-gateway/deposit
paymentLink — open it to complete the sandbox payment on 911Pay's hosted page, then 911Pay will call your PAY911_CALLBACK_BASE_URL/deposit webhook.3. Create Withdrawal — POST /payment-gateway/withdrawal
requestId — use it below in the Admin Review tab to approve/reject (requires an admin JWT in Config).4. Admin Review & Failed Webhooks
Review withdrawal — PATCH /payment-gateway/admin/withdrawal/:id
Failed webhooks — GET /payment-gateway/admin/failed-webhooks
5. Simulate 911Pay Webhooks
Deposit callback — POST /payment-gateway/webhook/deposit
sha256('ID|CustomerCode|Amount|Status|SecretKey'). Amount must match the exact string format 911Pay uses (xxxx.yy).Payout callback — POST /payment-gateway/webhook/payout
sha256('ID|Amount|Status|SecretKey') (no customer_code).6. Direct 911Pay API (bypasses your backend)
911Pay's API is a plain server-to-server REST API with no CORS headers, so calls made directly
from a browser tab will almost certainly be blocked by the browser (and this form would also expose your
secret_key in browser network traffic). This tab is provided for completeness /
cross-checking the request shape against https://merchant.911pay.asia/Api — if the
"Send" button fails with a network/CORS error, that is expected; use curl/Postman/your backend
instead of a browser for real calls to 911Pay directly.
7. Field Reference (cross-checked against merchant.911pay.asia/Api)
Base URL: https://api.911pay.asia/nineoneonepay_api/ Method: POST, all endpoints Body: multipart/form-data Auth: secret_key field on every request.
POST /create_order/ (deposit)
| Field | Required? | Sent by this repo's client? |
|---|---|---|
| secret_key | always | yes (appended by Pay911ClientService) |
| unique_id | always | yes |
| amount | always | yes |
| return_url | always | yes |
| callback_url | always | yes |
| customer_bank_holder_name | required for INR/THB/TRY/NPR | yes (optional in our DTO — must be supplied for INR flows) |
| customer_bank_acc | required for INR/THB/TRY/NPR | yes (optional in our DTO — must be supplied for INR flows) |
| bank_code | required for BDT/NPR only | not sent — not needed for INR |
| customer_phone_number | required for NPR only | not sent — not needed for INR |
| customer_id / customer_name / customer_surname | required for TRY only | not sent — not needed for INR |
| customer_code | optional | yes |
| customer_email / remark | optional | not currently sent — could be added if needed |
Response fields per docs: customer_code, transaction_id, transaction_date, amount, typefee, totalamount, payment_link, status (SUCCESS|ERROR), message. Our client returns the raw JSON as Pay911CreateOrderResponse (typed for transaction_id/payment_link, rest passthrough).
POST /create_payout/ (withdrawal)
| Field | Required? | Sent by this repo's client? |
|---|---|---|
| secret_key, unique_id, amount, callback_url | always | yes |
| customer_bank_code | always | yes |
| customer_bank_holder_name | always | yes |
| customer_bank_acc | always | yes |
| customer_bank_branch (IFSC) | required for TRY only | yes (optional in our DTO — must be supplied for TRY flows) |
| customer_id / customer_surname | required for TRY only | yes (optional in our DTO — must be supplied for TRY flows) |
| customer_mobile_number | required for NPR only | yes (optional in our DTO — must be supplied for NPR flows) |
Response: payout_id, payout_date, amount, totalamount, status (SUCCESS|ERROR), message.
Deposit callback (webhook)
| Field | Notes |
|---|---|
| id | transaction_id — this repo's DTO reads it as transaction_id, confirm your controller's field name matches what 911Pay actually posts (docs call it id) |
| customer_code, amount, status (success|fail), message, reference_number, bank_time, unique_id, hash | hash = sha256('ID|CustomerCode|Amount|Status|SecretKey') |
Payout callback (webhook)
| Field | Notes |
|---|---|
| id, unique_id, amount, status (success|fail), message, reference_number, bank_time, hash | hash = sha256('ID|Amount|Status|SecretKey') |
Other endpoints
/check_transaction/ (needs transaction_id) → status, transaction_id, customer_code, amount, transaction_date, bank_to, bank_time, reference_number, remark, return_url, callback_url, state (PENDING|SUCCESS|FAILED).
/check_payout/ (needs payout_id) → status, payout_id, amount, withdrawal_date, bank_time, remark, callback_url, state.
/get_balance/ (needs only secret_key) → status, currency, main_wallet, payout_wallet.
⚠ Verify the callback field name discrepancy above (id vs transaction_id/payout_id) against a real sandbox webhook delivery from 911Pay before going live — the docs use id generically for both callback types, so check src/payment-gateway/dto/gateway-deposit-callback.dto.ts and gateway-payout-callback.dto.ts map to whatever key 911Pay actually sends.