Переглянути джерело

docs(汇安融): 开放文档按裁定收缩 —— 删建店/被扫/挑店/分期等,trade_type 与 biz 退出调用方契约

调用方契约收敛(2026-10-09 逐项裁定),全部落在「10 章 + 11 联调清单」:

- 删「创建门店」整节与门店 create_status 段:接口数四个 → 三个(两处计数同步)
- 请求表删七行:auth_code / province_code / extra_params / stage_num / percent /
  trade_type / biz;ip 行收窄为「顾客用户端ip」
- 删主扫/被扫两场景表与全文相关定义(auth_code 那条腿是后台/收银台的能力,开放文档不再教)
- 删「按地区自动挑店」说明块与章首门店地区引子
- 章首与第 5 章的差异说明(金额单位、幂等性对比)整块删除,改为一行接口路径前缀自述
- 响应表同步收窄:pay_url 行去掉主扫/被扫、`title / trade_type / stage_num / percent`
  改为只列 `title`、门店编码行改「你传的门店编码原样返回」
- 回调示例删 `trade_type` 行(报文实际仍携带该键,示例从简)
- 联调清单删四项(建号省码 / 挑店 / auth_code 两场景 / 门店状态),pay_url 项改口径
- 小节号整体上移一位:原 10.2~10.6 → 10.1~10.5(写前实测 30 处引用、写后两向分布核对)
- harDoc.ts 仅同步侧边栏注释(条目与切片逻辑未动)

隐藏 ≠ 后端不再收:DTO 字段全部保留,后台表单与既有调用方照传不误。
其中 trade_type / biz 的后端配套(留空兜底 alipay_un_stage)见下一提交。
alphaH 5 днів тому
батько
коміт
eaaa742b17

+ 50 - 149
frontend/src/views/module_payment/apikey/docs/har-openapi.md

@@ -1,23 +1,8 @@
 ## 10. 门店与订单接口
 
-本章是**另一条通道**,路径前缀 `/payment/openapi/alipay`,与 5 章的收款接口不是同一个接口族。
+本章接口路径前缀 `/payment/openapi/alipay`;请求头与签名算法(3.2 / 3.3)逐字适用,错误处理总则(3.6)同样适用。
 
-**相同的部分**:请求头与签名算法(3.2 / 3.3 逐字适用)、错误处理总则(3.6)。
-
-**不同的部分 —— 动手前先读完这张表**:
-
-| 项 | 5 章收款接口 | 本章 |
-|---|---|---|
-| 路径前缀 | `/payment/openapi/pay` | `/payment/openapi/alipay` |
-| 响应信封 | 三个下单接口 A 型,其余 B 型 | **4 个接口全部 B 型** |
-| 金额 | 整数,单位**分** | 小数,单位**元** |
-| 订单状态 | 文本枚举(`SUCCESS` / `PAYING`…),见 6 | **数字字符串**(`"0"` / `"1"`…),见 10.6 |
-| 下单幂等 | 同 `out_trade_no` 重发返回原单 | **不幂等**,每次调用都新建一笔,见 10.2 |
-| 退款 | 有(5.6 / 5.7),可指定金额 | **只有全额退款**,没有金额可填,见 10.4 |
-
-> ⚠️ **「不幂等」与「金额单位是元」这两条最容易出事。** 前者会让你在超时重发时收到两笔扣款,后者会把 1 元写成 1 分。请读完 10.2 的注意框再动手。
-
-**关于寻址**:本章四个接口都按**你这条 API Key 所属的租户账号**寻址,取该租户名下由平台运营报备好的商户配置。你不需要在请求里指定归属。
+**关于寻址**:本章三个接口都按**你这条 API Key 所属的租户账号**寻址,取该租户名下由平台运营报备好的商户配置。你不需要在请求里指定归属。
 
 **关于 `merchant_code`(新增,2026-09-24)**:平台**允许一个租户报备多个商户号**(例如你名下有多家门店主体,各自独立结算)。这时「这笔钱收进哪一个商户」必须由你在请求里说清楚,用 `merchant_code` 指定。
 
@@ -26,73 +11,13 @@
 
 > ⚠️ **你租户下配了多个商户号、而你又不传 `merchant_code` 时,接口会直接**拒绝**(`code=400`,`msg` 为 `当前租户配置了多个商户编号,请在请求中指定 merchant_code`),不会替你挑一个。**这是有意的** —— 挑错了钱会进另一个商户的账户,而且全程没有任何报错,要等到对账才发现。**只配了一个商户号的调用方不受影响**,什么都不用改。
 
