Connecting to Test Merchants Encryption Rules (MD5) Transaction Order Placement POST Asynchronous PayIn Notification NOTIFY Payment Order Inquiry POST Payment on Behalf (Transfer) POST Asynchronous Payout Notification NOTIFY Payout Status Inquiry POST Check Account Balance POST Indian Bank Codes SDKs & Code Examples
Developer Hub & API Reference

Connecting with Test Merchants

Welcome to the WatchPay Open Gateway API documentation. This document covers both PayIn (Collection) and PayOut (Disbursement / Transfer on behalf) integrations.

Demo Sandbox Credentials:
• Test Merchant ID (mch_id): 80010001
• Test API Secret Key: e10adc3949ba59abbe56e057f20f883e
• Portal URL: http://localhost/web/login

Gateway API Endpoints

Interface Service Method API Address Description
PayIn (Collection) POST /pay/web Place transaction order, redirect or return JSON payment link
PayOut (Disbursement) POST /pay/transfer Transfer funds to customer bank account or UPI ID
Order Inquiry POST /query/order Query PayIn collection transaction status
Payout Inquiry POST /query/transfer Query payout disbursement status
Balance Inquiry POST /query/balance Check available, total, and frozen merchant balances

Encryption Rules (MD5 Signature)

To ensure transaction security and prevent parameter tampering, all requests and responses must carry an MD5 signature verified against the merchant's private API secret key.

Algorithm Steps

  1. Sort all parameters that need to be signed in ascending order of ASCII code (a-z).
  2. Exclude parameters whose values are null or empty string "".
  3. Exclude the parameter sign and sign_type (or signType).
  4. Concatenate the key-value pairs formatted as key1=val1&key2=val2...
  5. Append &key= followed by your API Secret Key at the end of the string.
  6. Calculate the 32-character lowercase MD5 hash of this string.

Encryption Example

goods_name=test&mch_id=80010001&mch_order_no=2026090412345¬ify_url=http://example.com/notify&order_date=2026-09-04 12:34:56&pay_type=101&trade_amount=100.00&version=1.0&key=e10adc3949ba59abbe56e057f20f883e

Interactive Signature Tester

Test and verify MD5 signature calculations directly in your browser:

Transaction Order Placement (PayIn)

Initiates a payment collection request for UPI, QR, or Netbanking payments.

POST /pay/web
Content-Type: application/x-www-form-urlencoded
Redirect vs JSON:
• If you need JSON data returned synchronously (containing the payInfo URL), include version=1.0.
• If you want the customer to be redirected directly to the cashier page, omit the version parameter.

Request Parameters

Parameter Name Type Required Description
versionVersionStringNFixed value 1.0 to return JSON synchronously.
mch_idMerchant CodeStringYUnique merchant ID allocated by the platform (e.g. 80010001).
notify_urlAsynchronous URLStringYWebhook notification address initiated after payment completion.
page_urlRedirect URLStringNFrontend redirect address after payment.
mch_order_noMerchant Order NoStringYGuaranteed unique order ID generated by merchant system.
channel_code / pay_typeChannel CodeStringYDynamic routing code to select gateway: 101 (WatchPay), 102 (JikPay), 103 (AeroPay), 104 (SunPay), 105 (AllPay), 106 (NikPay).
trade_amountOrder AmountStringYTransaction amount in INR (e.g. 100.00).
order_dateOrder TimeStringYFormat: yyyy-MM-dd HH:mm:ss
bank_codeBank CodeStringNOptional. See Indian Bank Codes for online banking.
goods_nameGoods NameStringYProduct name (no more than 50 bytes).
mch_return_msgPass-through DataStringNCustom parameters returned untouched in callback.
sign_typeSignature MethodStringYFixed value: MD5
signSignatureStringY32-character lowercase MD5 signature.

Synchronous JSON Response (version=1.0)

{
  "respCode": "SUCCESS",
  "tradeMsg": "request success",
  "tradeResult": "1",
  "mchId": "80010001",
  "mchOrderNo": "2026090412345",
  "oriAmount": "100.00",
  "tradeAmount": "100.00",
  "orderDate": "2026-09-04 12:34:56",
  "orderNo": "ORD2026090403150001",
  "payInfo": "http://localhost/pay/uniqueurl?dataIndex=ORD2026090403150001",
  "signType": "MD5",
  "sign": "4ba90c98783a04d2dff2a032148d6d2b"
}

