Files
hjc-web/app/components/HjcPayQrcode.vue
T
weicw1996 5b6e1b67bc 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 里。
2026-09-17 02:32:39 +08:00

44 lines
1.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<img
v-if="dataUrl"
:src="dataUrl"
:width="size"
:height="size"
:alt="alt"
class="mx-auto block"
/>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { renderSVG } from 'uqr'
/**
* 支付二维码(纯展示)。内容是后端下发的**支付链接** `codeUrl`,不是网址——
* 它只能被微信扫,点不开。见 CONTEXT.md 的「支付链接」与「支付二维码」。
*/
const props = withDefaults(defineProps<{
/** 要编码的内容(支付链接 `codeUrl`);为空时不渲染任何东西 */
value?: string
/** 边长(像素) */
size?: number
alt?: string
}>(), {
value: '',
size: 240,
alt: '微信支付二维码'
})
/**
* 输出 `data:` URL 而不是 `v-html`
* 内容是本地编码出的 SVG、不含任何外部引用,同时避开 `vue/no-v-html`。
* 纠错级别取 M(约 15%),与主流收银台二维码一致——支付码是短串,密度代价很小。
*/
const dataUrl = computed(() => {
const text = (props.value || '').trim()
if (!text) return ''
const svg = renderSVG(text, { border: 2, ecc: 'M' })
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`
})
</script>