-> **怎么知道自己配了几个**:登录平台,在「商户配置」页可以看到你名下的全部商户号。四个接口都填同一个 `merchant_code` 即可。
+> **怎么知道自己配了几个**:登录平台,在「商户配置」页可以看到你名下的全部商户号。三个接口都填同一个 `merchant_code` 即可。
 
-**门店与下单的关系**:10.2 里的 `shop_code` / `third_shop_code` 都是**选填**。门店不是下单的前置条件 —— 只有需要把交易归属到某个具体门店时才填。
-
-> **但门店的「地区」是有用的**:平台的收款链接(第 6 章的顾客付款页)下单时会按顾客 IP 的归属地自动挑一家同地区的门店,见 10.1 的地区说明。你的接口自己下单时若指定了门店,那个地区的风控判断同样适用;或者**不指定门店、改传顾客归属**(顾客 IP 或省级编码,2026-10-09 起),由平台在该地区替你挑一家 —— 见 10.2。
+**门店与下单的关系**:10.1 里的 `shop_code` / `third_shop_code` 都是**选填**。门店不是下单的前置条件 —— 只有需要把交易归属到某个具体门店时才填。
 
 ---
 
-### 10.1 创建门店
-
-为你的一个线下门店建号。平台侧**没有门店查询接口**,本接口的返回就是你日后核对门店状态的依据,请把 `shop_id` 存下来。
-
-```
-POST /payment/openapi/alipay/shop/create
-```
-
-**请求**
-
-| 字段 | 类型 | 必填 | 说明 |
-|---|---|---|---|
-| `merchant_code` | string | 否 | **你租户下配了多个商户号时必填**:门店建在哪一个商户下,见本章开头。只配了一个的不用传 |
-| `third_shop_id` | string | 是 | 你方的门店编码,≤32 字符。**重复提交会被拒绝**,见下 |
-| `shop_name` | string | 是 | 门店名称,≤128 字符 |
-| `province_code` | string | **是**(2026-10-08 起) | 门店所在省,GB/T 2260 六位码,如 `320000`(江苏省)、`110000`(北京市) |
-| `city_code` | string | **是**(2026-10-08 起) | 门店所在市,GB/T 2260 六位码,如 `320100`(南京市)、`110100`(北京市)。**必须是 `province_code` 下的市**,编码填错一律 `code=400` 拒绝(`msg` 形如 `城市编码不属于该省: 110100(省 320000)`;省码写错则为 `省份编码不存在: 999999`)—— 是调用方的输入错误,改对再调即可 |
-
-> ⚠️ **`province_code` / `city_code` 自 2026-10-08 起为必填。** 在此之前提交成功的门店不传这两个字段也能建号,**现在不传会返回 `code=400`**(`msg` 为 `省份不能为空` / `城市不能为空`)。取值用国标 GB/T 2260 的行政区划代码完整六位:省级 `XX0000`(2 位省码 + `0000`)、地级 `XXXX00`(4 位市码 + `00`),直辖市取 `110100`(北京市)/ `120100`(天津市)/ `310100`(上海市)/ `500100`(重庆市)、`500200`(重庆市县)。
-
-> ⚠️ **地区填错不会有任何报错,但这家门店会永远收不到款。** 支付宝对**异地收款**有风控,所以平台的**收款链接**(第 6 章的顾客付款页)在下单时会按**顾客 IP 的归属地**自动挑一家同地区的门店去发起收款。地区为空、或与顾客所在地不一致的门店,在挑店时直接落选。上游没有门店更新接口,**建号时填错就补不回来**,只能换一个新的 `third_shop_id` 重新建号。
-
-> **2026-10-08 之前建的门店**:那批门店没有地区,无法回填,**也不会被收款链接挑中**。让顾客扫码付款的门店必须重新建号。
-
-**响应**(B 型,`data` 内)
-
-| 字段 | 说明 |
-|---|---|
-| `third_shop_id` | 原样返回 |
-| `shop_name` | 原样返回 |
-| `province_code` / `city_code` | 原样返回(建号时提交的那两个码) |
-| `shop_id` | 平台门店编号,**建号成功才有值**;下单时作为 `shop_code` 传入 |
-| `create_status` | 建号结果,见下 |
-| `merchant_code` | 平台侧为你配置的商户编号(你无需关心,原样带回) |
-| `fail_reason` | `create_status` 非 `SUCCESS` 时的原因 |
-| `created_time` / `updated_time` | 记录时间 |
-
-`create_status` 取值:
-
-| 值 | 含义 | 你该做什么 |
-|---|---|---|
-| `SUCCESS` | 门店已建好,`shop_id` 可用 | 保存 `shop_id` |
-| `FAILED` | 明确被拒,不会建号 | 看 `fail_reason`,改好再调一次 |
-| `PENDING` | **结果未知** —— 调用超时或网络失败,无法确认门店是否已经建出来 | **不要直接重发**(可能建出两个门店),联系平台方人工核实 |
-
-> ⚠️ **`third_shop_id` 重复会被直接拒绝,而不是「返回原有门店」。** 重复提交同一个 `third_shop_id`,返回 `code=500`,`msg` 形如 `门店编码已存在: <你的编码>`。所以本接口的正确幂等做法是**先查你本地的记录,再决定要不要调**,而不是无脑重发。
-
-> ⚠️ **`PENDING` 不是「处理中」。** 门店创建**不自动重试** —— 重试可能在上游建出两个门店。收到 `PENDING` 时唯一正确的动作是找平台方核实,不要自行重发。
-
----
-
-### 10.2 下单收款
-
-同一个接口承担两种场景,由 `auth_code` 是否有值决定:
-
-| `auth_code` | 场景 | 行为 |
-|---|---|---|
-| **有值** | 被扫 —— 用户出示付款码,你扫码后把码传进来 | 立即发起扣款 |
-| **不传** | 主扫 —— 平台返回一条收款链接,你渲染成二维码给用户扫 | 只下单,等用户付款 |
+### 10.1 下单收款
 
 ```
 POST /payment/openapi/alipay/order/create
@@ -101,64 +26,47 @@ POST /payment/openapi/alipay/order/create
 **请求**
 
 | 字段 | 类型 | 必填 | 说明 |
-|---|---|---|---|
-| `merchant_code` | string | 否 | **你租户下配了多个商户号时必填**:这笔钱收进哪一个商户,见本章开头 |
-| `price` | number | 是 | 金额,**单位元**,必须 > 0。与 5 章的「整数分」不同,见下 |
-| `title` | string | 是 | 商品名称,≤64 字符 |
-| `trade_type` | string | 是 | `alipay_un_stage` 支付宝支付 / `alipay_stage` 花呗分期 |
-| `biz` | string | 否 | 业务类型。**留空即可** —— 由平台按 `trade_type` 自动填,你不用知道它的取值。显式传值时原样透传 |
-| `out_biz_no` | string | 否 | 你自己的订单号,≤64 字符,原样存下供你查询 |
-| `auth_code` | string | 否 | 用户的付款码。有值走被扫,不传走主扫 |
-| `stage_num` | string | 否 | 分期期数:`3` / `6` / `12` / `24`。`trade_type=alipay_stage` 时必填 |
-| `percent` | string | 否 | 分期手续费承担方:`100` 商户承担 / `0` 用户承担。`trade_type=alipay_stage` 时必填 |
-| `shop_code` | string | 否 | 平台门店编号(10.1 返回的 `shop_id`) |
-| `third_shop_code` | string | 否 | 你方门店编码,≤32 字符 |
-| `ip` | string | 否 | **不指定门店时**由平台按地区挑店:**顾客的公网 IP**(不是服务器的),精度到市,**优先于 `province_code`**,见下 |
-| `province_code` | string | 否 | 顾客所在省,GB/T 2260 六位码(`"320000"` 江苏省、`"110000"` 北京市),与 10.1 建店**同一套码**;`ip` 解析不出(或 IP 地区没有可用门店)时的回退,见下 |
-| `pay_timeout` | int | 否 | 支付过期时间,取值 2–60(单位由上游定义,平台原样透传) |
-| `extra_params` | string | 否 | 透传字段 |
-
-> **按地区自动挑店(2026-10-09 起,选填)**:不传 `shop_code` / `third_shop_code`、但传了 `ip` 或 `province_code` 时,平台**替你在顾客所在地区挑一家门店**去发起交易,与平台的收款链接(第 6 章顾客付款页)同一套规则、同一个地区目录。`ip` 与 `province_code` 可以只传一个,也可以都传。
->
-> - **优先级**:`ip` 能解析出归属地时**以 `ip` 为准**(精确到市);解析不出(内网地址、非大陆 IP、查询失败)或 IP 地区没有可用门店时,**回退用 `province_code` 按全省挑**。两个都传最稳 —— IP 不灵时省码兜底。
-> - **`ip` 填什么**:**顾客发起支付的公网 IP**,不是你服务器的出口 IP、也不是你后台的 IP。格式照常(`"114.114.114.114"`)。
-> - **`province_code` 格式**(照这个填,填错会挑不到门店):GB/T 2260 行政区划代码完整六位,与 10.1 建店**完全同一套** —— 省级 `XX0000`,传的是**代码不是地名**(写 `"320000"`,写成 `"江苏省"` 会被拒)。
-> - **怎么挑**:先在同市可用门店里挑(市由 `ip` 解析决定);该市没有则回退到全省挑(不报错);同地区有多家时按 `out_biz_no` 稳定挑一家(同一 `out_biz_no` 重复调用落同一家;没传 `out_biz_no` 时随机挑一家)。
-> - **挑中哪家**:响应里的 `third_shop_code` 就是挑中的那家(本来该你传的字段,现在由平台回显)。
-> - **挑不出来会被拒收**(`code=400`,这单不会建立、不会扣款):省码不认识 —— `省份编码不存在: 999999`;只传 `ip` 而 IP 解析不出 —— `用户 IP 无法解析出归属地: 1.2.3.4`;IP 地区与省码都挑不到 —— `该地区没有可用门店: 省 320000`(`ip` 解析到了市时形如 `该地区没有可用门店: 430100(省 430000)`)。「可用门店」= 10.1 建号成功(`create_status=SUCCESS`)且地区与所传编码一致的门店;2026-10-08 之前建的门店没有地区,不会被挑中(见 10.1 的警告)。
-> - **传了任一门店编码时,这两个字段被忽略**(显式指定优先,平台不会用挑出来的店覆盖你指定的店)。
+|---|---|----|---|
+| `merchant_code` | string | 否  | **你租户下配了多个商户号时必填**:这笔钱收进哪一个商户,见本章开头 |
+| `price` | number | 是  | 金额,**单位元**,必须 > 0,见下 |
+| `title` | string | 是  | 商品名称,≤64 字符 |
+| `out_biz_no` | string | 否  | 你自己的订单号,≤64 字符,原样存下供你查询 |
+| `shop_code` | string | 否  | 平台门店编号 |
+| `third_shop_code` | string | 否  | 门店编码 |
+| `ip` | string | 是  | 顾客用户端ip |
+| `pay_timeout` | int | 否  | 支付过期时间,取值 2–60(单位由上游定义,平台原样透传) |
 
 **响应**(B 型,`data` 内)
 
 | 字段 | 说明 |
 |---|---|
-| `order_no` | **平台订单号**,后续查询(10.3)用它 |
+| `order_no` | **平台订单号**,后续查询(10.2)用它 |
 | `out_biz_no` | 原样返回 |
 | `upstream_order_no` | 上游订单号。下单成功才有值,下单超时时为空 |
 | `platform_trade_no` | 平台交易号,支付成功后才有值 |
-| `pay_url` | **主扫**:收款链接,渲染成二维码即可。**被扫**:为空 |
-| `trade_status` | 订单状态,见 10.6 |
+| `pay_url` | 收款链接,渲染成二维码即可 |
+| `trade_status` | 订单状态,见 10.5 |
 | `price` | 订单金额(元) |
-| `title` / `trade_type` / `stage_num` / `percent` | 原样返回 |
-| `shop_code` / `third_shop_code` | 你传的那个原样返回;按地区挑店时 `third_shop_code` 是**挑中的那家** |
+| `title` | 原样返回 |
+| `shop_code` / `third_shop_code` | 你传的门店编码原样返回 |
 | `trade_time` | 支付成功时间 |
 | `rcv_amount` | 实收金额(元),支付成功后有值 |
 | `fee_amount` / `channel_amount` | 手续费 / 渠道金额 |
 | `refund_time` | 退款时间。退款到账(`trade_status` 为 `"2"`)后才有值 |
-| `notify_status` | 平台向你推送回调的结果,见 10.5 |
+| `notify_status` | 平台向你推送回调的结果,见 10.4 |
 | `created_time` / `updated_time` | 记录时间 |
 
-> ⚠️ **本接口不幂等 —— 重复调用会产生两笔订单、两次扣款。** 每次调用都会生成一个新的 `order_no` 并向上游发起一笔新的交易,平台**不做** `out_biz_no` 去重(也不做唯一约束)。超时后不要直接重发:先用 **10.3 订单查询** 按 `out_biz_no` 查一次,查到就用那一笔的结果。
+> ⚠️ **本接口不幂等 —— 重复调用会产生两笔订单、两次扣款。** 每次调用都会生成一个新的 `order_no` 并向上游发起一笔新的交易,平台**不做** `out_biz_no` 去重(也不做唯一约束)。超时后不要直接重发:先用 **10.2 订单查询** 按 `out_biz_no` 查一次,查到就用那一笔的结果。
 
-> ⚠️ **`price` 的单位是「元」,是小数,不是「分」。** `1.5` 表示 1 元 5 角;5 章那一套要写 `total_amount=150` 才是同样的金额。**跨通道搬代码时这是最容易错的一处。**
+> ⚠️ **`price` 的单位是「元」,是小数,不是「分」。** `1.5` 表示 1 元 5 角;把「元」当「分」写会差 100 倍。
 
 > ⚠️ **金额的写法会直接影响签名。** 签名是对你**实际发出的那个值**做字符串化后算的(3.3),而平台把 JSON 数字读成双精度数:你写 `0.010`,平台看到的是 `0.01` —— 签名因此对不上,只会返回「签名验证失败」,不会告诉你原因。**请写成不带多余零的最简小数**(`0.01` / `1.5` / `100`),不要写 `0.010`、`1.50`。写成字符串(`"price": "0.01"`)也可以,字符串原样参与签名,最不容易出错。
 
-> ⚠️ **下单失败时本地记录仍在,不要当作「什么都没发生」。** 上游调用失败会以 `code=500` 返回(`msg` 形如 `下单失败: <原因>`),但平台**已经落了本地记录并排入了状态轮询** —— 这笔交易仍可能成功。收到失败后请用 10.3 确认,不要凭这一次返回就向用户宣称交易未发生。
+> ⚠️ **下单失败时本地记录仍在,不要当作「什么都没发生」。** 上游调用失败会以 `code=500` 返回(`msg` 形如 `下单失败: <原因>`),但平台**已经落了本地记录并排入了状态轮询** —— 这笔交易仍可能成功。收到失败后请用 10.2 确认,不要凭这一次返回就向用户宣称交易未发生。
 
 ---
 
-### 10.3 订单查询
+### 10.2 订单查询
 
 ```
 POST /payment/openapi/alipay/order/query
