feat(tender): 支付链接改为站内二维码,支付确认改走微信侧查单

- BuyDocument:支付步骤原先把后端 Native 下单返回的 codeUrl(weixin://wxpay/...)当明文
  链接渲染成一个 <a target="_blank">,而 weixin:// 在浏览器里点击没有任何有效行为——标题写
  着「请使用微信扫码支付」,页面上却没有二维码,PC 端 Native 支付实质不可用。改为渲染真正
  的二维码,并删掉那个链接。
- HjcPayQrcode(新):uqr 站内生成,renderSVG() → data:image/svg+xml → <img :src>。不用
  v-html(避开 vue/no-v-html),不用第三方外链(hjc-h5 用的 api.qrserver.com 在境内不可靠,
  且等于把支付凭据交给第三方),也不改后端契约。
- useHjcPayStatus(新):支付结果一律以**微信侧**为准——轮询 pay-status(3s,页面隐藏暂停,
  2 小时上限),手动「我已完成支付」按钮也走同一条查单通道。原先只有 mark-paid 一条路,而它
  不向微信查单(HjcOrderController 的 javadoc 自陈「订单置为已支付只有 /mark-paid 一条路」),
  用户一分钱不付、点一下就能把订单置为已支付并触发一站式推送。故 hjc-web 弃用它,并删除
  server/api/tender/mark-paid.put.ts,不留这个入口给下一个人误用。
- 查单的另一好处:微信已支付而本地仍未支付时它会就地补写状态(幂等)。于是「付了钱但页面被
  关掉/断网」这类漏单能被认出来——进入支付步骤即开始轮询,正是为了认出这种订单。
- 拿不到二维码时(例如租户支付配置错误)不再显示空白卡片,而是失败原因 +「重新获取二维码」。
  微信 Native 码默认 2 小时且服务端不下发 expireTime,故按发起支付时刻本地计时,过期把二维码
  置灰并提示重新获取;「重新获取二维码」重调 /api/tender/pay(同 out_trade_no 的 Native→
  Native 重下微信允许)。
- 由此 hjc-web 与 hjc-h5/小程序端的支付确认语义**有意不一致**(那两端仍在用 mark-paid,改动
  它们等于同时动三端线上支付路径)。理由与边界记在 ADR 0009。
- 依赖:新增 uqr;两份锁文件同步更新(pnpm 装,package-lock.json 同步)。
- 删除 BUY_TENDER_MAP_REPORT.md:530 行历史快照,结论与现状全面矛盾(称购买流程是桩函数、
  /buy 不可用、没有登录流程、pay 代理路径写错),已实际误导过一次调研;历史价值留在 git 里。
This commit is contained in:
2026-09-17 02:32:39 +08:00
parent 32098b69ac
commit 5b6e1b67bc
8 changed files with 337 additions and 563 deletions
+7 -4
View File
@@ -20,12 +20,19 @@ importers:
nuxt:
specifier: ^4.2.2
version: 4.4.8(@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7))(@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7))(@parcel/watcher@2.5.6)(@types/node@25.9.5)(@vue/compiler-sfc@3.5.40)(cac@6.7.14)(db0@0.3.4)(esbuild@0.28.1)(eslint@9.39.5(jiti@2.7.0))(ioredis@5.11.1)(magicast@0.5.3)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1(rollup@4.62.2))(rollup@4.62.2)(srvx@0.11.22)(terser@5.49.0)(typescript@6.0.3)(vite@7.3.6(@types/node@25.9.5)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(yaml@2.9.0)
uqr:
specifier: ^0.1.3
version: 0.1.3
vue:
specifier: ^3.5.26
version: 3.5.40(typescript@6.0.3)
vue-router:
specifier: ^4.6.4
version: 4.6.4(vue@3.5.40(typescript@6.0.3))
optionalDependencies:
'@oxc-parser/binding-darwin-arm64':
specifier: ^0.105.0
version: 0.105.0
devDependencies:
'@eslint/js':
specifier: ^9.39.2
@@ -51,10 +58,6 @@ importers:
typescript-eslint:
specifier: ^8.50.1
version: 8.64.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
optionalDependencies:
'@oxc-parser/binding-darwin-arm64':
specifier: ^0.105.0
version: 0.105.0
packages: