|
@@ -9,15 +9,15 @@
|
|
|
| 项 | 5 章收款接口 | 本章 |
|
|
| 项 | 5 章收款接口 | 本章 |
|
|
|
|---|---|---|
|
|
|---|---|---|
|
|
|
| 路径前缀 | `/payment/openapi/pay` | `/payment/openapi/har` |
|
|
| 路径前缀 | `/payment/openapi/pay` | `/payment/openapi/har` |
|
|
|
-| 响应信封 | 三个下单接口 A 型,其余 B 型 | **3 个接口全部 B 型** |
|
|
|
|
|
|
|
+| 响应信封 | 三个下单接口 A 型,其余 B 型 | **4 个接口全部 B 型** |
|
|
|
| 金额 | 整数,单位**分** | 小数,单位**元** |
|
|
| 金额 | 整数,单位**分** | 小数,单位**元** |
|
|
|
-| 订单状态 | 文本枚举(`SUCCESS` / `PAYING`…),见 6 | **数字字符串**(`"0"` / `"1"`…),见 10.5 |
|
|
|
|
|
|
|
+| 订单状态 | 文本枚举(`SUCCESS` / `PAYING`…),见 6 | **数字字符串**(`"0"` / `"1"`…),见 10.6 |
|
|
|
| 下单幂等 | 同 `out_trade_no` 重发返回原单 | **不幂等**,每次调用都新建一笔,见 10.2 |
|
|
| 下单幂等 | 同 `out_trade_no` 重发返回原单 | **不幂等**,每次调用都新建一笔,见 10.2 |
|
|
|
-| 退款 | 有(5.6 / 5.7) | **本章没有退款接口** |
|
|
|
|
|
|
|
+| 退款 | 有(5.6 / 5.7),可指定金额 | **只有全额退款**,没有金额可填,见 10.4 |
|
|
|
|
|
|
|
|
> ⚠️ **「不幂等」与「金额单位是元」这两条最容易出事。** 前者会让你在超时重发时收到两笔扣款,后者会把 1 元写成 1 分。请读完 10.2 的注意框再动手。
|
|
> ⚠️ **「不幂等」与「金额单位是元」这两条最容易出事。** 前者会让你在超时重发时收到两笔扣款,后者会把 1 元写成 1 分。请读完 10.2 的注意框再动手。
|
|
|
|
|
|
|
|
-**关于寻址**:本章三个接口都按**你这条 API Key 所属的租户账号**寻址,取该租户名下由平台运营报备好的商户配置。你不需要在请求里指定归属。
|
|
|
|
|
|
|
+**关于寻址**:本章四个接口都按**你这条 API Key 所属的租户账号**寻址,取该租户名下由平台运营报备好的商户配置。你不需要在请求里指定归属。
|
|
|
|
|
|
|
|
**关于 `merchant_code`(新增,2026-09-24)**:平台**允许一个租户报备多个商户号**(例如你名下有多家门店主体,各自独立结算)。这时「这笔钱收进哪一个商户」必须由你在请求里说清楚,用 `merchant_code` 指定。
|
|
**关于 `merchant_code`(新增,2026-09-24)**:平台**允许一个租户报备多个商户号**(例如你名下有多家门店主体,各自独立结算)。这时「这笔钱收进哪一个商户」必须由你在请求里说清楚,用 `merchant_code` 指定。
|
|
|
|
|
|
|
@@ -26,7 +26,7 @@
|
|
|
|
|
|
|
|
> ⚠️ **你租户下配了多个商户号、而你又不传 `merchant_code` 时,接口会直接**拒绝**(`code=400`,`msg` 为 `当前租户配置了多个商户编号,请在请求中指定 merchant_code`),不会替你挑一个。**这是有意的** —— 挑错了钱会进另一个商户的账户,而且全程没有任何报错,要等到对账才发现。**只配了一个商户号的调用方不受影响**,什么都不用改。
|
|
> ⚠️ **你租户下配了多个商户号、而你又不传 `merchant_code` 时,接口会直接**拒绝**(`code=400`,`msg` 为 `当前租户配置了多个商户编号,请在请求中指定 merchant_code`),不会替你挑一个。**这是有意的** —— 挑错了钱会进另一个商户的账户,而且全程没有任何报错,要等到对账才发现。**只配了一个商户号的调用方不受影响**,什么都不用改。
|
|
|
|
|
|
|
|
-> **怎么知道自己配了几个**:登录平台,在「商户配置」页可以看到你名下的全部商户号。三个接口都填同一个 `merchant_code` 即可。
|
|
|
|
|
|
|
+> **怎么知道自己配了几个**:登录平台,在「商户配置」页可以看到你名下的全部商户号。四个接口都填同一个 `merchant_code` 即可。
|
|
|
|
|
|
|
|
**门店与下单的关系**:10.2 里的 `shop_code` / `third_shop_code` 都是**选填**。门店不是下单的前置条件 —— 只有需要把交易归属到某个具体门店时才填。
|
|
**门店与下单的关系**:10.2 里的 `shop_code` / `third_shop_code` 都是**选填**。门店不是下单的前置条件 —— 只有需要把交易归属到某个具体门店时才填。
|
|
|
|
|
|
|
@@ -114,15 +114,15 @@ POST /payment/openapi/har/order/create
|
|
|
| `upstream_order_no` | 上游订单号。下单成功才有值,下单超时时为空 |
|
|
| `upstream_order_no` | 上游订单号。下单成功才有值,下单超时时为空 |
|
|
|
| `platform_trade_no` | 平台交易号,支付成功后才有值 |
|
|
| `platform_trade_no` | 平台交易号,支付成功后才有值 |
|
|
|
| `pay_url` | **主扫**:收款链接,渲染成二维码即可。**被扫**:为空 |
|
|
| `pay_url` | **主扫**:收款链接,渲染成二维码即可。**被扫**:为空 |
|
|
|
-| `trade_status` | 订单状态,见 10.5 |
|
|
|
|
|
|
|
+| `trade_status` | 订单状态,见 10.6 |
|
|
|
| `price` | 订单金额(元) |
|
|
| `price` | 订单金额(元) |
|
|
|
| `title` / `trade_type` / `stage_num` / `percent` | 原样返回 |
|
|
| `title` / `trade_type` / `stage_num` / `percent` | 原样返回 |
|
|
|
| `shop_code` / `third_shop_code` | 原样返回 |
|
|
| `shop_code` / `third_shop_code` | 原样返回 |
|
|
|
| `trade_time` | 支付成功时间 |
|
|
| `trade_time` | 支付成功时间 |
|
|
|
| `rcv_amount` | 实收金额(元),支付成功后有值 |
|
|
| `rcv_amount` | 实收金额(元),支付成功后有值 |
|
|
|
| `fee_amount` / `channel_amount` | 手续费 / 渠道金额 |
|
|
| `fee_amount` / `channel_amount` | 手续费 / 渠道金额 |
|
|
|
-| `refund_time` | 退款时间。本章无退款接口,该字段恒为空 |
|
|
|
|
|
-| `notify_status` | 平台向你推送回调的结果,见 10.4 |
|
|
|
|
|
|
|
+| `refund_time` | 退款时间。退款到账(`trade_status` 为 `"2"`)后才有值 |
|
|
|
|
|
+| `notify_status` | 平台向你推送回调的结果,见 10.5 |
|
|
|
| `created_time` / `updated_time` | 记录时间 |
|
|
| `created_time` / `updated_time` | 记录时间 |
|
|
|
|
|
|
|
|
> ⚠️ **本接口不幂等 —— 重复调用会产生两笔订单、两次扣款。** 每次调用都会生成一个新的 `order_no` 并向上游发起一笔新的交易,平台**不做** `out_biz_no` 去重(也不做唯一约束)。超时后不要直接重发:先用 **10.3 订单查询** 按 `out_biz_no` 查一次,查到就用那一笔的结果。
|
|
> ⚠️ **本接口不幂等 —— 重复调用会产生两笔订单、两次扣款。** 每次调用都会生成一个新的 `order_no` 并向上游发起一笔新的交易,平台**不做** `out_biz_no` 去重(也不做唯一约束)。超时后不要直接重发:先用 **10.3 订单查询** 按 `out_biz_no` 查一次,查到就用那一笔的结果。
|
|
@@ -163,7 +163,58 @@ POST /payment/openapi/har/order/query
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-### 10.4 回调通知
|
|
|
|
|
|
|
+### 10.4 订单退款
|
|
|
|
|
+
|
|
|
|
|
+对一笔**已支付成功**的订单发起退款。
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+POST /payment/openapi/har/refund
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**请求**(`order_no` 与 `out_biz_no` **至少提供一个**,规则同 10.3)
|
|
|
|
|
+
|
|
|
|
|
+| 字段 | 类型 | 必填 | 说明 |
|
|
|
|
|
+|---|---|---|---|
|
|
|
|
|
+| `merchant_code` | string | 否 | **你租户下配了多个商户号时必填**,与其它三个接口同一个值 |
|
|
|
|
|
+| `order_no` | string | 二选一 | 平台订单号(10.2 响应里的 `order_no`) |
|
|
|
|
|
+| `out_biz_no` | string | 二选一 | 你自己的订单号 |
|
|
|
|
|
+
|
|
|
|
|
+> ⚠️ **本接口只有全额退款,请求里没有金额字段。** 这条通道的上游不支持部分退款 —— 发起即退整笔。需要退一部分的场景请先联系平台。
|
|
|
|
|
+
|
|
|
|
|
+**响应**(B 型,`data` 内):结构与 10.3 完全相同(同一份订单)。
|
|
|
|
|
+
|
|
|
|
|
+> ⚠️ **返回时 `trade_status` 是 `"4"`(退款中),不是 `"2"`。** 同步返回只代表平台已把退款指令发给上游,**不代表钱已经退回用户账上**。
|
|
|
|
|
+
|
|
|
|
|
+**结果怎么收敛**:`"4"` 由平台的查询任务持续向上游确认,直到拿到终态(上游若推了通知,平台也会转推给你,见 10.5):
|
|
|
|
|
+
|
|
|
|
|
+| 最终 `trade_status` | 含义 |
|
|
|
|
|
+|---|---|
|
|
|
|
|
+| `"2"` | **退款成功,钱已退回** |
|
|
|
|
|
+| `"1"` | 退款**没有发生**,订单回到已支付 |
|
|
|
|
|
+
|
|
|
|
|
+> ⚠️ **不要把 `"4"` 当成已退款,也不要凭它给用户承诺到账。** 用户看到的是钱有没有回来,不是接口返回了什么。同 10.5 的提醒:通知可能丢,**请对停在 `"4"` 的订单做主动查询兜底**。
|
|
|
|
|
+
|
|
|
|
|
+> ⚠️ **只有 `trade_status = "1"` 的订单能退款。** 其它状态(`"0"` / `"4"` / `"2"` / `"8"`)一律拒绝,`code=500`,`msg` 形如 `订单当前状态不可退款: <状态值>`。查不到订单、或不是你的订单,仍然是 10.3 那句 `code=500` 的 `订单不存在`。
|
|
|
|
|
+
|
|
|
|
|
+**重复调用会怎样** —— 这是最容易误解的一处:
|
|
|
|
|
+
|
|
|
|
|
+- 退款**不会重复发生**。第二次调用时订单已不在 `"1"`,会被上面那句错误挡下。
|
|
|
|
|
+- 但它**不是幂等接口**:重复调用拿到的是**错误**,不是第一次的结果。所以不要写「重试到成功为止」,要按下面的分支处理。
|
|
|
|
|
+
|
|
|
|
|
+**失败分两条路,处理方式相反**:
|
|
|
|
|
+
|
|
|
|
|
+| 返回 | 订单状态 | 你该做什么 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `code=500`,`msg` 形如 `退款失败: <原因>` | **退回 `"1"`** | 上游明确拒绝了,什么都没发生。可用 10.3 确认状态是 `"1"` 后**重新发起** |
|
|
|
|
|
+| `code=500`,`msg` 为 `退款结果未知(上游未响应),订单已置为退款中,请稍后查询订单状态确认` | **保持 `"4"`** | 上游没应答,**这笔退款可能已经发生**。**不要重发** —— 用 10.3 查到终态为止 |
|
|
|
|
|
+
|
|
|
|
|
+> ⚠️ **两条路都是 `code=500`,只能靠 `msg` 区分。** 拿不准时一律按「结果未知」处理(不重发、去查询):重发一笔可能已经退掉的款是真实资金损失,多查一次只是麻烦。
|
|
|
|
|
+
|
|
|
|
|
+> ⚠️ **「退款失败就再退一次」的前提是订单已回到 `"1"`,不是你上次调用的返回。** 并发重复发起时只有一次会成功,另一次会被状态挡下 —— 但两次的返回里只有一次是「已受理」,别把两者搞混。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### 10.5 回调通知
|
|
|
|
|
|
|
|
订单状态变化时,平台会向你推送一条回调。
|
|
订单状态变化时,平台会向你推送一条回调。
|
|
|
|
|
|
|
@@ -224,7 +275,7 @@ Content-Type: application/x-www-form-urlencoded
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-### 10.5 状态说明
|
|
|
|
|
|
|
+### 10.6 状态说明
|
|
|
|
|
|
|
|
**`trade_status` 是数字字符串**(JSON 里带引号,不是数字):
|
|
**`trade_status` 是数字字符串**(JSON 里带引号,不是数字):
|
|
|
|
|
|
|
@@ -237,6 +288,7 @@ Content-Type: application/x-www-form-urlencoded
|
|
|
| `"8"` | 交易关闭 | 是 |
|
|
| `"8"` | 交易关闭 | 是 |
|
|
|
|
|
|
|
|
判断「是否收到过钱」用 `"1"` / `"2"`;判断「是否还要等」用 `"0"` / `"4"`。
|
|
判断「是否收到过钱」用 `"1"` / `"2"`;判断「是否还要等」用 `"0"` / `"4"`。
|
|
|
|
|
+判断「退款是否已经到账」只看 `"2"` —— 停在 `"4"` 表示平台还在向上游确认,**不代表已退**(见 10.4)。
|
|
|
|
|
|
|
|
**门店 `create_status`**:`SUCCESS` / `FAILED` / `PENDING`,见 10.1。
|
|
**门店 `create_status`**:`SUCCESS` / `FAILED` / `PENDING`,见 10.1。
|
|
|
|
|
|
|
@@ -261,4 +313,7 @@ Content-Type: application/x-www-form-urlencoded
|
|
|
- [ ] 回调接口能处理表单编码,并把 `content` **再解析一次** JSON
|
|
- [ ] 回调接口能处理表单编码,并把 `content` **再解析一次** JSON
|
|
|
- [ ] 回调按 `out_biz_no` 做幂等
|
|
- [ ] 回调按 `out_biz_no` 做幂等
|
|
|
- [ ] 对长期停在 `"0"` 的订单有主动查询兜底
|
|
- [ ] 对长期停在 `"0"` 的订单有主动查询兜底
|
|
|
|
|
+- [ ] 退款只对 `trade_status = "1"` 的订单发起,且发起前用 10.3 确认过没有退过
|
|
|
|
|
+- [ ] 退款返回 `退款结果未知…` 时**不重发**,改用 10.3 查到终态
|
|
|
|
|
+- [ ] 退款结果按 `"2"`(已到账)判定,不把 `"4"` 当已退款
|
|
|
- [ ] 门店 `create_status` 收到 `PENDING` 时走人工核实,不自行重发
|
|
- [ ] 门店 `create_status` 收到 `PENDING` 时走人工核实,不自行重发
|