@@ -168,11 +76,11 @@ POST /payment/openapi/alipay/order/query
 
 | 字段 | 类型 | 必填 | 说明 |
 |---|---|---|---|
-| `merchant_code` | string | 否 | **你租户下配了多个商户号时必填**,与上面两个接口同一个值。传了就只查这个商户的订单 |
-| `order_no` | string | 二选一 | 平台订单号(10.2 响应里的 `order_no`) |
+| `merchant_code` | string | 否 | **你租户下配了多个商户号时必填**,与其它接口同一个值。传了就只查这个商户的订单 |
+| `order_no` | string | 二选一 | 平台订单号(10.1 响应里的 `order_no`) |
 | `out_biz_no` | string | 二选一 | 你自己的订单号 |
 
-**响应**(B 型,`data` 内)—— 字段与 10.2 的响应一致,另加:
+**响应**(B 型,`data` 内)—— 字段与 10.1 的响应一致,另加:
 
 | 字段 | 说明 |
 |---|---|
@@ -182,11 +90,11 @@ POST /payment/openapi/alipay/order/query
 
 > `order_no` 与 `out_biz_no` 都没传,返回 `code=500`,`msg` 为 `order_no 与 out_biz_no 至少填一个`。
 
-> ⚠️ **查不到订单时返回的是 `code=500`,不是 `404`。** 这与 5.4 的行为不同。`msg` 为 `订单不存在`。**不属于你的订单也返回同一个 `msg`** —— 平台有意不区分「不存在」与「不属于你」,避免被用来探测他人订单是否存在。
+> ⚠️ **查不到订单时返回的是 `code=500`,不是 `404`。** `msg` 为 `订单不存在`。**不属于你的订单也返回同一个 `msg`** —— 平台有意不区分「不存在」与「不属于你」,避免被用来探测他人订单是否存在。
 
 ---
 
