2026-10-28 19:10:39 +08:00
11
2026-10-28 19:10:39 +08:00
11
2026-10-28 19:10:39 +08:00
2026-10-20 13:45:05 +08:00
11
2026-10-28 18:49:38 +08:00
11
2026-10-28 18:49:38 +08:00
11
2026-10-28 19:10:39 +08:00

商户付款 H5

uni-app Vue 3 + TypeScript + UnoCSS + tm-ui 的独立 H5 项目。工程与蓝色主题参考 ../biz_zax_app_cloud,提供商户收银与付款结果页面,默认中文、人民币、浅色主题。

本地开发

要求 Node.js 20.19+、pnpm 10.13.0。

pnpm install --frozen-lockfile
pnpm dev:h5

浏览器访问 http://localhost:8890/。同一局域网内可使用本机 IP 和 8890 端口进行手机预览。

pnpm type-check
pnpm build:h5

type-check 检查业务代码与工程配置。tm-ui 采用按需引入的原始源码,保留第三方类型与样式;不对上游组件做单页定制。按团队规则,生产构建和完整测试在明确的集中验证指令后执行。

目录与调整入口

src/
├── pages/pay/index.vue             # 收银页面:商户、金额与付款交互
├── pages/pay/pay-complete.vue      # 只读付款结果页:Lottie、金额与交易信息
├── sheep/
│   ├── components/payment-keyboard.vue  # 四列常驻键盘
│   ├── config/merchant.ts          # 仅供设计参考的示例数据,真实页面不引用
│   ├── config/theme.ts             # UnoCSS、CSS 与 tm-ui 共享主题
│   ├── hooks/use-payment-amount.ts  # 金额字符串输入规则
│   ├── scss/global.scss            # 全局字体与 H5 视口适配
│   └── stores/index.ts             # tm-ui 主题使用的 Pinia
└── uni_modules/tm-ui/              # 参考项目同版 3.2.0 组件及必要依赖
  • 商户名称与标识通过匿名商户接口读取;src/sheep/config/merchant.ts 中的示例仅保留作设计参考,真实页面不引用。标识缺省或加载失败时展示统一店铺图形。
  • 修改主题:编辑 src/sheep/config/theme.ts。页面基础色在 pages.json、uni.scss 和 HTML 的 theme-color 中保留一致的框架配置。
  • 页面采用 Hash 路由,收银页面为 /pages/pay/index,结果页为 /pages/pay/pay-complete。部署子路径统一在 src/manifest.json 的 h5.router.base 中修改,默认 /,避免在 Vite 中重复设置路径前缀。
  • 接入 third 服务的匿名商户查询、线下收款、OAuth 回跳和真实支付。无签名入口或短期收银票据时展示错误,不回退到示例商户。

金额与 H5 交互

  • 使用字符串保存元单位金额,保留 0. 和 1.20 等输入过程,不进行浮点金额运算;支持两位小数、前导零处理和逐位删除。
  • 付款键对空金额、零金额和超过 9,999.99 元的金额禁用;提交前保存稳定请求号,刷新或网络失败后复用原请求。
  • 金额框为可聚焦的只读展示,避免系统软键盘和常驻键盘重叠。物理键盘支持数字、小数点、退格和 Enter;Tab、组合快捷键及数字按钮自身的键盘激活不被拦截。
  • 内容最大宽度 480px,rpx 同步限制放大;使用 100dvh 并提供 100vh 回退,键盘位于独立的底部区域。页面直接展示商户和金额,无顶部标题。
  • 整页锁定在可视高度,常见竖屏不产生纵向滚动;短屏压缩卡片间距,极短横屏保留内容区内部滑动。所有内部滚动条均隐藏,长金额仍可横向查看。
  • 支持安全区、长商户名称、长金额横向滚动、可见焦点与减少动态效果偏好;不禁止浏览器缩放。

第三方来源

tm-ui 3.2.0 从参考项目的 src/uni_modules/tm-ui 原样引入 tm-sheet、tm-icon 及其主题、工具、类型、CSS 和图标资源,保留上游说明与版本信息。数字键盘使用 uni-app 自带按钮,维持明确的禁用状态和 H5 键盘语义。

依赖基于参考项目的 pnpm 锁文件解析版本;只保留本项目需要的 H5 依赖,不包含 App 原生配置、服务地址或应用凭据。

接口与部署

项目只使用根目录一个 .env,变量命名与参考 App 一致:VITE_API_URL 为开发请求前缀,VITE_APP_DEV_SERVICE 为开发后端地址,VITE_APP_PROD_SERVICE 为生产后端地址,VITE_IS_MICRO 控制是否保留微服务前缀。修改后重启 pnpm dev:h5。这里不配置登录 Token、签名密钥或支付密钥。

开发模式下,浏览器请求 VITE_API_URL(默认 /api),由 vite.config.ts 转发到 VITE_APP_DEV_SERVICE,避免跨域。例如开发地址为 https://dzc-test-1.fy.takin.cc 且 VITE_IS_MICRO=true 时,http://localhost:8890/api/third/aggregate-merchant-pay/merchant 转发到 https://dzc-test-1.fy.takin.cc/third/aggregate-merchant-pay/merchant。目标地址自带 /api 等基础路径时会保留,不要在请求层再次添加。

