Payment Callback Specification
Payment Callback Guide#
1.
TrustPay sends a signed JSON callback to the notify_url set when the merchant submitted the order.
3.
For virtual-card issuance and top-up callbacks, see the Credit Card Issuance chapter.
5.
This document covers payment and refund lifecycle callbacks only.
Request#
Content-Type: application/json
URL: the notify_url submitted with the order
Success Response#
The merchant should return HTTP 200. Any non-200 response (including 400/500) or a timeout is treated as failure and retried.| Item | Rule |
|---|
| Success | HTTP 200 only |
| Max attempts | 3 (initial send + up to 2 retries) |
| Interval | Exponential backoff, about 60s → 120s (capped at 1h) |
Payment Notification Types#
| type | Meaning | Primary field |
|---|
0 | Payin | numeric status |
1 | Payout | numeric status |
2 | Refund | numeric refund_status |
Common Fields#
| Field | Type | Required | Description |
|---|
type | integer | Yes | 0 = payin, 1 = payout, 2 = refund |
merchant_id | integer | Yes | TrustPay merchant ID |
order_no | string | Yes | Merchant order number |
order_amount | number | Yes | Order amount |
status | integer | Payment callbacks only | Order status; see Enums |
reason | string | Yes | Result or failure reason; may be empty |
sign | string | Yes | MD5 lowercase hex signature |
Amount Fields#
| Field | Type | Required | Description |
|---|
order_amount | number | Yes | Order amount |
paid_amount | number | No | Actual paid amount |
balance_amount | number | No | Settlement / balance-change amount (see each type) |
refund_amount | number | No | Refund amount (see Refund Fields) |
fee | number | No | Fee |
Refund Fields#
| Field | Type | Required | Description |
|---|
merchant_refund_no | string | No | Merchant refund number for this refund only |
refund_status | int64 | No | 1 processing / 2 success / 3 failed / 4 rollback / 5 accounting conflict. Use this field to determine the refund result. |
Amounts are JSON numbers; serialization may omit trailing zeros. When verifying the signature, use the values parsed from the callback body. Do not round or reformat amounts first.Callback Type Examples#
1. Payin (type = 0)#
Field rules#
| Scenario | status | paid_amount | balance_amount | fee | pay_time |
|---|
| Failed / timed out | 3 / 4 | omitted | omitted | omitted | omitted |
| Success (not refunded) | e.g. 5 / 6 | present | paid_amount - fee | present | present (if unsettled and pay_time is missing, current UTC may be used) |
Example (payin, unsettled)#
{
"type": 0,
"merchant_id": 8820250900009,
"order_no": "MCH-PAYIN-20260513-001",
"order_amount": 500.00,
"paid_amount": 500.00,
"balance_amount": 492.50,
"fee": 7.50,
"status": 5,
"reason": "payment received",
"pay_time": "2026-05-13T08:30:00Z",
"sign": "..."
}
2. Payout (type = 1)#
Field rules#
| Scenario | paid_amount | balance_amount |
|---|
| Failed / timed out | omitted | omitted |
| Other | order.paid_amount | paid_amount + fee (payout convention) |
Example#
{
"type": 1,
"merchant_id": 8820250900009,
"order_no": "MCH-PAYOUT-20260513-001",
"order_amount": 1000.00,
"paid_amount": 1000.00,
"balance_amount": 1003.00,
"fee": 3.00,
"status": 2,
"reason": "payout success",
"pay_time": "2026-05-13T09:00:00Z",
"sign": "..."
}
3. Refund (type = 2)#
Field rules#
| Field | Rule |
|---|
type | Always 2 |
order_no | Original payment merchant order number (no extra payment_order_no) |
merchant_refund_no | Merchant refund number for this refund (present on the normal path; may be omitted if no matching refund record is found) |
refund_status | Determines the refund result; see the table below |
refund_amount | Processing / failed: amount of this refund; success (automatic path): usually the cumulative refunded amount on the original payment |
status | Order-side display: processing 9; full success 7; partial success 8; failed = restored original payment status (e.g. 5 / 6 / 17), not always 3 |
paid_amount / balance_amount / fee / pay_time | All omitted |
Enum values#
refund_status | Meaning |
|---|
1 | processing |
2 | success |
3 | failed |
4 | rollback |
5 | accounting_conflict |
Examples#
{
"type": 2,
"merchant_id": 8820250900009,
"order_no": "TPC_PAY_202508130001",
"order_amount": 20.00,
"refund_amount": 20.00,
"merchant_refund_no": "TPC_REFUND_202508130001",
"refund_status": 1,
"status": 9,
"reason": "refund processing",
"sign": "..."
}
{
"type": 2,
"merchant_id": 8820250900009,
"order_no": "TPC_PAY_202508130001",
"order_amount": 20.00,
"refund_amount": 20.00,
"merchant_refund_no": "TPC_REFUND_202508130001",
"refund_status": 2,
"status": 7,
"reason": "refund completed",
"sign": "..."
}
{
"type": 2,
"merchant_id": 8820250900009,
"order_no": "TPC_PAY_202508130001",
"order_amount": 100.00,
"refund_amount": 30.00,
"merchant_refund_no": "TPC_REFUND_202508130002",
"refund_status": 2,
"status": 8,
"reason": "refund completed",
"sign": "..."
}
{
"type": 2,
"merchant_id": 8820250900009,
"order_no": "TPC_PAY_202508130001",
"order_amount": 20.00,
"refund_amount": 20.00,
"merchant_refund_no": "TPC_REFUND_202508130001",
"refund_status": 3,
"status": 5,
"reason": "channel rejected refund",
"sign": "..."
}
Recommended Decision Logic (Conservative)#
if type == 2:
refund_status=1 → keep processing
refund_status=2 and merchant_refund_no plus amount match this refund → success
refund_status=3 → failed
status ∈ {5, 6, 17} only, without refund_status=3 → do not auto-fail
If the create API returns 7/8 → do not treat as success by itself; wait for webhook / query cross-check
Signature Verification#
Verify sign before processing any callback. Every non-empty field in the actual payload is included in the signature.For the string to sign, examples, and JavaScript / Go reference implementations, see Signature Calculation.Security Checklist#
Accept callbacks over HTTPS only.
Verify the signature before updating business state.
Confirm merchant_id belongs to the current recipient.
Run an idempotency check before applying a payment or refund change.
Do not log the merchant secret or the full unsigned string.
Keep the raw callback body for audit; mask any card data.
Modified at 2026-08-29 06:35:09