-### 10.4 订单退款
+### 10.3 订单退款
 
 对一笔**已支付成功**的订单发起退款。
 
@@ -194,12 +102,12 @@ POST /payment/openapi/alipay/order/query
 POST /payment/openapi/alipay/refund
 ```
 
-**请求**(`order_no` 与 `out_biz_no` **至少提供一个**,规则同 10.3)
+**请求**(`order_no` 与 `out_biz_no` **至少提供一个**,规则同 10.2)
 
 | 字段 | 类型 | 必填 | 说明 |
 |---|---|---|---|
-| `merchant_code` | string | 否 | **你租户下配了多个商户号时必填**,与其它三个接口同一个值 |
-| `order_no` | string | 二选一 | 平台订单号(10.2 响应里的 `order_no`) |
+| `merchant_code` | string | 否 | **你租户下配了多个商户号时必填**,与其它接口同一个值 |
+| `order_no` | string | 二选一 | 平台订单号(10.1 响应里的 `order_no`) |
 | `out_biz_no` | string | 二选一 | 你自己的订单号 |
 | `reason` | string | 否 | 退款原因。**留空时平台补一个默认值**(`商户申请退款`);填了就以你填的为准 |
 
@@ -207,20 +115,20 @@ POST /payment/openapi/alipay/refund
 
 > ℹ️ **`reason` 为什么是选填**:通道上游把它列为必填,但没公布长度上限,所以平台不强制你填 —— 留空就替你补一个默认值,不会因此失败。想在自己的账上区分退款来源就填上。
 
-**响应**(B 型,`data` 内):结构与 10.3 完全相同(同一份订单)。
+**响应**(B 型,`data` 内):结构与 10.2 完全相同(同一份订单)。
 
 > ⚠️ **返回时 `trade_status` 是 `"4"`(退款中),不是 `"2"`。** 同步返回只代表平台已把退款指令发给上游,**不代表钱已经退回用户账上**。
 
-**结果怎么收敛**:`"4"` 由平台的查询任务持续向上游确认,直到拿到终态(上游若推了通知,平台也会转推给你,见 10.5):
+**结果怎么收敛**:`"4"` 由平台的查询任务持续向上游确认,直到拿到终态(上游若推了通知,平台也会转推给你,见 10.4):
 
 | 最终 `trade_status` | 含义 |
 |---|---|
 | `"2"` | **退款成功,钱已退回** |
 | `"1"` | 退款**没有发生**,订单回到已支付 |
 
-> ⚠️ **不要把 `"4"` 当成已退款,也不要凭它给用户承诺到账。** 用户看到的是钱有没有回来,不是接口返回了什么。同 10.5 的提醒:通知可能丢,**请对停在 `"4"` 的订单做主动查询兜底**。
+> ⚠️ **不要把 `"4"` 当成已退款,也不要凭它给用户承诺到账。** 用户看到的是钱有没有回来,不是接口返回了什么。同 10.4 的提醒:通知可能丢,**请对停在 `"4"` 的订单做主动查询兜底**。
 
-> ⚠️ **只有 `trade_status = "1"` 的订单能退款。** 其它状态(`"0"` / `"4"` / `"2"` / `"8"`)一律拒绝,`code=500`,`msg` 形如 `订单当前状态不可退款: <状态值>`。查不到订单、或不是你的订单,仍然是 10.3 那句 `code=500` 的 `订单不存在`。
+> ⚠️ **只有 `trade_status = "1"` 的订单能退款。** 其它状态(`"0"` / `"4"` / `"2"` / `"8"`)一律拒绝,`code=500`,`msg` 形如 `订单当前状态不可退款: <状态值>`。查不到订单、或不是你的订单,仍然是 10.2 那句 `code=500` 的 `订单不存在`。
 
 **重复调用会怎样** —— 这是最容易误解的一处:
 
@@ -231,8 +139,8 @@ POST /payment/openapi/alipay/refund
 
 | 返回 | 订单状态 | 你该做什么 |
 |---|---|---|
-| `code=500`,`msg` 形如 `退款失败: <原因>` | **退回 `"1"`** | 上游明确拒绝了,什么都没发生。可用 10.3 确认状态是 `"1"` 后**重新发起** |
-| `code=500`,`msg` 为 `退款结果未知(上游未响应),订单已置为退款中,请稍后查询订单状态确认` | **保持 `"4"`** | 上游没应答,**这笔退款可能已经发生**。**不要重发** —— 用 10.3 查到终态为止 |
+| `code=500`,`msg` 形如 `退款失败: <原因>` | **退回 `"1"`** | 上游明确拒绝了,什么都没发生。可用 10.2 确认状态是 `"1"` 后**重新发起** |
+| `code=500`,`msg` 为 `退款结果未知(上游未响应),订单已置为退款中,请稍后查询订单状态确认` | **保持 `"4"`** | 上游没应答,**这笔退款可能已经发生**。**不要重发** —— 用 10.2 查到终态为止 |
 
 > ⚠️ **两条路都是 `code=500`,只能靠 `msg` 区分。** 拿不准时一律按「结果未知」处理(不重发、去查询):重发一笔可能已经退掉的款是真实资金损失,多查一次只是麻烦。
 
@@ -240,11 +148,11 @@ POST /payment/openapi/alipay/refund
 
 ---
 
-### 10.5 回调通知
+### 10.4 回调通知
 
 订单状态变化时,平台会向你推送一条回调。
 
-**回调地址取自你这把 API Key 上配置的 `return_url`**(未配置时退回该租户的默认回调地址)。**没配时平台不会丢下这笔** —— 记一次推送失败并继续重试(见下),你补配地址后未达上限的订单仍会收到;但尽快补配,超过上限就不会再推了,届时只能靠主动查询(10.3)拿结果。
+**回调地址取自你这把 API Key 上配置的 `return_url`**(未配置时退回该租户的默认回调地址)。**没配时平台不会丢下这笔** —— 记一次推送失败并继续重试(见下),你补配地址后未达上限的订单仍会收到;但尽快补配,超过上限就不会再推了,届时只能靠主动查询(10.2)拿结果。
 
 ```
 POST <你的 return_url>
