/v1/payments/void
POST /v1/payments/void
The void
API is used to void a paid order before the payment is captured or the order confirmed by a merchant or payer, and then return money to the payer. There are the following two types of voiding a paid order:
- Partially void: To partially void a paid order will return a part of the payment amount to the payer. It will not change the order status. There is a timeout setting for the remaining payment amount. Once the time is out of the setting, the remaining payment amount will be voided or confirmed automatically.
- Fully void: To fully void an order will close the order automatically.
The timeout setting is available when the remaining payment amount is voided or confirmed automatically if the session timeout is set.
Note: All monetary values in the fields of request and response in their smallest currency units, and for IQD, the smallest unit is fils. Thus, if a transaction amount is 150 IQD, the value will be gaven as 150000.
Message structure
A message consists of a header and body. The following sections are focused on the body structure. For the header structure, see:
Request
Property | Data Type | Required | Description | Example |
voidRequestId | String | Yes | The unique ID of a void request generated by a merchant. Max. length: 64 characters. | "20230101234567890133333xxxx" |
paymentId | String | Yes | The payment ID of the original authorization to be voided. Max. length: 64 characters. | "2023120611121280010016600090000xxxx" |
voidAmount | No | The void payment amount. The voidAmount is mandatory in partial void scenario. The voidAmount is optional in full void scenario. | { "value":"100", "currency":"IQD" } | |
extendInfo | String | No | The extension information that wallets and merchants want to describe. The format shoud be JSON format. Max. length: 2048 characters. | "extendInfo: This is additional information" |
Response
Property | Data Type | Required | Description | Example |
result | Yes | The request result, which contains information such as result status and error codes. | { "resultCode": "SUCCESS", "resultStatus": "S", "resultMessage": "Success." } | |
voidRequestId | String | No | The unique ID of a void request generated by a merchant. Max. length: 64 characters. | "20230101234567890133333xxxx" |
voidId | String | No | The unique ID of a void request generated by the wallet. Max. length: 64 characters. | "2023120611121280170016600090000xxxx" |
Result process logic
In the response, the result.resultStatus
field indicates the result of processing a request. The following table describes each result status:
resultStatus | Description |
S |
It means that the void is successful. The corresponding
|
U | It means that the status of the void is unknown. The corresponding
What needs to note is as follow:
If other response (almost never occur), the merchant/partner should process like U. |
F | It means that the void fails. The corresponding |
Error code
Error codes are usually classified into the following categories:
- Common error codes are common across all mini program's APIs.
- API-specific error codes: are listed in the following table.
resultStatus | resultCode | resultMessage |
F | ORDER_NOT_EXISTS | The order does not exist. |
F | ORDER_STATUS_INVALID | The order status is invalid. |
U | VOID_IN_PROCESS | The void is still under process. |
F | CURRENCY_NOT_SAME | The currency of a user's payment is not the same as the original payment currency. |
F | VOID_AMOUNT_EXCEEDS_AUTH_LIMIT | The total void amount exceeds the limit of the authorized payment amount. |
F | MUTEX_OPERATION_IN_PROCESSING | There is another payment void, confirm, or capture in processing. |
F | ORDER_UNSUPPORTED_OPERATION | The order is not support void. |
F | REPEAT_REQ_INCONSISTENT | Repeated submit, and requests are inconsistent. |
F | PARTNER_NOT_EXIST | The partner does not exist. |
F | USER_NOT_EXISTS | The user does not exist. |
F | USER_STATUS_ABNORMAL | The user status is abnormal. |
F | PARTNER_STATUS_ABNORMAL | The partner status is abnormal. |
Samples
For example, a wallet user authorizes a 1000 IQD to make a hotel reservation, and when the user leaves the hotel, there are still scheduled days left, merchant/partner will call this void API to the wallet to return money to the payer.
- The Mini Program calls this my.getAuthCode JSAPI with specific scopes(USER_ID) to request an authorization code.
- The E-wallet App service calls authorization service to processes the authorization information.
- The E-wallet backend verifies the authorization information, generates the authCode and returns.
- The E-wallet App service returns the authCode to the Mini Program.
- The Mini Program sends the authCode to the merchant backend.
- The merchant backend calls the applyToken API with authCode to apply the accessToken.
- The E-Wallet backend returns accessToken information to the merchant backend, such as customerId, accessToken, refreshToken, etc.
- The Mini Program creates an order with customerId.
- The merchant backend calls the payment API to initialte payment flow, including customerId as referenceBuyerId, paymentNotifyUrl(optional), etc.
- The E-Wallet backend returns payment detail information the merchant backend, such as redirectionUrl.
- The merchant backend passes the payment detail information to the Mini Program.
- The Mini Program calls the my.tradePay JSAPI with redirectionUrl to conduct the payment.
- The E-Wallet App Service displays the cashier page with order information, such as amount, order details, etc.
- The user confirms the payment in the cashier page.
- The E-Wallet App Service calls payment service and execute the payment process.
- When the payment reaches the final status, the E-wallet backend returns the payment result to the Mini Program (Step 18).
- Also the E-wallet backend notifies the merchant backend of the payment result with paymentNotifyUrl provided in Step 10(Step 19).
- Finally, E-wallet backend notifies the user of the payment result via SMS/Email/Inbox message (Step 20).
- After the service or goods has been delivered, the user could confirm void in the Mini Program or the merchant cashier (Step 21).
- The Mini Program sends the void request to merchant backend, and the merchant backend calls the
void
API to refund the money(Step 23). - The E-Wallet backend returns the void result to the merchant backend.
- And the Mini Program displays the void result to the user(Step 26).
- When the E-Wallet backend returns the resultCode as VOID_IN_PROCESS, the merchant can call
inquiryPayment
API to query void result (Step 27).
Request
{
"voidAmount": {
"value":"1000",
"currency":"IQD"
},
"paymentId":"2023120611121280170016600090000xxxx",
"voidRequestId":"202331231313123124"
}
- voidRequestId is the unique ID of this capture request, generated by merchant/partner, merchant/partner should make sure it is unique, because wallet will use voidRequestId to do idempotent process.
- paymentId is the unique Id of a payment generated by Wallet, which is the unique payment identifier associated with this capture.
Response
{
"result": {
"resultCode":"SUCCESS",
"resultStatus":"S",
"resultMessage":"Success."
},
"voidId":"2023120611121280170016600090000xxxx",
"voidRequestId":"202331231313123124"
}
- result.resultStatus==S shows that the Wallet void is successful.
- voidId is generated by Wallet, uniquely identifies the void.