变更日期:2026-06-30
关联需求:支付渠道切换与重复支付追溯、邀请链接直接下载、邀请文案调整
本次后端改动涉及三大模块:
/api/invite/{code} 改为直接下载(302 重定向到安装包),删除独立下载接口 /api/invite/{code}/download。wechat_nickname、paid_channel 字段及 t_payment_order_extra_payment 重复支付记录表。| 接口 | 变更前 | 变更后 |
|---|---|---|
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。POST /api/payment/order/{orderNo}/switch-channel
Content-Type: application/json
{
"channel": "ALIPAY" // 可选值:WECHAT / ALIPAY
}
说明:
qrCodeBaseUrl / qrCodeBase64 / payUrl。GET /api/payment/order/{orderNo}
变更说明:
qrCodeBase64:Base64 图片二维码payUrl:支付链接(支付宝等可用)channel:当前订单渠道expireHint:过期提示文案paidChannel。t_payment_order_extra_payment,但不重复激活会员。删除旧调用:
GET /api/invite/{code}/download
改为:
GET /api/invite/{code}
实现建议:
<a href="/api/invite/{code}" download> 或 window.open('/api/invite/{code}')。appDownloadUrl(当前等于邀请链接本身)。inviteLink 和 downloadUrl 现在统一为 https://priceapi.kailin.com.cn/api/invite/{code}(含 /api 路径),之前生成的 /invite/{code} 已修复。文案来源:
使用 /api/invite/code 接口返回的 copyText 字段,不要在前端硬编码。
文案格式示例:
我是Evan,在这里发现了一个药店采购神器——智价云(药店版)!它聚合比价功能特别方便,能快速查到最低价,帮你节省采购成本。填我的邀请码 2XKADABS 完成注册,你也会获得会员权益!下载链接https://priceapi.kailin.com.cn/api/invite/C6GZJEU4
兜底展示名规则:
后端已处理,优先级为:微信昵称 > 用户昵称 > 手机尾号(如"手机尾号6688")> "一位药店用户"。
新增交互:
点击后调用:
POST /api/payment/order/{orderNo}/switch-channel
请求体:
{
"channel": "WECHAT"
}
前端处理:
待支付订单详情需要展示二维码:
{
"qrCodeBase64": "data:image/png;base64,iVBORw0KGgo...",
"payUrl": "https://qr.alipay.com/...",
"channel": "ALIPAY",
"expireHint": "请在15分钟内完成支付"
}
qrCodeBase64 图片。qrCodeBase64,或提供"打开支付宝"按钮使用 payUrl。appDownloadUrl 现在就是 /api/invite/{code}。/download。downloadUrl 字段与 inviteLink 一致。| 项 | 说明 |
|---|---|
| 会员激活 | 仍以第一个支付成功渠道为准 |
| 重复支付 | 第二个渠道支付只记录,不重复激活会员,前端正常展示成功即可 |
| 订单过期 | 15 分钟未支付自动过期,过期后切换渠道会失败 |
| 支付宝支付 | 当前仅保留扫码模式(alipay.trade.precreate) |
| 微信支付 | Native API v3,返回 Base64 二维码 |
http://localhost:{port}/invite-test.html已有环境需要执行 zhijiayun-gateway/src/main/resources/db/migration-v5.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''...编码,兼容主流浏览器。
zhijiayun-user 已关闭 Spring Security CORS。zhijiayun-invite、zhijiayun-payment)本身无 CORS 配置,直接由 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;
# ... 其他代理配置
}
虽然 CORS 由 Nginx 统一处理,但为避免 Nginx 配置遗漏或本地直连后端时 OPTIONS 预检被 Spring Security 拦截,已在 SecurityConfig 中放行 OPTIONS 请求:
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
注意: 放行 OPTIONS 仅保证不返回 401/403 认证错误,CORS 响应头仍由 Nginx 负责添加。生产环境必须确保 Nginx 在 proxy_pass 之前拦截 OPTIONS 并返回 204。
zhijiayun-gateway 原有的 GatewayFilterTest.CorsTests 测试后端 CORS 行为,现已删除。原因:
$cors_origin 为空,Nginx 会输出空的 Access-Control-Allow-Origin 头,浏览器会忽略它,符合安全预期。/api/invite/ 建议单独配置 location,并设置 proxy_buffering off,保证大文件流式下载不被 Nginx 缓冲截断。| 文件 | 变更类型 | 说明 |
|---|---|---|
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 下载文件路径配置 |