@@ -271,7 +179,6 @@ Content-Type: application/x-www-form-urlencoded
   "third_shop_code": "S001",
   "price": 1.50,
   "title": "测试商品",
-  "trade_type": "alipay_un_stage",
   "status": "1",
   "trade_time": "2026-09-24T10:30:00+08:00",
   "refund_time": null,
@@ -283,9 +190,9 @@ Content-Type: application/x-www-form-urlencoded
 
 金额字段是 **JSON 数字**(不是字符串);时间字段是 **ISO-8601 带时区偏移**的字符串。
 
-> ⚠️ **回调里的 `order_no` 与 10.2 响应里的 `order_no` 不是同一个号。**
-> 回调里的 `order_no` 是**上游订单号**(等于 10.2 响应里的 `upstream_order_no`);
-> 回调里的 `third_order_no` 才是**平台订单号**(等于 10.2 响应里的 `order_no`)。
+> ⚠️ **回调里的 `order_no` 与 10.1 响应里的 `order_no` 不是同一个号。**
+> 回调里的 `order_no` 是**上游订单号**(等于 10.1 响应里的 `upstream_order_no`);
+> 回调里的 `third_order_no` 才是**平台订单号**(等于 10.1 响应里的 `order_no`)。
 > 名字是反的,但对账必须靠它们,请按这层对应关系取用。
 > **最省事的做法:始终用你自己生成的 `out_biz_no` 作主键做幂等,不要依赖这两个 `order_no`。**
 
