# 处理退款

> Shoplazza 支付应用处理退款的流程：商家后台发起的退款请求、同步响应，以及最终结果的异步通知。

当商家在 Shoplazza 后台提交退款请求时，退款处理流程开始。Shoplazza 调用支付应用的退款 API，支付应用同步返回退款结果。如果退款仍处于处理中，支付应用必须异步通知 Shoplazza 最终结果。

## 时序步骤

![退款时序图](https://cnres.appracle.com/98efe36d81aefe6f3fbd1eb44b379d90.png)

1. 商家在 Shoplazza 后台确认退款并提交请求。
2. Shoplazza 接收退款请求并开始退款流程。
3. Shoplazza 组装退款请求并调用支付应用的退款 API。
4. 支付应用同步返回退款结果。
5. Shoplazza 处理并展示退款结果。
6. 必要时，支付应用异步通知 Shoplazza 最终退款结果。
7. Shoplazza 处理退款通知并更新订单状态。

## 请求头

| Header | 说明 |
| --- | --- |
| `Shoplazza-Shop-Id` | Shoplazza 系统中的店铺 ID。 |
| `Shoplazza-Shop-Domain` | Shoplazza 分配的系统域名。 |
| `Shoplazza-Request-Id` | 唯一请求 ID。 |
| `Shoplazza-Api-Version` | Open API 版本。 |
| `Shoplazza-Hmac-Sha256` | 用于请求校验的数字签名。 |

## 请求参数

Shoplazza 通过调用 refund session URL 将支付相关信息传给支付服务商。服务商同步返回退款结果。如果当前状态不是最终状态，服务商必须后续发送异步退款通知。

请求体以 `x-www-form-urlencoded` 形式发送。

```json
{
  "id": "7eb3fefb-6b43-4400-b40a-a2a0531364ae",
  "app_id": "db5fc9a6-2a64-11ec-8d3d-0242ac130003",
  "account_id": "TIOnETZE",
  "payment_id": "7eb3fefb-6b43-4400-b40a-a2a0531364ae",
  "amount": "254.20",
  "currency": "CAD",
  "callback_url": "https://developer.myshoplaza.com/openapi/2021-07/payments_apps/notify_callbacks?version=1.0",
  "test": false,
  "type": "refund",
  "extra": "625598363623041156",
  "timestamp": "2021-09-01T18:32:20Z"
}
```

| Parameter | 是否必填 | 类型 | 说明 |
| --- | --- | --- | --- |
| `id` | 是 | string | 唯一退款 ID，用于幂等。 |
| `app_id` | 是 | string | 支付应用 ID。 |
| `account_id` | 是 | string | 支付服务商系统中的商户 ID。 |
| `payment_id` | 是 | string | 原支付 ID。 |
| `amount` | 是 | string | 退款金额，保留两位小数。 |
| `currency` | 是 | string | 币种代码，例如 `USD` 或 `CAD`。 |
| `callback_url` | 是 | string | 异步退款结果通知 URL。 |
| `test` | 否 | boolean | 请求是否为测试模式。 |
| `type` | 是 | string | 固定值：`refund`。 |
| `extra` | 是 | string | 附加信息。 |
| `timestamp` | 是 | long | ISO 8601 时间戳。 |

## 退款响应

| Key | 类型 | 是否必填 | 说明 |
| --- | --- | --- | --- |
| `refund_id` | string | 是 | 退款 ID，用于幂等。 |
| `status` | string | 是 | 退款状态：`refund_success`、`refund_failed` 或 `refund_pending`。 |
| `message` | string | 是 | 退款说明或失败原因。 |

### 响应示例

```json
{
  "refund_id": "db5fc9a6-2a64-11ec-8d3d-0242ac130003",
  "status": "refund_success",
  "message": "success"
}
```
