Refund

Discover Antom's refund rules and learn how to initiate a refund for a successful transaction.

Refund rules

The relevant refund rules are as follows:

  • Refund restrictions: Different payment methods have varying restrictions, including:
    • Refund not supported.
    • Partial refund not supported.
    • Refunds are not allowed after a certain period from the time of successful payment.

For refund capabilities and the refund period of each payment method, refer to Supported payment methods.

  • Refund return: In rare cases, due to reasons such as the buyer's account status being abnormal on the bank side, a situation may occur where the refund API is called and returns a success message, but the buyer does not receive the funds. In such cases, Antom will settle the corresponding funds and notify you through a settlement bill, and you need to handle these funds by your own.

Refund methods

If a payment is completed successfully, you can initiate a refund through the following two methods:

  • Refund using the refund API: Call the refund API to refund a successfully paid transaction.
  • Refund in Antom Dashboard: For more information about how to initiate a refund and check the refund result, see Refund transactions.

Refund process

The refund workflow is as follows:

refund.png

  1. Call the refund API.
  2. Process the refund response.

Handle the result based on the response returned by the refund API.

  1. Obtain the refund result.

Obtain the refund result by using one of the following two methods:

    • Asynchronous notification: Specify refundNotifyUrl in the refund API to set the address for receiving asynchronous notifications, or configure a webhook URL in Antom Dashboard. When the payment is successful or failed, Antom will use notifyRefund to send asynchronous notifications to you.
    • Synchronous inquiry: Call the inquiryRefund API to check the final refund result.

Integration steps

Start your integration by taking the following steps:

  1. Initiate a refund request
  2. Obtain the refund result

Step 1: Initiate a refund request Server-side

The code below shows a sample of calling the refund API:

copy
public static void payRefund() {
        AlipayPayRefundRequest alipayPayRefundRequest = new AlipayPayRefundRequest();

        // replace with your refundRequestId
        String refundRequestId = UUID.randomUUID().toString();
        alipayPayRefundRequest.setRefundRequestId(refundRequestId);

        // replace with your paymentId
        alipayPayRefundRequest.setPaymentId("yourPaymentId");

        // set amount
        // you should convert amount unit(in practice, amount should be calculated on your serverside)
        Amount amount = Amount.builder().currency("USD").value("100").build();
        alipayPayRefundRequest.setRefundAmount(amount);

        // replace with your refundReason
        alipayPayRefundRequest.setRefundReason("yourRefundReason");

        // replace with your refundNotifyUrl
        alipayPayRefundRequest.setRefundNotifyUrl("yourRefundNotifyUrl");

        AlipayPayRefundResponse alipayPayRefundResponse = null;
        try {
            alipayPayRefundResponse = CLIENT.execute(alipayPayRefundRequest);
        } 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.

The key parameters for initiating a refund request are 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. This value must match the paymentId in the pay (Auto Debit) API.

refundAmount

Yes

The refund amount. It includes the following parameters:

  • currency: The refund currency. This value must match the paymentAmount.currency in the pay (Auto Debit) API.
  • value: The refund amount (as a positive integer in the smallest currency unit). The single refund amount must be less than or equal to the payment amount (paymentAmount.value) in the pay (Auto Debit) API, and the cumulative amount of multiple partial refunds must be less than or equal to the total amount for this paymentId in the pay (Auto Debit) API.

refundNotifyUrl

No

The address for receiving asynchronous refund notifications from Antom.

The following code shows a sample of initiating a refund request:

copy
{
  "paymentId": "20181129190741010007000000XXXX",
  "refundReason": "amsdemorefund",
  "refundRequestId": "20181129190741020007000000XXXX",
  "refundAmount": {
    "currency": "USD",
    "value": "100"
  }
}

After calling the refund API, Antom returns the processing result of the refund. The following code shows a sample of the response message:

copy
{
  "result": {
    "resultCode": "SUCCESS",
    "resultStatus": "S",
    "resultMessage": "Success"
  },
  "refundAmount": {
    "value": "100",
    "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

S

Refund is successful.

No further action is needed.

U

Refund is being processed.

The following scenarios may occur:

  • REFUND_IN_PROCESS: Indicates that the refund is being processed. You can call the inquiryRefund API to obtain the refund result or wait for the refund result notification.
  • Other error codes: Retry with the original request.

F

Refund failed.

Please retry with a new refundRequestId. If the issue persists, contact Antom Technical Support.

Step 2: Receive the refund result Server-side

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:

  • Recommended If each of your orders has a unique notification URL, it is recommended to set the webhook URL in each request. You can pass the asynchronous notification receiving URL for the specific order through refundNotifyUrl 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 code shows a sample of the notification request of a refund:

copy
{
    "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

S

Refund is successful.

No further action is required.

F

Refund failed.

Please retry with a new refundRequestId. If the issue persists, contact Antom Technical Support.

Note: After initiating a refund, Antom sends asynchronous notifications to you by default. However, in some failure scenarios such as parameter anomalies, the refund API will return F. In such cases, Antom will not send asynchronous notifications and it can be considered as a refund failure.

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:

copy
/**
 * 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:

copy
{
  "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.

Parameter name

Required

Description

refundRequestId

No

The unique ID assigned by the merchant to identify a refund request.

The following code shows how to call the inquiryRefund API:

copy
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 a sample of the inquiryRefund response:

copy
{
  "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 refundStatus returned in the response, please handle the result according to the guidance provided:

refundStatus

Message

Further action

SUCCESS

Refund is successful.

No further action is needed.

FAIL

Refund failed.

Please retry with a new refundRequestId. If the issue persists, contact Antom Technical Support.

PROCESSING

Refund is being processed.

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.