@@ -299,11 +206,11 @@ Content-Type: application/x-www-form-urlencoded
 
 > ⚠️ **退款的最终结果(`"4"` → `"2"` / `"1"`)走的是同一条回调**,`content.status` 里就是新状态,`refund_time` 也在里面。所以上面的兜底对退款**同样适用,而且更要紧**:退款停在 `"4"` 时你等的是钱有没有回来,回调不响就只能自己查。**给长期停在 `"4"` 的订单也做主动查询。**
 
-> ⚠️ **回调不带签名。** 与 7.2 的情况相同 —— 不能仅凭收到回调就认定收款成功。请以 **10.3 订单查询** 的结果为准,把回调当作「该查了」的触发信号。
+> ⚠️ **回调不带签名。** 不能仅凭收到回调就认定收款成功。请以 **10.2 订单查询** 的结果为准,把回调当作「该查了」的触发信号。
 
 ---
 
-### 10.6 状态说明
+### 10.5 状态说明
 
 **`trade_status` 是数字字符串**(JSON 里带引号,不是数字):
 
@@ -316,9 +223,7 @@ Content-Type: application/x-www-form-urlencoded
 | `"8"` | 交易关闭 | 是 |
 
 判断「是否收到过钱」用 `"1"` / `"2"`;判断「是否还要等」用 `"0"` / `"4"`。
