RedotPay Connect

Webhook

Payment and refund webhook notifications, signature verification, response rules, and retry policy

1. Overview

When a payment succeeds or a refund is completed, whether it succeeds or fails, RedotPay Connect's system will send a webhook to the merchant’s webhook URL.

Webhooks are sent separately for payment events and refund events.

If a webhook request fails (for example, due to a timeout or an error response), RedotPay Connect automatically retries it according to the retry policy.

Webhooks also require signature verification. The signature will be passed by RedotPay Connect in the request header X-R-Signature during the webhooks.

2. Webhook Mechanism

Webhook TypeDescriptionTrigger Condition
PAYMENTNotifies the merchant of the payment resultSent when a payment succeeds
REFUNDNotifies the merchant of the refund resultSent when a refund succeeds or fails

Each webhook is asynchronous and stateless.

Make sure your system handles it idempotently so retries do not cause duplicate processing.

Signature Verification

To ensure the authenticity and integrity of incoming webhook notifications and prevent forged requests, it is strongly recommended to verify the validity of the X-R-Signature header before processing any business logic.

The verification process involves extracting the signature, timestamp, and key version from the request headers, and validating them using your appKey and RedotPay's public key.

For the complete signature verification steps, code examples in multiple languages, and troubleshooting, please refer to the Verifying RedotPay Callback Notification Signatures section in the Request Signature and Verification Guide.

3. Payment Webhook

Request Example

{
    "outerOrder": "T300088...",
    "preSn": "RAP202601051045558385...",
    "orderCurrency": "USD",
    "billCoin": "USDT",
    "billCurrency": "USDT",
    "outerUid": "T3111...",
    "txId": "PAYH20260105104613401...",
    "rateExtra": 0,
    "actionType": "ACQUIRER_PAY",
    "billAmount": 0.99,
    "orderAmount": 1,
    "orderTime": 1767609970940,
    "merchantId": 3000000...,
    "cryptoAmount": 1,
    "rate": 1,
    "walletName": "redotpay",
    "paymentMethod": "redotpay",
    "paymentDeadline": 1767611755616,
    "sn": "RA20260105104610940923...",
    "paymentTime": 1767609973423,
    "orderStatus": 2,
    "coin": "USDT",
    "clientIp": "13.230.109.247",
    "source": "WEB",
    "subMerchantCode": "STORE_A"
}
FieldTypeRequiredDescription
outerOrderStringYesMerchant’s original order number. DEPRECATED
outerOrderSnStringYesMerchant’s original order number
preSnStringYesPrepayment serial number, used to match previous requests. DEPRECATED
orderSnStringYesPrepayment serial number, used to match previous requests
orderAmountdecimalYesOrder's original amount (up to merchant)
orderCurrencyStringYesOrder's original currency (up to merchant)
cryptoAmountdecimalYesOrder's payment crypto currency amount
cryptoCurrencyStringYesOrder's payment crypto currency
billAmountdecimalYesOrder's settlement amount
billCurrencyStringYesOrder's settlement currency
fiatCurrencyStringYesOrder's payment currency. DEPRECATED
outerUidStringYesExternal user ID or identifier passed when the payment was created
txIdStringYesChannel payment transaction id
rateExtradecimalYesMerchant exchange rate markup
actionTypeStringYesType of payment webhook action. Always "ACQUIRER_PAY" for payment webhooks
orderTimelongYesOrder creation time in milliseconds
merchantIdlongYesMerchant's unique ID
rateStringYesFiat to cryptocurrency exchange rates
walletNameStringYesPayment selection wallet name. DEPRECATED
paymentMethodStringYesPayment selection wallet name
paymentDeadlinelongYesPayment deadline in milliseconds. DEPRECATED
timeExpirelongYesPayment deadline in milliseconds
snStringYesPayment serial number
paymentTimelongYesSuccessful payment completion time (timestamp in milliseconds)
orderStatusintYesPayment status:1= Paying; 2= Success; 3= Payment failed; 4= Payment closed
clientIpStringYesBuyer's terminal ip
sourceStringYesbuyer's source: H5/APP/WEB
subMerchantCodeStringNoPSP sub-merchant business code from payment create. Present when tagged; otherwise null/empty. Not a separate merchant account.

4. Refund Webhook

Request Example

{
    "refundSn": "RE2025121402253023...",
    "merchantRefundSn": "TestRefund20251201...",
    "merchantId": 2135213432...,
    "status": "SUCCESS",
    "completeTime": 1768357531591,
    "outerOrderSn": "test-quick-pay-1768301309...",
    "refundType": "redotpay",
    "createTime": 1768354530000,
    "refundAmount": 0.01001,
    "refundCurrency": "USDT",
    "eventType": "MERCHANT",
    "subMerchantCode": "STORE_A"
}

Field Description

FieldTypeRequiredDescription
merchantRefundSnStringYesRefund serial number sent by the merchant when initiating the refund
refundSnStringYesRefund reference number
statusStringYesRefund result status: REFUNDING、SUCCESS、FAILED
refundOrderAmountdecimalYesAmount of refund order
refundOrderCurrencyStringYesCurrency of refund order
failReasonStringNoExplains why refund order fails
merchantIdlongYesMerchant's unique ID
failReasonStringNoReason the refund failed
completeTimelongYesRefund completion time (timestamp in milliseconds)
outerOrderSnStringYesMerchant’s original payment number related to the refund
eventTypeStringYesType of refund webhook event "MERCHANT"= refund initiated by the merchant "PAY_DUPLICATION"= refund for duplicate payments; "PAY_EXPIRED" = refund for expired payments
refundTypeStringYesRefund channel types (Refund via original payment channel)
refundAmountdecimalYesActual refund amount
refundCurrencyStringYesActual refund currency
addressStringNoRefund wallet address (returned only for Web3 decentralized payments)
subMerchantCodeStringNoPSP sub-merchant business code copied from the original payment. Not accepted on refund create; echoed here when the original order had it.

5. Expected Merchant Response

After your system processes the webhook, your endpoint should return the following JSON response:

Response Example

Success Response
{
    "code": "SUCCESS",
    "requestId": "0195c081-d54e-4569-a657-0f54388fa9ba"
}
Fail Response
{
    "code": "FAIL",
    "requestId": "0d992439-38a7-4674-9e06-19a7602eae2e",
    "msg": "update failed"
}

Response Rules

FieldTypeRequiredDescription
codeStringYes"SUCCESS" or "FAIL"
msgStringNoError message, present only when code is "FAIL"
requestIdStringYesUnique request ID

Retry Policy

ConditionRetry IntervalMax Retries
Non-SUCCESS code response180 seconds3

The webhook is marked as failed after all retry attempts. You can then use the query APIs to manually check the transaction or refund status.

Sandbox testing

Before you verify webhooks in sandbox, complete a test payment on the sandbox checkout. Sandbox QR codes cannot be scanned with the production RedotPay app.

Payment steps: Testing Payments in the Sandbox.

On this page