Asynchronous PayIn Notification (Webhook)

After customer payment is confirmed, the platform sends a POST request with application/x-www-form-urlencoded parameters to the merchant's notify_url.

Response Requirement:
Upon successfully processing the notification, your server MUST return the literal string success (lowercase). Any other response will cause the platform to retry up to 8 times.

Notification Parameters

ParameterTypeRequiredDescription
tradeResultStringY1: Payment Successful.
mchIdStringYMerchant ID.
mchOrderNoStringYMerchant's order ID.
oriAmountStringYOriginal order amount uploaded by merchant.
amountStringYActual payment amount.
orderDateStringYOrder timestamp.
orderNoStringYPlatform payment order number.
merRetMsgStringNPass-through parameters sent by merchant.
signTypeStringYMD5
signStringYMD5 signature for notification verification.

Payment on Behalf Order (PayOut / Transfer)

Submits a payout request to disburse funds to a customer's Indian bank account or UPI ID.

POST /pay/transfer
Content-Type: application/x-www-form-urlencoded

Request Parameters

ParameterNameTypeRequiredDescription
mch_idMerchant CodeStringYMerchant ID.
mch_transferIdMerchant Transfer IDStringYUnique serial number for payout.
transfer_amountTransfer AmountStringYAmount to transfer in INR.
apply_dateOrder TimeStringYFormat: yyyy-MM-dd HH:mm:ss
bank_codeBank CodeStringYIDPT0001 (or ABB or UPI).
receive_nameBeneficiary NameStringYAccount holder's name.
receive_accountBeneficiary AccountStringYBank account number or UPI ID.
remarkIFSC / RemarkStringYRequired for India: Bank IFSC code (e.g. HDFC0001234).
back_urlCallback AddressStringNAsynchronous payout notification URL.
sign_typeSignature MethodStringYMD5
signSignatureStringYMD5 signature.

Synchronous JSON Response

{
  "respCode": "SUCCESS",
  "errorMsg": null,
  "signType": "MD5",
  "sign": "53d5cee43aa98c4f91b8b7bc7ea67d90",
  "mchId": "80010001",
  "merTransferId": "TRF_1788472021",
  "transferAmount": "100.00",
  "applyDate": "2026-09-04 03:15:00",
  "tradeNo": "SER2026090403150002",
  "tradeResult": "0"
}

tradeResult codes: 0 = Application received / in progress, 1 = Successful, 2 = Failed.

Asynchronous PayOut Notification

When the payout status changes (funds credited or failed), the platform notifies the merchant's back_url.

Merchant server must respond with string success to stop retries.
{
  "tradeResult": "1",
  "mchId": "80010001",
  "merTransferId": "TRF_1788472021",
  "transferAmount": "100.00",
  "applyDate": "2026-09-04 03:15:00",
  "tradeNo": "SER2026090403150002",
  "signType": "MD5",
  "sign": "d95e221325baaaf16396f323f40b7627"
}

Payout Status Inquiry

Check the status of any payout disbursement if notification is delayed.

POST /query/transfer

Request Parameters

ParameterTypeRequiredDescription
mch_idStringYMerchant ID.
mch_transferIdStringYMerchant's transfer serial number.
sign_typeStringYMD5
signStringYMD5 signature.

Response Example

{
  "mchId": "80010001",
  "mchTransferId": "TRF_1788472021",
  "transferAmount": 100,
  "applyDate": "2026-09-04 03:15:00",
  "respCode": "SUCCESS",
  "tradeResult": 1,
  "tradeNo": "SER2026090403150002",
  "signType": "MD5",
  "sign": "d95e221325baaaf16396f323f40b7627",
  "errorMsg": null
}

PayIn Order Inquiry

Check the status of any PayIn collection transaction.

POST /query/order

Response Example

{
  "respCode": "SUCCESS",
  "tradeResult": "1",
  "mchId": "80010001",
  "mchOrderNo": "WP_TEST_1788472021",
  "tradeAmount": "250.00",
  "orderNo": "ORD202609032347019555",
  "orderDate": "2026-09-04 03:17:01",
  "signType": "MD5",
  "errorMsg": null,
  "sign": "a12498ab0da5bef88e3ba8c46a6b6b76"
}

Check Account Balance