-判断「退款是否已经到账」只看 `"2"` —— 停在 `"4"` 表示平台还在向上游确认,**不代表已退**(见 10.4)。
-
-**门店 `create_status`**:`SUCCESS` / `FAILED` / `PENDING`,见 10.1。
+判断「退款是否已经到账」只看 `"2"` —— 停在 `"4"` 表示平台还在向上游确认,**不代表已退**(见 10.3)。
 
 **订单 `notify_status`**(平台向你推送回调的结果):
 
@@ -333,17 +238,13 @@ Content-Type: application/x-www-form-urlencoded
 ## 11. 门店与订单通道的联调检查清单
 
 - [ ] 认证与签名复用 3.3 的实现,先跑通 3.4 的样例
-- [ ] 建号带了 `province_code` / `city_code`(GB/T 2260 完整六位),且市码属于该省码
-- [ ] 不指定门店下单时传了 `ip`(**顾客**的公网 IP)或 `province_code`,且拿响应里的 `third_shop_code` 核对了挑中的门店
 - [ ] `price` 用**元**、写成最简小数(不要 `1.50`、`0.010`)
-- [ ] 下单**不重发** —— 超时先查 10.3,确认没有再决定
-- [ ] `auth_code` 有值走被扫、不传走主扫,两种都测过
-- [ ] 主扫拿到了 `pay_url` 并能渲染成二维码
+- [ ] 下单**不重发** —— 超时先查 10.2,确认没有再决定
+- [ ] 拿到了 `pay_url` 并能渲染成二维码
 - [ ] 按 `trade_status` 的**数字字符串**分支处理(`"1"` 才是钱到账)
 - [ ] 回调接口能处理表单编码,并把 `content` **再解析一次** JSON
 - [ ] 回调按 `out_biz_no` 做幂等
 - [ ] 对长期停在 `"0"` 的订单有主动查询兜底