VITE_IS_MICRO=true 保留 /third;false 对接单体服务时移除 /third,代理规则共用。生产构建直接读取同一 .env 的 VITE_APP_PROD_SERVICE;若线上反向代理已提供同源接口,可将其设为空。Vite 开发代理不随生产构建发布。

  • 商户码入口:/#/pages/pay/index?id=...&tenantId=...&v=1&sign=...,商户和租户 ID 按字符串处理。
  • 收银入口:/#/pages/pay/index?tenantCode=...&ticket=...,页面通过接口读取真实场景、固定金额和渠道参数。支付宝 WAP 的返回/退出由后端固定入口回跳同一票据,并附加 returned=1;该标记只阻止自动重复唤起,不表示支付结果。
  • GET /third/aggregate-merchant-pay/merchant 读取公开商户资料及 supportedPlatforms(10 微信、20 支付宝);商户可以只开通其中一个渠道。
  • POST /third/aggregate-merchant-pay/create 提交整数分金额及稳定 requestId;不在前端指定业务类型或渠道商户。
  • GET /third/aggregate-order-pay/context/{tenantCode}/{ticket} 读取收银上下文;现有 /status/{tenantCode}/{ticket} 确认结果。
  • 后端把本 H5 来源加入精确 CORS 允许列表;跨域接口必须使用 HTTPS。OAuth 回调仍由后端接收,平台密钥和 OAuth 身份不进入前端。

线下收款在提交前保留数字键盘;订单聚合及已提交的收款金额锁定。新票据只自动调起一次,取消后可手动继续,刷新不会自动重复弹出。微信 JSBridge 返回成功或支付宝 WAP 返回后仍查询服务端状态;未确认原单成功或关闭之前不释放金额创建新请求。

支付宝 WAP 使用后端 launchParams.mode=ALIPAY_WAP 和签名 payUrl,直接前往 https://openapi.alipay.com/gateway.do,必须带 method=alipay.trade.wap.pay,不等待 JSBridge。签名支付地址仅保留在当前上下文内存,不写入二维码、Hash 或浏览器恢复存储;支付宝旧 tradeNO/AlipayJSBridge.tradePay 分支已移除,微信客户端桥保持原逻辑。WAP 返回、退出或浏览器后退只查询原单,不自动重复导航;手动“继续付款”会先重读上下文,已成功、关闭或过期时停止发起。

扫码客户端未在商户已开通渠道中时,在原单页展示“商户暂不支持微信/支付宝支付”及换用已开通 App 重新扫码的指引,隐藏金额与键盘。普通浏览器提示使用已支持 App 扫码;全部渠道停用时提示联系商户。可重新检查开通情况,不在当前客户端强制唤起另一个 App,也不会据此清除待确认的原付款请求。

完整后端配置、迁移、平台域名设置及发布顺序见 ../biz-api-cloud-zax/pjcloud-thirdparty/docs/aggregate-h5.md。更换二维码使用的域名或签名密钥后需重新生成商户 URL 收款码,原 App Base64 收款码保持兼容。

付款结果页

付款成功或服务端明确关闭、过期、创建失败后,收银页自动进入 /pages/pay/pay-complete。入口只传 tenantCode、ticket,刷新后重新查询真实金额、商户、支付渠道和支付单号;不信任 URL 中的金额或成功状态。结果页仅调用已有 context/status 查询接口,不创建付款、不调起 JSBridge/WAP,也不释放待确认的 requestId。

结果页参考 App 的 pay-complete.vue,使用同版 lottie-web 5.13.0 和原始 success/fail/loading 矢量动画:成功、失败播放一次,查询中循环;减少动态效果时显示最终帧,后台暂停,销毁时清理。动画不可用时显示本地状态图标,文字与金额保持可读。

取消、网络错误和确认超时不会显示“支付失败”,而是保留待确认说明及只读重新查询入口。返回收银台仍使用同一票据,携带 returned=1、resultViewed=1 抑制再次自动付款及结果页往返跳转;该标记只影响导航,不改变服务端状态。确认成功或关闭后,线下商户入口可继续沿用原“再付一笔/重新输入金额”流程。

商户标识地址

收银页和付款结果页共用 merchant-logo.vue,原始 logoPic 保持后端返回值。相对图片路径(例如 /admin/sys-file/oss/file?fileName=...)按后台同名的 .env 配置 VITE_IMAGE_BASE_PATH 拼接,默认 /api,不追加 /third。生产同源 /api 代理应同时承接文件接口的 /admin 路径;也可把图片基址设为独立文件网关的完整地址。

完整 HTTP(S) 图片链接及其查询参数原样保留;缺少图片或加载失败时使用店铺占位图形。切换图片地址后重置失败状态,不影响商户信息或付款状态。修改 .env 后需重启开发服务,线上需要重新构建发布。

S
Description
No description provided
Readme
353 KiB
0 Stars 1 Watchers 0 Forks
Languages
TypeScript 39.7%
CSS 38.6%
Vue 20.9%
SCSS 0.6%
HTML 0.2%