Flows

Cashier Payment

End-to-end guide for redirecting users to the wallet cashier flow.

Overview

This flow covers the standard cashier payment experience where the Mini Program hands off to the wallet hosted cashier page. Use POST /v1/payments/pay (cashier mode) to create the order, then open the cashier via my.tradePay.

Cashier payment is part of the pay API, which supports both cashier and agreement payment scenarios.

Flow Steps

  1. The Mini Program calls this my.getAuthCode JSAPI with specific scopes(USER_ID) to request an authorization code.
  2. The E-wallet App service calls authorization service to processes the authorization information.
  3. The E-wallet backend verifies the authorization information, generates the authCode and returns.
  4. The E-wallet App service returns the authCode to the Mini Program.
  5. The Mini Program sends the authCode to the merchant backend.
  6. The merchant backend calls the applyToken API with authCode to apply the accessToken.
  7. The E-Wallet backend returns accessToken information to the merchant backend, such as customerId, accessToken, refreshToken, etc.
  8. The Mini Program creates an order with customerId.
  9. The merchant backend calls the payment API to initiate payment flow, including customerId as referenceBuyerId, paymentNotifyUrl(optional), etc.
  10. The E-Wallet backend returns payment detail information the merchant backend, such as redirectionUrl.
  11. The merchant backend passes the payment detail information to the Mini Program.
  12. The Mini Program calls the my.tradePay JSAPI with redirectionUrl to conduct the payment.
  13. The E-Wallet App Service displays the cashier page with order information, such as amount, order details, etc.
  14. The user confirms the payment in the cashier page.
  15. The E-Wallet App Service calls payment service and execute the payment process.
  16. When the payment reaches the final status, the E-wallet backend returns the payment result to the Mini Program (Step 18).
  17. Also the E-wallet backend notifies the merchant backend of the payment result with paymentNotifyUrl provided in Step 10(Step 19).
  18. Finally, E-wallet backend notifies the user of the payment result via SMS/Email/Inbox message (Step 20).

Request Structure

POST /v1/payments/pay
Content-Type: application/json

{
  "productCode": "51051000101000000011",
  "paymentRequestId": "UDQzzvxwvyvUDxGqhMHUlIBpGkydOQC6",
  "paymentAmount": {
    "currency": "IQD",
    "value": "100000"
  },
  "order": {
    "orderDescription": "order_description",
    "buyer": {
      "referenceBuyerId": "216610000000003660xxxx"
    }
  },
  "paymentExpiryTime": "2024-01-18T16:10:36+03:00",
  "paymentNotifyUrl": "https://www.merchant.com/paymentNotifyxxxx",
  "paymentRedirectUrl": "https://www.merchant.com/order/return",
  "voidNotifyUrl": "https://www.merchant.com/payment/void",
  "extendInfo": "{\"memo\":\"channel=miniapp\"}"
}

Field Notes

  • productCode: cashier product identifier defined by the wallet (e.g., "51051000101000000011").
  • paymentRequestId: unique ID per payment (max 64 characters) for idempotence.
  • paymentAmount.value: value in IQD fils; ensure it matches the order total.
  • order.buyer.referenceBuyerId: must match the customerId returned by applyToken.
  • paymentExpiryTime: optional ISO 8601 timestamp to auto-close the order.
  • paymentNotifyUrl: HTTPS endpoint to receive asynchronous payment results.
  • paymentRedirectUrl: optional URL for post-payment completion/cancel page.
  • voidNotifyUrl: optional endpoint for void notifications.
  • extendInfo: JSON string for custom metadata (max 2048 chars).

Response

{
  "result": {
    "resultCode": "ACCEPT",
    "resultStatus": "A",
    "resultMessage": "accept"
  },
  "paymentId": "2023120611121280010016600900000xxxx",
  "redirectActionForm": {
    "redirectionUrl": "https://www.wallet.com/cashier?orderId=xxxxxxx"
  }
}

Response Interpretation

  • result.resultStatus = A: payment accepted; redirect the user using redirectActionForm.redirectionUrl via my.tradePay.
  • result.resultStatus = S: payment completed instantly; update order status and wait for notifications.
  • result.resultStatus = U: wallet returned an unknown status; do not mark success/failure yet—wait for notification or poll /v1/payments/inquiryPayment.
  • result.resultStatus = F: payment failed. Inspect result.resultCode (e.g., USER_BALANCE_NOT_ENOUGH, RISK_REJECT, REPEAT_REQ_INCONSISTENT) and provide remediation to the user.

Common Error Codes

StatusresultCodeDescriptionRecommended Action
UPAYMENT_IN_PROCESSPayment still processing.Wait for wallet notification or poll /v1/payments/inquiryPayment.
FPAYMENT_AMOUNT_EXCEED_LIMITAmount exceeds wallet limit.Send smaller amount or request higher limit.
FUSER_BALANCE_NOT_ENOUGHUser’s wallet balance insufficient.Prompt user to top up balance.
FUSER_STATUS_ABNORMALUser account restricted.Instruct user to resolve with wallet support.
FPARTNER_STATUS_ABNORMALMerchant account restricted.Resolve merchant compliance issues before retrying.
FRISK_REJECTBlocked by risk engine.Request user to try later or different channel.
FCURRENCY_NOT_SUPPORTUnsupported currency.Use IQD or permitted currency.
FINVALID_ACCESS_TOKENAccess token invalid/expired.Re-run applyToken.
FREPEAT_REQ_INCONSISTENTDuplicate paymentRequestId with different payload.Reuse original payload or change paymentRequestId.