Callbacks

Handling callbacks

Callbacks are the source of truth for order state. They are delivered at least once, over plain HTTP POST, and you have five seconds to acknowledge — anything slower counts as a failure and triggers a retry.

Last updated 2026-10-24

Collection callback payload

status 2 means paid, 3 means failed. utr is only present on success and may be empty for some channels.

FieldTypeNotes
platform_order_nostringPlatform order number
merchant_order_nostringYour order number
amountstringOrder amount as string, e.g. "1000.00"
actual_amountstringAmount actually paid
feestringFee, e.g. "30.00"
statusint2 paid, 3 failed
utrstringBank reference, success only
signstringMD5 signature

Verify before you trust

Use the raw received values — do not reformat amount or fee. Formatting "1000" into "1000.00" changes the hash and every callback will fail verification.

php
$data = json_decode(file_get_contents('php://input'), true);

$calc = md5(
  $data['platform_order_no'] .
  $data['merchant_order_no'] .
  $data['amount'] .
  $data['fee'] .
  $data['status'] .
  $key
);

if (!hash_equals($calc, $data['sign'] ?? '')) {
  http_response_code(403);
  exit('SIGN ERROR');
}

// idempotency: platform_order_no is the key
if (alreadyProcessed($data['platform_order_no'])) {
  echo 'SUCCESS';
  exit;
}

if ((int)$data['status'] === 2) {
  markOrderPaid($data['merchant_order_no'], $data['actual_amount'], $data['utr'] ?? '');
}

echo 'SUCCESS';

Rules that prevent most integration bugs

Reply within five seconds. Do the heavy work asynchronously — persist the payload, reply SUCCESS, then process.

Be idempotent. The same order may be delivered more than once; key your writes on platform_order_no.

Never trust the body without the signature. A forged callback that passes your handler is a free order.

Do not rely on callback order. A payout reversal can arrive after a success if it was re-delivered late — always reconcile against the latest state query.

FAQ

What if my endpoint is down?

Delivery is retried. Reconciling with collectStatus or payoutStatus closes any gap without waiting for a retry.

Do you sign with HMAC?

No — plain MD5 over concatenated values plus your secret key. Bind the callback URL to HTTPS and verify the signature; that is the security model.

← PayoutQueries →

Telegram

Need test credentials, or stuck on the integration? Message us directly.

@GGR100