Fetch real-time available funds, total funds, and frozen funds.

POST /query/balance

Response Example

{
  "mchId": "80010001",
  "amount": 50010.00,
  "frozenAmount": 0.00,
  "availableAmount": 50010.00,
  "respCode": "SUCCESS",
  "signType": "MD5",
  "errorMsg": null,
  "sign": "b2c5f26d5bc474279e08faba8dc0348e"
}

Indian Bank Codes Reference

Use these bank codes when initiating online banking or payout transactions.

Bank CodeBank NameShort Name
IDPT0001Canara BankCANARA
IDPT0002DCB BankDCB
IDPT0003Federal BankFED
IDPT0004HDFC BankHDFC
IDPT0005Punjab National BankPNB
IDPT0006Indian BankIDBI
IDPT0007ICICI BankICICI
IDPT0008State Bank of IndiaSBI
IDPT0009Axis BankAXIS
IDPT0010Kotak Mahindra BankKOTAK
UPIDirect UPI / VPA TransferUPI

Integration Code Examples

Copy-pasteable code examples for placing orders and verifying callbacks.

PHP Implementation

<?php
function generateSign($params, $secretKey) {
    ksort($params);
    $pairs = [];
    foreach ($params as $k => $v) {
        if ($k === 'sign' || $k === 'sign_type' || $v === '' || $v === null) continue;
        $pairs[] = $k . '=' . $v;
    }
    return md5(implode('&', $pairs) . '&key=' . $secretKey);
}

// 1. PayIn Order Request
$mchId = '80010001';
$secretKey = 'e10adc3949ba59abbe56e057f20f883e';

$data = [
    'version' => '1.0',
    'mch_id' => $mchId,
    'mch_order_no' => 'ORDER_' . time(),
    'trade_amount' => '500.00',
    'pay_type' => '101',
    'goods_name' => 'Coins',
    'order_date' => date('Y-m-d H:i:s'),
    'notify_url' => 'https://yourdomain.com/payin_webhook.php',
    'sign_type' => 'MD5'
];
$data['sign'] = generateSign($data, $secretKey);

$ch = curl_init('http://localhost/pay/web');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
echo "Payment Link: " . $result['payInfo'];
?>

Python Implementation

import requests
import hashlib
import time
from datetime import datetime

def generate_sign(params, secret_key):
    filtered = {k: str(v) for k, v in params.items() if k not in ['sign', 'sign_type'] and v != ''}
    sorted_pairs = [f"{k}={filtered[k]}" for k in sorted(filtered.keys())]
    query_str = "&".join(sorted_pairs) + f"&key={secret_key}"
    return hashlib.md5(query_str.encode('utf-8')).hexdigest()

params = {
    'version': '1.0',
    'mch_id': '80010001',
    'mch_order_no': f"PY_ORD_{int(time.time())}",
    'trade_amount': '500.00',
    'pay_type': '101',
    'goods_name': 'Subscription',
    'order_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
    'notify_url': 'https://yourdomain.com/webhook',
    'sign_type': 'MD5'
}
params['sign'] = generate_sign(params, 'e10adc3949ba59abbe56e057f20f883e')

res = requests.post('http://localhost/pay/web', data=params)
print("Response:", res.json())

Node.js Implementation

const axios = require('axios');
const crypto = require('crypto');

function generateSign(params, secretKey) {
  const filteredKeys = Object.keys(params)
    .filter(k => k !== 'sign' && k !== 'sign_type' && params[k] !== '' && params[k] !== null)
    .sort();
  const queryStr = filteredKeys.map(k => `${k}=${params[k]}`).join('&') + `&key=${secretKey}`;
  return crypto.createHash('md5').update(queryStr, 'utf8').digest('hex');
}

const payload = {
  version: '1.0',
  mch_id: '80010001',
  mch_order_no: 'NODE_' + Date.now(),
  trade_amount: '300.00',
  pay_type: '101',
  goods_name: 'Diamonds',
  order_date: new Date().toISOString().replace('T', ' ').substring(0, 19),
  notify_url: 'https://yourdomain.com/webhook',
  sign_type: 'MD5'
};
payload.sign = generateSign(payload, 'e10adc3949ba59abbe56e057f20f883e');

axios.post('http://localhost/pay/web', new URLSearchParams(payload))
  .then(res => console.log('Payment URL:', res.data.payInfo));