-- [ ] 退款只对 `trade_status = "1"` 的订单发起,且发起前用 10.3 确认过没有退过
-- [ ] 退款返回 `退款结果未知…` 时**不重发**,改用 10.3 查到终态
+- [ ] 退款只对 `trade_status = "1"` 的订单发起,且发起前用 10.2 确认过没有退过
+- [ ] 退款返回 `退款结果未知…` 时**不重发**,改用 10.2 查到终态
 - [ ] 退款结果按 `"2"`(已到账)判定,不把 `"4"` 当已退款
-- [ ] 门店 `create_status` 收到 `PENDING` 时走人工核实,不自行重发

+ 2 - 3
frontend/src/views/module_payment/apikey/harDoc.ts

@@ -11,10 +11,9 @@ import { buildSections, type DocSectionDef } from "./docSlicer";
  * 侧边栏条目定义。键即 `activeSection` 的值。
  * `parts` 里的标题必须与 md 里的标题**逐字一致**(含空格、全角括号)。
  *
- * 整章只给一个条目,不再拆成 10.1~10.6 —— 章首那张差异表(金额单位、幂等性)
- * 必须先读,拆开会让读者直接跳到 10.2 下单。
+ * 整章只给一个条目,不拆成 10.1~10.5(各小节互相引用,拆开会让读者跳读)。
  * 注意:`take("## 10. …")` 会一并吞掉其下所有 `###` 子块,所以这里**不能**改写成
- * 「## 10 + 各 ### 分开列」—— 那样差异表会被重复渲染五次。
+ * 「## 10 + 各 ### 分开列」—— 那样各小节会被重复渲染。
  */
 const SECTIONS: DocSectionDef[] = [
   {