All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m12s
1. 修正 retail_price 架构:
- 删除 batch-pricing 接口的 pricing_target 字段和 retail_price 分支
(上级只能改下级成本价,不能改零售价)
- 新增 PATCH /api/admin/packages/:id/retail-price 接口
(代理自己改自己的零售价,校验 retail_price >= cost_price)
2. 清理旧微信 YAML 配置(已全部迁移到数据库 tb_wechat_config):
- 删除 config.yaml 中 wechat.official_account 配置节
- 删除 NewOfficialAccountApp() 旧工厂函数
- 清理 personal_customer service 中的死代码(旧登录/绑定微信方法)
- 清理 docker-compose.prod.yml 中旧微信环境变量和证书挂载注释
3. 归档四个已完成提案到 openspec/changes/archive/
4. 新增前端接口变更说明文档(docs/前端接口变更说明.md)
5. 修正归档提案和 specs 中关于 pricing_target 的错误描述
4.3 KiB
4.3 KiB
client-wechat-login Specification
Purpose
TBD - created by archiving change client-auth-system. Update Purpose after archive.
Requirements
Requirement: A2 微信公众号登录接口
系统 MUST 提供 POST /api/c/v1/auth/wechat-login,使用公众号 OAuth code + asset_token 完成登录。
- HTTP Method + Path:
POST /api/c/v1/auth/wechat-login - 请求体字段:
codestring,MUST,微信 OAuth 授权码asset_tokenstring,MUST,A1 返回的资产令牌
- 响应体字段:
tokenstring,MUST,登录 JWTneed_bind_phonebool,MUST,是否需要绑定手机号is_new_userbool,MUST,是否新创建用户
- 错误码:
1002token 无效或过期(asset_token/JWT)1040微信授权失败1006参数错误
Scenario: 公众号登录成功
- WHEN 客户端提交有效
code与有效asset_token - THEN 系统 SHALL 调用公众号 OAuth 获取
openid与可选unionid - THEN 系统 SHALL 执行客户查找/创建/合并逻辑
- THEN 系统 SHALL 绑定资产并签发登录 token
Requirement: A3 微信小程序登录接口
系统 MUST 提供 POST /api/c/v1/auth/miniapp-login,使用小程序 jscode2session + asset_token 完成登录。
- HTTP Method + Path:
POST /api/c/v1/auth/miniapp-login - 请求体字段:
codestring,MUST,小程序登录凭证asset_tokenstring,MUST,A1 返回的资产令牌
- 响应体字段:
tokenstring,MUST,登录 JWTneed_bind_phonebool,MUSTis_new_userbool,MUST
- 错误码:
1002token 无效或过期1040微信授权失败1006参数错误
Scenario: 小程序登录成功
- WHEN 客户端提交有效小程序
code与有效asset_token - THEN 系统 SHALL 调用
jscode2session获取openid与可选unionid - THEN 系统 SHALL 执行与 A2 一致的客户查找/创建/合并、资产绑定与签发逻辑
Requirement: asset_token 校验与资产解析
系统 SHALL 在 A2/A3 登录前强制校验 asset_token,并解析出 asset_type + asset_id。
Scenario: asset_token 无效
- WHEN
asset_token签名不合法或已过期 - THEN 系统 MUST 拒绝登录并返回
1002
Scenario: asset_token 有效
- WHEN
asset_token可被成功解析 - THEN 系统 SHALL 使用解析出的资产信息继续登录流程
Requirement: 客户查找/创建/合并逻辑
系统 MUST 按以下顺序处理客户归属:
- 先查
PersonalCustomerOpenID:(app_id, open_id); - 未命中且存在
unionid时按unionid回查并复用客户; - 仍未命中时创建新
PersonalCustomer与 OpenID 记录。
Scenario: openid 命中既有客户
- WHEN
(app_id, open_id)已存在 - THEN 系统 SHALL 直接复用对应
customer_id
Scenario: openid 未命中但 unionid 命中
- WHEN
(app_id, open_id)不存在且unionid命中历史记录 - THEN 系统 SHALL 复用已存在客户
- THEN 系统 SHALL 新增当前
app_id + open_id记录
Scenario: openid/unionid 均未命中
- WHEN 无任何匹配记录
- THEN 系统 SHALL 创建新客户并写入 OpenID 记录
Requirement: 登录后资产绑定
系统 SHALL 在 A2/A3 每次登录时创建一条 PersonalCustomerDevice 绑定记录,且 MUST 允许同一资产被多个客户绑定。
Scenario: 已有绑定时再次登录
- WHEN 同一客户再次登录同一资产
- THEN 系统 SHALL 记录本次登录绑定关系(按实现可去重或追加历史)
Scenario: 不同客户绑定同一资产
- WHEN 资产已被其他客户绑定
- THEN 系统 MUST 允许新增绑定,不得覆盖已有客户绑定关系
Requirement: 登录响应与手机号绑定开关
系统 MUST 在登录响应中返回 need_bind_phone,该值由 client.require_phone_binding 与客户手机号绑定状态共同决定。
Scenario: 要求手机号绑定且未绑定
- WHEN 配置
client.require_phone_binding=true且客户未绑定手机号 - THEN 登录响应 MUST 返回
need_bind_phone=true
Scenario: 已绑定手机号或配置关闭
- WHEN 客户已绑定手机号或
client.require_phone_binding=false - THEN 登录响应 MUST 返回
need_bind_phone=false