# 前端对接变更说明 > 变更日期:2026-06-30 > 关联需求:支付渠道切换与重复支付追溯、邀请链接直接下载、邀请文案调整 --- ## 一、变更范围概览 本次后端改动涉及三大模块: 1. **支付模块**:支持订单详情页切换支付渠道,15 分钟内原渠道二维码仍有效;多渠道重复支付时以首笔成功渠道为准,其余渠道记录备查。 2. **邀请模块**:邀请链接 `/api/invite/{code}` 改为直接下载(302 重定向到安装包),删除独立下载接口 `/api/invite/{code}/download`。 3. **数据库**:新增 `wechat_nickname`、`paid_channel` 字段及 `t_payment_order_extra_payment` 重复支付记录表。 --- ## 二、后端接口变更清单 ### 2.1 邀请模块 | 接口 | 变更前 | 变更后 | |---|---|---| | `GET /api/invite/{code}` | 302 重定向到安装包 URL | **服务端流式返回安装包二进制**,浏览器自动下载 | | `GET /api/invite/{code}/download` | 下载接口 | **已删除** | **响应行为:** - 服务端根据 `User-Agent` 自动判断系统类型(Windows x64 / macOS ARM64)。 - 返回 `Content-Type: application/octet-stream` 和 `Content-Disposition: attachment; filename="..."`。 - 从本地 `invite.download-base-path` 配置目录读取安装包文件写入响应流,不再暴露真实文件 URL。 ### 2.2 支付模块 #### 新增接口:切换支付渠道 ```http POST /api/payment/order/{orderNo}/switch-channel Content-Type: application/json { "channel": "ALIPAY" // 可选值:WECHAT / ALIPAY } ``` **说明:** - 用于订单详情页切换支付方式。 - 不关闭原渠道订单,原渠道二维码 15 分钟内仍有效。 - 返回新渠道的支付二维码 `qrCodeBaseUrl` / `qrCodeBase64` / `payUrl`。 #### 已有接口:查询订单 ```http GET /api/payment/order/{orderNo} ``` **变更说明:** - 待支付订单会返回当前渠道二维码字段,前端可直接展示扫码支付。 - 关键返回字段: - `qrCodeBase64`:Base64 图片二维码 - `payUrl`:支付链接(支付宝等可用) - `channel`:当前订单渠道 - `expireHint`:过期提示文案 #### 回调逻辑变更 - 第一个支付成功渠道写入 `paidChannel`。 - 若同一订单在另一个渠道也支付成功,后端记录到 `t_payment_order_extra_payment`,但不重复激活会员。 - 前端正常展示"支付成功"即可,无需额外处理。 --- ## 三、前端必须修改的内容 ### 3.1 邀请链接直接下载(高优先级) **删除旧调用:** ```http GET /api/invite/{code}/download ``` **改为:** ```http GET /api/invite/{code} ``` **实现建议:** - H5/小程序/Web:使用 `` 或 `window.open('/api/invite/{code}')`。 - 桌面端:直接访问该 URL,浏览器自动处理下载。 - 落地页中的"下载 APP / Windows 客户端"按钮,URL 使用后端返回的 `appDownloadUrl`(当前等于邀请链接本身)。 - 注意:`inviteLink` 和 `downloadUrl` 现在统一为 `https://priceapi.kailin.com.cn/api/invite/{code}`(含 `/api` 路径),之前生成的 `/invite/{code}` 已修复。 ### 3.2 邀请分享文案(高优先级) **文案来源:** 使用 `/api/invite/code` 接口返回的 `copyText` 字段,不要在前端硬编码。 **文案格式示例:** ```text 我是Evan,在这里发现了一个药店采购神器——智价云(药店版)!它聚合比价功能特别方便,能快速查到最低价,帮你节省采购成本。填我的邀请码 2XKADABS 完成注册,你也会获得会员权益!下载链接https://priceapi.kailin.com.cn/api/invite/C6GZJEU4 ``` **兜底展示名规则:** 后端已处理,优先级为:微信昵称 > 用户昵称 > 手机尾号(如"手机尾号6688")> "一位药店用户"。 ### 3.3 支付订单详情页新增"切换支付渠道"(高优先级) **新增交互:** - 在订单详情页增加"切换为微信支付" / "切换为支付宝支付"按钮。 - 点击后调用: ```http POST /api/payment/order/{orderNo}/switch-channel ``` **请求体:** ```json { "channel": "WECHAT" } ``` **前端处理:** 1. 调用成功后,重新展示新渠道的二维码。 2. 提示用户:"已切换支付方式,请使用新二维码完成支付。原二维码 15 分钟内仍有效。" 3. 不要在前端主动关闭或禁用原二维码的展示(如果已展示)。 ### 3.4 查询订单二维码展示(中优先级) 待支付订单详情需要展示二维码: ```json { "qrCodeBase64": "data:image/png;base64,iVBORw0KGgo...", "payUrl": "https://qr.alipay.com/...", "channel": "ALIPAY", "expireHint": "请在15分钟内完成支付" } ``` - 微信支付:展示 `qrCodeBase64` 图片。 - 支付宝支付:可展示 `qrCodeBase64`,或提供"打开支付宝"按钮使用 `payUrl`。 ### 3.5 落地页字段调整(中优先级) - `appDownloadUrl` 现在就是 `/api/invite/{code}`。 - 落地页点击下载按钮直接访问该 URL 即可,无需拼接 `/download`。 - `downloadUrl` 字段与 `inviteLink` 一致。 --- ## 四、前端无需改动但需知悉 | 项 | 说明 | |---|---| | 会员激活 | 仍以第一个支付成功渠道为准 | | 重复支付 | 第二个渠道支付只记录,不重复激活会员,前端正常展示成功即可 | | 订单过期 | 15 分钟未支付自动过期,过期后切换渠道会失败 | | 支付宝支付 | 当前仅保留扫码模式(`alipay.trade.precreate`) | | 微信支付 | Native API v3,返回 Base64 二维码 | --- ## 五、本地测试指引 1. 启动网关服务。 2. 访问测试页面:`http://localhost:{port}/invite-test.html` 3. 在"支付模块"中找到: - **创建支付订单** - **查询订单** - **切换支付渠道** 4. 在"邀请模块"中找到: - **邀请链接入口(直接下载)** - **获取邀请码** --- ## 六、数据库上线注意 已有环境需要执行 `zhijiayun-gateway/src/main/resources/db/migration-v5.sql`,主要变更: ```sql -- t_user 新增微信昵称字段 ALTER TABLE `t_user` ADD COLUMN `wechat_nickname` VARCHAR(128) DEFAULT NULL COMMENT '微信昵称'; -- t_payment_order 新增实际支付渠道字段 ALTER TABLE `t_payment_order` ADD COLUMN `paid_channel` VARCHAR(20) DEFAULT NULL COMMENT '实际支付渠道'; -- 新增重复支付记录表 CREATE TABLE `t_payment_order_extra_payment` (...); ``` --- ## 七、安装包部署路径 流式下载会从 `invite.download-base-path` 配置目录直接读取安装包文件。 生产环境默认: ``` /app/zhijiayun/downloads/desktop-updates/ ``` 需要放入: - `智价云-x64.exe` - `智价云-arm64.dmg` > 中文文件名已通过 `Content-Disposition: filename*=UTF-8''...` 编码,兼容主流浏览器。 --- ## 八、CORS 部署说明 ### 8.1 架构调整 - **CORS 统一由 Nginx 处理**,后端 `zhijiayun-user` 已关闭 Spring Security CORS。 - 其他模块(`zhijiayun-invite`、`zhijiayun-payment`)本身无 CORS 配置,直接由 Nginx 接管。 ### 8.2 Nginx 关键配置 ```nginx # http 块内全局定义 map $http_origin $cors_origin { "~^(http://localhost:63342|https://[a-zA-Z0-9-]+\.kailin\.com\.cn)$" $http_origin; default ""; } # /api/ 接口统一加头(示例) location ^~ /api/ { add_header Access-Control-Allow-Origin $cors_origin always; add_header Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS" always; add_header Access-Control-Allow-Headers "Content-Type,Authorization,X-Request-Id" always; add_header Access-Control-Allow-Credentials "true" always; add_header Access-Control-Max-Age "86400" always; if ($request_method = 'OPTIONS') { return 204; } proxy_pass http://172.27.95.79:8002; # ... 其他代理配置 } ``` ### 8.3 后端 OPTIONS 兜底 虽然 CORS 由 Nginx 统一处理,但为避免 Nginx 配置遗漏或本地直连后端时 OPTIONS 预检被 Spring Security 拦截,已在 `SecurityConfig` 中放行 OPTIONS 请求: ```java .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() ``` **注意:** 放行 OPTIONS 仅保证不返回 401/403 认证错误,CORS 响应头仍由 Nginx 负责添加。生产环境必须确保 Nginx 在 `proxy_pass` 之前拦截 OPTIONS 并返回 204。 ### 8.4 测试调整 `zhijiayun-gateway` 原有的 `GatewayFilterTest.CorsTests` 测试后端 CORS 行为,现已删除。原因: - CORS 逻辑已迁移到 Nginx 层,后端不再负责添加 CORS 头。 - 后端单元测试无法模拟 Nginx 行为,继续断言 CORS 头会导致测试失效。 ### 8.5 注意事项 - 空 Origin 时 `$cors_origin` 为空,Nginx 会输出空的 `Access-Control-Allow-Origin` 头,浏览器会忽略它,符合安全预期。 - `/api/invite/` 建议单独配置 `location`,并设置 `proxy_buffering off`,保证大文件流式下载不被 Nginx 缓冲截断。 - 部署前务必检查 Nginx 配置已包含上述 CORS 头并正确拦截 OPTIONS,否则前端跨域会失败。 ## 九、变更文件列表 | 文件 | 变更类型 | 说明 | |---|---|---| | `zhijiayun-invite/.../InviteController.java` | 修改 | `/api/invite/{code}` 改为服务端流式下载,删除 `/download` 接口 | | `zhijiayun-invite/.../InviteService.java` | 修改 | 邀请文案、下载链接(含 `/api` 路径修正)、展示名优先级调整、流式下载文件读取 | | `zhijiayun-payment/.../PaymentOrder.java` | 修改 | 新增 `paidChannel` 字段 | | `zhijiayun-payment/.../PaymentOrderExtraPayment.java` | 新增 | 重复支付记录实体 | | `zhijiayun-payment/.../PaymentOrderExtraPaymentMapper.java` | 新增 | 重复支付记录 Mapper | | `zhijiayun-payment/.../PaymentOrderService.java` | 修改 | 渠道切换、重复支付处理 | | `zhijiayun-payment/.../PaymentCallbackController.java` | 修改 | 回调传递 `paidChannel` | | `zhijiayun-user/.../SecurityConfig.java` | 修改 | 关闭 Spring Security CORS,放行 OPTIONS 作为兜底 | | `zhijiayun-gateway/.../GatewayFilterTest.java` | 修改 | 删除已失效的后端 CORS 测试 | | `zhijiayun-gateway/.../db/schema.sql` | 修改 | 新增字段和表 | | `zhijiayun-gateway/.../db/migration-v5.sql` | 新增 | 已有环境幂等升级脚本 | | `zhijiayun-test/.../invite-test.html` | 修改 | 测试页面同步新增/调整接口说明 | | `zhijiayun-gateway/.../application-dev.yml` | 修改 | 新增 invite 下载文件路径配置 | | `zhijiayun-gateway/.../application-prod.yml` | 修改 | 新增 invite 下载文件路径配置 |