# Refund

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

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 [payment methods](https://docs.antom.com/payment_methods.md).

-   **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**](https://docs.antom.com/ac/ams/refund_online.md) 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**](https://docs.antom.com/ac/ams/refund_online.md) API to refund a successfully paid transaction.
-   Refund in [Antom Dashboard](https://dashboard.alipay.com/global-payments/home): For more information about how to initiate a refund and check the refund result, see [Refund transactions](https://docs.antom.com/ac/merchant_service/transactions.md#QySzf).

# Refund process

The refund workflow is as follows:

![Sequence diagram illustrating the Tokenized Payment refund process.](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/png/3795f3bc-ccf6-467c-b151-86c546b1d887.png)

1.  **Call the** [**refund**](https://docs.antom.com/ac/ams/refund_online.md) **API.**
2.  **Process the refund response.**Handle the result based on the response returned by the [**refund**](https://docs.antom.com/ac/ams/refund_online.md) API.
3.  **Obtain the refund result.**
    Obtain the refund result by using one of the following two methods:

-   Asynchronous notification: Specify _refundNotifyUrl_ in the [**refund**](https://docs.antom.com/ac/ams/refund_online.md) 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**](https://docs.antom.com/ac/ams/notify_refund.md) to send asynchronous notifications to you.
-   Synchronous inquiry: Call the [**inquiryRefund**](https://docs.antom.com/ac/ams/ir_online.md) 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**](https://docs.antom.com/ac/ams/refund_online.md) API:

```java
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**](https://docs.antom.com/ac/ams/refund_online.md) 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 (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md) 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 (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md) 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 (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md) 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 (Tokenized Payment)**](https://docs.antom.com/ac/ams/payment_agreement.md) API. |
| _refundNotifyUrl_ | No | The address for receiving asynchronous refund notifications from Antom. |

The following code shows a sample of initiating a [**refund**](https://docs.antom.com/ac/ams/refund_online.md) request:

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

After calling the [**refund**](https://docs.antom.com/ac/ams/refund_online.md) API, Antom returns the processing result of the refund. The following code shows a sample of the response message:

```json
{
  "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**](https://docs.antom.com/ac/ams/ir_online.md) 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**](https://docs.antom.com/ac/ams/notify_refund.md) 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**](https://docs.antom.com/ac/ams/refund_online.md) API.
-   If all your orders share a unified notification URL, you can set the webhook URL on [Antom Dashboard](https://dashboard.alipay.com/global-payments/developers/iNotify) through **Developer > Notification URL**. For detailed steps, refer to [Notification URL](https://docs.antom.com/ac/merchant_service/notification.md).

The following code shows a sample of the notification request of a refund:

```json
{
    "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**](https://docs.antom.com/ac/ams/refund_online.md) 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](https://docs.antom.com/ac/auto_debit/notifications.md#vQK5A) format, but you do not need to countersign the response.

You need to verify the signature of the refund notification sent by Antom:

```java
/**
 * 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:

```json
{
  "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**](https://docs.antom.com/ac/ams/ir_online.md) 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**](https://docs.antom.com/ac/ams/ir_online.md) API:

```java
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**](https://docs.antom.com/ac/ams/ir_online.md) response:

```json
{
  "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**](https://docs.antom.com/ac/ams/notify_refund.md) 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.