Refund
Discover Antom's refund rules and learn how to initiate a refund for a successful transaction.
Refund rules
The following are the relevant refund rules:
- Commission fee: Whether the commission fee is returned or whether there are additional charges for the refund is subject to the contract.
- Refund settlement rate: When the settlement and payment currency are inconsistent, the settlement exchange rate used for refund is the Antom exchange rate on the day of the successful refund.
- Refund restriction: Different payment methods have different restrictions. The following are specific situations:
- Refund not supported
- Partial refund not supported
- Refunds are not supported after a certain time, starting from the time of successful payment.
For details, see Supported payment methods.
- Refund return: In extreme cases, due to the abnormal status of the buyer's bank account and other reasons, the refund API is called and returns a successful refund status, but the buyer is unable to receive the funds successfully. Antom will settle the corresponding funds and notify you through the financial report settlement. You need to decide how to handle the funds.
Refund methods
After the transaction is paid successfully, you can initiate a refund through the following two ways:
- Refund using the refund API: You can initiate a refund for a successfully paid transaction by calling the refund API.
- Refund in Antom Dashboard: For more information about how to issue a refund and view the refund result, see Refund transactions.
Workflow
The following figure is the workflow of refund.
Figure 1. Workflow of refund
Notes:
- After calling the refund API, the following three situations may be returned:
- A refund failure is returned in the refund response: If the request parameters are incorrect, try to adjust the refund parameters based on the returned error code information and retry. Contact Antom Technical Support for troubleshooting. For details about how to handle each error code, see Error codes.
- A successful refund is returned in the refund response: The resultCode parameter returns
REFUND_IN_PROCESS
, use the inquiryRefund API to obtain the final refund result, or wait for the refund result notification through notifyRefund.- An unknown exception of refund is returned in the refund response: It is usually due to network reasons, and you can try to retry without changing the account.
- Refund notification: A refund notification will be sent if the refund is successful. In the case of refund failure, there will be no refund notification if the processing is abnormal due to an illegal refund request.
Integration steps
Start your integration by taking the following steps:
- Initiate a refund request
- Obtain the refund result
Step 1: Initiate a refund request
The refund process through the refund API varies depending on the payment method and may proceed either synchronously or asynchronously:
- Synchronous refund: After calling the refund API, the response directly indicates whether the refund was successful or failed. Nevertheless, there is a slight possibility of system exceptions or payment channel processing exceptions, which might result in different responses.
- Asynchronous refund: After calling the refund API, a response indicates the refund is being processed. You are then required to periodically check the refund status or wait for a notification that will provide the final refund status.
The following table shows payment methods supported by the synchronous and asynchronous refunds.
Synchronous refund | Asynchronous refund |
Alipay+ payment methods | All other payment methods default to asynchronous refunds. For a comprehensive list of payment methods, refer to Supported payment methods. |
Mastercard and Visa cards through acquirers 2C2P HK and 2C2P SG |
The following table shows API compatibility with synchronous and asynchronous refund processes.
API | Synchronous refund | Asynchronous refund |
Supported | Supported | |
Not supported | Supported | |
Supported | Supported |
The following sample code shows how to call the refund API:
public static void refund() {
AlipayRefundRequest alipayRefundRequest = new AlipayRefundRequest();
// replace with your refundRequestId
String refundRequestId = UUID.randomUUID().toString();
alipayRefundRequest.setRefundRequestId(refundRequestId);
alipayRefundRequest.setPaymentId("20181129190741010007000000XXXX");
alipayRefundRequest.setRefundReason("demo refund");
// set refund amount
Amount amount = Amount.builder().currency("USD").value("1000").build();
alipayRefundRequest.setRefundAmount(amount);
AlipayRefundResponse alipayRefundResponse;
try {
alipayRefundResponse = CLIENT.execute(alipayRefundRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
}
If the refund request does not meet relevant requirements when using the API, Antom will return corresponding error codes:
Error code | Description |
ORDER_STATUS_INVALID | The payment is not successful. |
REFUND_WINDOW_EXCEED | The refund date exceeds the refundable period that is agreed in the contract. |
PAYMENT_METHOD_NOT_SUPPORTED | The payment method does not support canceling or refunding transactions. |
PARTIAL_REFUND_NOT_SUPPORTED | A partial refund is not supported for this transaction. |
MERCHANT_BALANCE_NOT_ENOUGH | The merchant balance is insufficient. |
When initiating a refund through the refund API, the key parameters in the request are listed as follows:
Parameter name | Required | Description |
refundRequestId | Yes | The unique identifier that you assign to a refund. |
paymentId | Yes | The unique identifier that Antom assigns to the original payment to be refunded. |
refundAmount | Yes | The refund amount must be no less than the minimum refund amount (usually the same as the minimum payment amount) and no greater than the refundable amount of a payment. The currency of the refund amount must be consistent with the currency of the payment amount (paymentAmount.currency) in the pay API. |
refundNotifyUrl | No | The URL for receiving asynchronous refund notifications. |
The following shows the sample code of a refund request:
{
"paymentId": "20181129190741010007000000XXXX",
"refundReason": "amsdemorefund",
"refundRequestId": "20181129190741020007000000XXXX",
"refundAmount": {
"currency": "USD",
"value": "1000"
}
}
The following shows the sample code of a response:
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "Success"
},
"refundAmount": {
"value": "1000",
"currency": "USD"
},
"refundTime": "2020-10-10T12:01:01+08:30",
"paymentId": "20181129190741010007000000XXXX",
"refundRequestId": "20181129190741020007000000XXXX",
"refundId": "40181129190741020007000000XXXX"
}
The value of result.resultStatus in the response represents the refund status of the transaction. Please handle the result according to the guidance provided:
result.resultStatus | Message | Further action |
| Indicates that the refund is successful. | No further action is required. |
| Indicates that the refund failed. | When the error codes mentioned in Step 1 are excluded, returning |
| Indicates that the refund failed for unknown reasons. | The following scenarios may occur:
|
| Indicates the oder is closed. | Usually returned in the inquiryRefund response, refund re-call, and notifyRefund request. It may be that the refund cannot be processed in Antom for some reason. You can use a new paymentRequestId to initiate the refund again. |
Step 2: Receive the refund result
Antom will send the corresponding refund result to you via server interaction. You can obtain the refund result using one of the following methods:
- Receive asynchronous notifications from Antom
- Inquire about the refund result
Receive asynchronous notifications
Complete the following steps to receive notifications from the Antom notifyRefund API:
1. Configure the webhook URL to receive notifications
You can choose one of following two methods to set the webhook URL to receive notifications:
- If each of your orders has a unique notification URL, we recommend to set the webhook URL in each individual request. You can pass the asynchronous notification receiving URL for the specific order through the refundNotifyUrl field in the refund API.
- If all your orders share a unified notification URL, you can set the webhook URL on Antom Dashboard through Developer > Notification URL. For detailed steps, refer to Notification URL.
The following is the notification request sample code:
{
"notifyType": "REFUND_RESULT",
"refundAmount": {
"currency": "USD",
"value": "100"
},
"refundId": "40181129190741020007000000XXXX",
"refundRequestId": "20181129190741020007000000XXXX",
"refundStatus": "SUCCESS",
"refundTime": "2020-10-10T12:01:01+08:30",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}
The table below shows the possible values of result.resultStatus in the request message. Please handle the result according to the guidance provided:
result.resultStatus | Message | Further action |
| Indicates that the refund is successful. | No further action is required. |
| Indicates that the refund failed. | Please retry with a new refundRequestId, or contact Antom Technical Support. |
2. Verify the asynchronous notification
If you receive an asynchronous notification from Antom, you are required to return the response in the Sample code format, but you do not need to countersign the response.
You need to verify the signature of the refund notification sent by Antom.
/**
* receive notify
*
* @param request request
* @param notifyBody notify body
* @return Result
*/
@PostMapping("/receiveNotify")
@ResponseBody
public Result receiveNotify(HttpServletRequest request, @RequestBody String notifyBody) {
// retrieve the required parameters from http request
String requestUri = request.getRequestURI();
String requestMethod = request.getMethod();
// retrieve the required parameters from request header
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String signature = request.getHeader("signature");
try {
// verify the signature of notification
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId,
requestTime, signature, notifyBody, ANTOM_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// deserialize the notification body
JSONObject jsonObject = JSON.parseObject(notifyBody);
String notifyType = (String)jsonObject.get("notifyType");
if("REFUND_RESULT".equals(notifyType)){
AlipayRefundNotify paymentNotify = jsonObject.toJavaObject(AlipayRefundNotify.class);
if (paymentNotify != null && "SUCCESS".equals(paymentNotify.getResult().getResultCode())) {
// handle your own business logic.
// e.g. The relationship between payment information and users is kept in the database.
System.out.println("receive payment notify: " + JSON.toJSONString(paymentNotify));
return Result.builder().resultCode("SUCCESS").resultMessage("success.").resultStatus(ResultStatusType.S).build();
}
}
// other types of notifications
} catch (Exception e) {
// handle error condition
return Result.builder().resultCode("FAIL").resultMessage("fail.").resultStatus(ResultStatusType.F).build();
}
return Result.builder().resultCode("SYSTEM_ERROR").resultMessage("system error.").resultStatus(ResultStatusType.F).build();
}
Whether the refund is successful or not, each notification request must be responded to in the format specified below:
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}
Inquire about the refund result
In addition to obtaining the refund result through the asynchronous notification, you can also inquire about the refund status by calling the inquiryRefund API using the refundRequestId from the refund request.
The following code shows how to call the inquiryRefund API:
public static void inquiryRefund() {
AlipayInquiryRefundRequest alipayInquiryRefundRequest = new AlipayInquiryRefundRequest();
// replace with your refundId
alipayInquiryRefundRequest.setRefundId("yourRefundId");
AlipayInquiryRefundResponse alipayInquiryRefundResponse = null;
try {
alipayInquiryRefundResponse = CLIENT.execute(alipayInquiryRefundRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// handle error condition
}
}
The following code shows an example of a response:
{
"refundAmount": {
"currency": "USD",
"value": "1000"
},
"refundId": "40181129190741020007000000XXXX",
"refundRequestId": "20181129190741020007000000XXXX",
"refundStatus": "SUCCESS",
"refundTime": "2024-12-10T22:02:02-08:00",
"result": {
"resultCode": "SUCCESS",
"resultMessage": "success.",
"resultStatus": "S"
}
}
The table below shows the possible values of refundStatus returned in the response, please handle the result according to the guidance provided:
refundStatus | Message | Further action |
| Indicates that the refund is successful. | No further action is required. |
| Indicates that the refund failed. | Please retry with a new refundRequestId, or contact Antom Technical Support. |
| Indicates that the refund is processing. | Please continue to inquire about the refund status until a final result is obtained or a refund asynchronous notification is received. |
Commom questions
Q: Will the refund result be returned immediately after initiating a refund?
A: Not all payment methods can return the final refund status synchronously. Please refer to the asynchronous notification result from notifyRefund for a final outcome.
Q: How long does it take for the buyer to receive the refund after it is successful?
A: A successful refund indicates that the payment method has accepted the buyer’s refund request. The specific time for funds to arrive depends on the payment method.