|
|
@@ -20,14 +20,15 @@
|
|
|
8. 常设约束:验签绝不跳过;文案不暴露上游;开发测试期先用文档给的测试信息把支付与收款生命周期走通,线上必须先进件。
|
|
|
9. **(2026-09-22 追加,推翻第 1 条里「一单一码」的隐含前提)群收款场景**:商户拿到**一个长期固定的收款码**发到群里,群里任何人扫这个码进收银台,**顾客自己输入金额**、点确认,**直接唤起对应的支付 App**。用户逐字口径:
|
|
|
- 「其实就是提供一个链接或者二维码,指向系统收银台前端,链接或二维码需要**绑定生成的商户**」
|
|
|
- - 「需要**区分微信和支付宝两种二维码**,商户生成微信二维码则发到微信群,支付宝二维码则发给支付宝用户,输入完金额后**直接要唤起对应的 app 支付**」
|
|
|
+ - ~~「需要**区分微信和支付宝两种二维码**,商户生成微信二维码则发到微信群,支付宝二维码则发给支付宝用户,输入完金额后**直接要唤起对应的 app 支付**」~~ **(2026-09-22 撤销,见下方第 ④ 条裁定)**
|
|
|
- 「**可建多个,带名称**」
|
|
|
- 扫码环境三者都要覆盖:**微信群 / 微信内置浏览器、手机相机 / 普通浏览器、支付宝扫**
|
|
|
|
|
|
本条的实测可行性见 §2.4,落地设计见 §4。**§4 已按本条重写**;第 1 条中「返回收银台页面链接」的结论仍成立,但「一单一码、商户先输金额、收银台只做展示」不成立。
|
|
|
|
|
|
- 用户就本条追加的三条裁定(2026-09-22):
|
|
|
- - **渠道不符不用管**:「微信扫不了支付宝的码,反过来也是一样,不用管」⇒ 不做硬拦、不做提示(落点 §4.2)
|
|
|
+ 用户就本条追加的裁定(2026-09-22):
|
|
|
+ - **渠道不符不用管**:「微信扫不了支付宝的码,反过来也是一样,不用管」⇒ 不做硬拦、不做提示(落点 §4.2)。**该条 2026-09-22 晚些时候因第 ④ 条失去对象**:码上不再有渠道,「不符」无从谈起。
|
|
|
+ - **④ 不区分渠道**:用户问「能做到一个码微信和支付宝都能用吗?」⇒ **能,且原设计已经就是这样**(证据链见 §4.2)⇒ 裁定**去掉 `pay_receive_code.channel` 列**,并撤销上面第 ② 条口径。普通浏览器那条腿改由顾客点选渠道(落点 §4.4)。
|
|
|
- **收银台域名与 `notify-url` 同源**(落点 §5.3)
|
|
|
- **开放接口不改**:「一般人不会抓包,就算抓包也抓不到什么有用的信息」⇒ 原「`codeUrl` → `cashierUrl`」提案作废(落点 §4.7)
|
|
|
- **金额范围**:下限 `0.01` 元、**上限不额外限制**(落点 §5.3)
|
|
|
@@ -129,7 +130,7 @@
|
|
|
|---|---|---|
|
|
|
| 微信内置浏览器(群里扫码) | `v3/jspay` `pay_type=400` | `WeixinJSBridge` **原生唤起微信支付** |
|
|
|
| 支付宝内置浏览器 | `v3/jspay` `pay_type=300` | `ali_trade_no` 调起支付宝 |
|
|
|
-| 普通浏览器(手机相机扫 / 电脑打开) | `v3/h5pay` | 返回跳转 URL,`location` 过去 |
|
|
|
+| 普通浏览器(手机相机扫 / 电脑打开) | `v3/h5pay` | 返回跳转 URL,`location` 过去;**渠道由顾客在页面上点选**(见下) |
|
|
|
|
|
|
**仍待上游确认**(外部依赖,不阻塞本地开发,测试环境已证明不校验):
|
|
|
1. `redirect_uri` 在**正式环境**是否需要预先登记白名单(测试环境实测未校验);
|
|
|
@@ -205,20 +206,29 @@ DDL(唯一一处,见 §7):
|
|
|
| `code_no` | **URL 短码,32 位随机,不可枚举**(沿用旧设计对收银台令牌的要求) |
|
|
|
| `name` | 名称,商户自取(「前台」「3 号桌」) |
|
|
|
| `merchant_id` | → `pay_lsy_merchant.id`。**码绑定到哪个商户**,用户口径第 ① 条 |
|
|
|
-| `channel` | **复用既有枚举 `LsyPayType`**:`WECHAT`/`ALIPAY`(上游值 `400`/`300`)。用户口径第 ② 条 |
|
|
|
+| ~~`channel`~~ | **2026-09-22 删除** —— 码不分渠道,理由见下 |
|
|
|
| `status` | 启用 / 停用 |
|
|
|
| `remark` | 备注 |
|
|
|
| `created_time` / `updated_time` | 同全库约定 |
|
|
|
|
|
|
约束:`code_no` 全局唯一;`(tenant_id, name)` 唯一(同名无法管理)。
|
|
|
|
|
|
-⚠ **`channel` 是「这个码发给谁」的标记,不参与任何服务端判断。** 真实走哪条通道**只以 UA 为准**(§4.4)。
|
|
|
+**为什么不分渠道(2026-09-22 定)**
|
|
|
|
|
|
-用户 2026-09-22 裁定:「微信扫不了支付宝的码,反过来也是一样,**不用管**」⇒ 不做硬拦,**也不做「渠道不符」的提示**。`channel` 只用于管理端列表的区分与筛选,**收银台逻辑里一行都不读它**。
|
|
|
+用户问「能做到一个码微信和支付宝都能用吗?」——**能,而且原设计就已经是这样**,只是被一个多余的列挡住了:
|
|
|
|
|
|
-技术备注(不影响上面的裁定,也不改变任何实现):**我们的二维码内容是自己的 URL**(§4.5),两种码长得一模一样,区别只在管理端那个 `channel` 标签。所以「微信扫不了支付宝的码」在技术上未必成立。但**成立与否结论都一样**——因为分流是按 UA 做的(§4.4):**实测**同一个 `getauth2` 端点,微信 UA 与支付宝 UA **都会**被静默授权,只有其他 UA 才报错。真扫到了,顾客仍会被带到能付成的那条通道。
|
|
|
+1. 二维码里编的是**我们自己的地址** `https://<收银台域名>/payment/cashier/{codeNo}`(§4.5),**不是**微信或支付宝的专属链接;
|
|
|
+2. 两个 App 的「扫一扫」扫到 URL 都用各自内置浏览器打开(**平台既定行为,本项目未实测**);
|
|
|
+3. 进了收银台页之后**分流按 UA 做,与码本身无关**(§4.4)。
|
|
|
|
|
|
-⚠ 分清上面两句的性质:「两个渠道都静默授权」是**实测**;「所以顾客一定能付成」是我由实测推出的**推断**,没在真机走过完整一单。这是**联调时要验的项**,不是已证事实。
|
|
|
+⇒ 所谓「微信码」与「支付宝码」的二维码图像**逐像素相同**;`channel` 唯一作用是管理端列表上那个标签。故删列,§0.9 口径第 ② 条同时撤销。
|
|
|
+
|
|
|
+**证据强度要分清**(§11.2 第 1/2 条要验):
|
|
|
+
|
|
|
+- **实测** —— 上游 `getauth2` 同一个端点,微信 UA 与支付宝 UA **都会被静默授权**,只有其他 UA 报错(§2.4)。
|
|
|
+- **推断(未实测)** —— 因此顾客一定能付成。**没在真机走过完整一单**,不是已证事实。
|
|
|
+
|
|
|
+用户此前「微信扫不了支付宝的码,反过来也是一样,不用管」那条裁定**仍然成立**,且现在自动满足:码上根本没有渠道,「不符」无从发生。
|
|
|
|
|
|
### 4.3 免鉴权收银台页
|
|
|
|
|
|
@@ -278,6 +288,16 @@ GET /payment/cashier/{codeNo}/auth
|
|
|
|
|
|
**普通浏览器**(手机相机扫、电脑打开):`WeixinJSBridge` 不存在,两个 JSAPI 都不适用,走 H5 支付。服务端下单后**自己 302** 过去,上游链接不下发到浏览器。
|
|
|
|
|
|
+⚠ **这一条腿的渠道必须顾客选**(2026-09-22 定,因为 `channel` 列已删,§4.2)。理由是两头都堵死了:
|
|
|
+
|
|
|
+- `h5pay` 的 `pay_type` 是**必填**(`M`:300 支付宝 / 400 微信 / 600 云闪付,page 196236551)——**不能省**;
|
|
|
+- 普通浏览器里 UA 只能告诉我们「不是微信也不是支付宝」,**推不出顾客装了哪个 App**,也没有 `channel` 可读。
|
|
|
+
|
|
|
+⇒ **收银台页在这一条腿上渲染两个按钮(微信支付 / 支付宝支付)**,顾客点哪个就用哪个 `pay_type` 下单。
|
|
|
+另两条腿(微信/支付宝内置浏览器)**不出现按钮**——UA 已知,直接唤起。
|
|
|
+
|
|
|
+> 可选优化(**未实测,不作为本期方案**):上游 `/v3/qrpay` 是聚合码接口,描述逐字「创建订单生成**包含微信、支付宝**的二维码链接」,**没有 `pay_type` 入参**。若它在**普通浏览器**里打开也能分流,这条腿就不需要顾客选了。列入 §11.2 第 6 条待验;验通了可以去掉按钮。
|
|
|
+
|
|
|
**字段名口径**:`pay` 只回微信/支付宝自己的唤起参数名。`appId`/`timeStamp`/`nonceStr`/`packages`/`signType`/`paySign` 是微信 JSAPI 的**既定名,必须原样**(改了 `WeixinJSBridge` 不认),但它们属于微信、不暴露上游。**不回上游订单号、不回上游域名、不回上游任何字段名。**
|
|
|
|
|
|
**支付结果的真实性**:`WeixinJSBridge` 的回调**只用来做提示、不作为成功依据**——用户中途退出、网络抖动都会让它丢。真实状态由前端轮询 `GET ./{codeNo}/status` 得到,最终以上游异步回调落库的状态为准(回调链路在批次一之前就有,不在本轮改动范围)。
|
|
|
@@ -517,7 +537,6 @@ CREATE TABLE IF NOT EXISTS pay_receive_code (
|
|
|
code_no VARCHAR(64) NOT NULL,
|
|
|
name VARCHAR(64) NOT NULL,
|
|
|
merchant_id BIGINT NOT NULL,
|
|
|
- channel VARCHAR(16) NOT NULL,
|
|
|
status VARCHAR(32) NOT NULL DEFAULT 'ENABLED',
|
|
|
remark VARCHAR(255),
|
|
|
created_time TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
|
|
|
@@ -588,7 +607,7 @@ CREATE INDEX IF NOT EXISTS idx_receive_code_mch ON pay_receive_code (merc
|
|
|
|
|
|
**已裁定:**
|
|
|
|
|
|
-5. ~~渠道不符怎么办~~ → **不用管**(用户逐字:「微信扫不了支付宝的码,反过来也是一样,不用管」)。落点见 §4.2:不做硬拦、不做提示,`channel` 不参与服务端判断。**已落地文档。**
|
|
|
+5. ~~渠道不符怎么办~~ → **不用管**(用户逐字:「微信扫不了支付宝的码,反过来也是一样,不用管」)。**已落地文档,且 2026-09-22 晚些时候因删掉 `channel` 列而自动满足**:码上不再有渠道,「不符」无从发生。§4.2 有完整理由链。
|
|
|
7. ~~收银台对外域名~~ → **与 `notify-url` 同源**(用户答「可以」)。落点见 §5.3。**已落地文档。**
|
|
|
|
|
|
**已裁定:**
|
|
|
@@ -608,5 +627,6 @@ CREATE INDEX IF NOT EXISTS idx_receive_code_mch ON pay_receive_code (merc
|
|
|
| 1 | **真机走通完整一单**(三通道各一次) | 未做。本文档所有「能付成」都是从实测推出的**推断** | 微信内扫码 → 输金额 → 唤起 → 支付成功 → 回调入账 |
|
|
|
| 2 | 支付宝侧的**回跳与唤起**(不是字段名——字段名文档已明写,见 §2.4 订正) | 微信侧实测可达;支付宝侧只验到「UA 会被静默授权」这一步 | 同上,走一单真支付宝:看回跳带没带 `openid`、`jspay` 回没回 `ali_trade_no` |
|
|
|
| 3 | **上游回跳时 `?openid=` 是怎么拼上去的** | 文档示例里 redirect_uri 带 query 时拼 `&openid=`,还会插一个 `/`;**我们的 redirect_uri 不带 query**,那到底拼 `?` 还是 `&`、会不会插 `/`——**没实测过**(探针没走完整趟 OAuth) | 真机看回跳 URL 原文;若拼错,`/auth` 侧要能容错解析 |
|
|
|
-| 4 | 普通浏览器(手机相机扫)走 `v3/h5pay` 的兜底 | `h5pay` 本身实测过(对照探针 `PAY_SUCCESS`),但**没串进收银台链路** | 用相机扫码走一遍 |
|
|
|
+| 4 | 普通浏览器(手机相机扫)走 `v3/h5pay` 的兜底,**含顾客点选渠道那两个按钮** | `h5pay` 本身实测过(对照探针 `PAY_SUCCESS`),但**没串进收银台链路**;两个按钮是 2026-09-22 新增的设计,**零实测** | 用相机扫码走一遍:**两个渠道各点一次**,看 400 和 300 是否都跳到对应 App |
|
|
|
| 5 | 上游 `redirect_uri` 正式环境是否要预登记白名单 | 未知(测试环境实测未校验) | 问上游(§11.1 第 8 条) |
|
|
|
+| 6 | **(可选优化)`/v3/qrpay` 的聚合码 `code_url` 在普通浏览器里能不能两端分流** | 未测。文档只写「在支付宝或微信中打开支付链接完成支付」,**没写普通浏览器**。若成立,第 4 条的按钮可以去掉,一条腿也变成零交互 | 建一笔 `qrpay` 单,把 `code_url` 在 Chrome/Safari 里打开,看是否给出渠道选择或自动分流 |
|