diff --git a/.env b/.env index 4c29fa8..d861b06 100644 --- a/.env +++ b/.env @@ -8,4 +8,5 @@ VITE_IS_MICRO=true VITE_APP_DEV_SERVICE=https://dzc-test-1.fy.takin.cc # 生产环境后端地址;配置为空时由线上部署提供同源接口。 -VITE_APP_PROD_SERVICE=https://www.zianxin.com/api +# VITE_APP_PROD_SERVICE=https://www.zianxin.com/api +VITE_APP_PROD_SERVICE=/api diff --git a/README.md b/README.md index 4166460..f161f7d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 商户付款 H5 -uni-app Vue 3 + TypeScript + UnoCSS + tm-ui 的独立 H5 项目。工程与蓝色主题参考 `../biz_zax_app_cloud`,只注册一个付款页面,默认中文、人民币、浅色主题。 +uni-app Vue 3 + TypeScript + UnoCSS + tm-ui 的独立 H5 项目。工程与蓝色主题参考 `../biz_zax_app_cloud`,提供商户收银与付款结果页面,默认中文、人民币、浅色主题。 ## 本地开发 @@ -24,7 +24,8 @@ pnpm build:h5 ```text src/ -├── pages/pay/index.vue # 唯一页面:商户、金额与付款交互 +├── pages/pay/index.vue # 收银页面:商户、金额与付款交互 +├── pages/pay/pay-complete.vue # 只读付款结果页:Lottie、金额与交易信息 ├── sheep/ │ ├── components/payment-keyboard.vue # 四列常驻键盘 │ ├── config/merchant.ts # 仅供设计参考的示例数据,真实页面不引用 @@ -37,7 +38,7 @@ src/ - 商户名称与标识通过匿名商户接口读取;`src/sheep/config/merchant.ts` 中的示例仅保留作设计参考,真实页面不引用。标识缺省或加载失败时展示统一店铺图形。 - 修改主题:编辑 `src/sheep/config/theme.ts`。页面基础色在 `pages.json`、`uni.scss` 和 HTML 的 theme-color 中保留一致的框架配置。 -- 页面采用 Hash 路由,唯一页面为 `/pages/pay/index`。部署子路径统一在 `src/manifest.json` 的 `h5.router.base` 中修改,默认 `/`,避免在 Vite 中重复设置路径前缀。 +- 页面采用 Hash 路由,收银页面为 `/pages/pay/index`,结果页为 `/pages/pay/pay-complete`。部署子路径统一在 `src/manifest.json` 的 `h5.router.base` 中修改,默认 `/`,避免在 Vite 中重复设置路径前缀。 - 接入 third 服务的匿名商户查询、线下收款、OAuth 回跳和真实支付。无签名入口或短期收银票据时展示错误,不回退到示例商户。 ## 金额与 H5 交互 @@ -64,14 +65,24 @@ tm-ui `3.2.0` 从参考项目的 `src/uni_modules/tm-ui` 原样引入 `tm-sheet` `VITE_IS_MICRO=true` 保留 `/third`;`false` 对接单体服务时移除 `/third`,代理规则共用。生产构建直接读取同一 `.env` 的 `VITE_APP_PROD_SERVICE`;若线上反向代理已提供同源接口,可将其设为空。Vite 开发代理不随生产构建发布。 - 商户码入口:`/#/pages/pay/index?id=...&tenantId=...&v=1&sign=...`,商户和租户 ID 按字符串处理。 -- OAuth 回跳:`/#/pages/pay/index?tenantCode=...&ticket=...`,页面通过接口读取真实场景、固定金额和渠道参数。 +- 收银入口:`/#/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 身份不进入前端。 -线下收款在提交前保留数字键盘;订单聚合及已提交的收款金额锁定。OAuth 回跳只自动调起一次,取消后可手动继续,刷新不会自动重复弹出。JSBridge 返回成功后仍查询服务端状态;未确认原单成功或关闭之前不释放金额创建新请求。 +线下收款在提交前保留数字键盘;订单聚合及已提交的收款金额锁定。新票据只自动调起一次,取消后可手动继续,刷新不会自动重复弹出。微信 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` 抑制再次自动付款及结果页往返跳转;该标记只影响导航,不改变服务端状态。确认成功或关闭后,线下商户入口可继续沿用原“再付一笔/重新输入金额”流程。 diff --git a/package.json b/package.json index 60547c7..71d8f00 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@dcloudio/uni-app": "3.0.0-5000720260410001", "@dcloudio/uni-components": "3.0.0-5000720260410001", "@dcloudio/uni-h5": "3.0.0-5000720260410001", + "lottie-web": "5.13.0", "pinia": "3.0.4", "vue": "3.5.26" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f8e0668..ca6fd08 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: "@dcloudio/uni-h5": specifier: 3.0.0-5000720260410001 version: 3.0.0-5000720260410001(postcss@8.5.6)(vue@3.5.26(typescript@4.9.5)) + lottie-web: + specifier: 5.13.0 + version: 5.13.0 pinia: specifier: 3.0.4 version: 3.0.4(typescript@4.9.5)(vue@3.5.26(typescript@4.9.5)) @@ -52,6 +55,9 @@ importers: specifier: 1.8.27 version: 1.8.27(typescript@4.9.5) packages: + lottie-web@5.13.0: + resolution: + integrity: sha512-+gfBXl6sxXMPe8tKQm7qzLnUy5DUPJPKIyRHwtpCpyUEYjHYRJC/5gjUvdkuO2c3JllrPtHXH5UJJK8LRYl5yQ== "@ampproject/remapping@2.3.0": resolution: integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== @@ -3103,6 +3109,7 @@ packages: engines: node: ">= 6" snapshots: + lottie-web@5.13.0: {} "@ampproject/remapping@2.3.0": dependencies: "@jridgewell/gen-mapping": 0.3.13 diff --git a/src/pages.json b/src/pages.json index d8de7a5..d3722e2 100644 --- a/src/pages.json +++ b/src/pages.json @@ -12,6 +12,13 @@ "navigationBarTitleText": "商户收款", "disableScroll": true } + }, + { + "path": "pages/pay/pay-complete", + "style": { + "navigationBarTitleText": "付款结果", + "disableScroll": true + } } ], "globalStyle": { diff --git a/src/pages/pay/index.vue b/src/pages/pay/index.vue index 6e3723e..43fea6a 100644 --- a/src/pages/pay/index.vue +++ b/src/pages/pay/index.vue @@ -35,6 +35,7 @@ {{ error }} {{ feedback || '正在读取收款信息…' }} + {{ resultNavigationError }} @@ -43,7 +44,8 @@