Files
junhong_cmp_fiber/openspec/specs/wechat-official-account/spec.md
huang b9733c4913
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m12s
fix: 修正零售价架构错误 + 清理旧微信配置 + 归档提案 + 前端接口文档
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 的错误描述
2026-03-19 17:39:43 +08:00

8.2 KiB
Raw Blame History

wechat-official-account Specification

Purpose

微信公众号能力规范,定义微信 OAuth 2.0 授权登录、账号绑定、OpenID/UnionID 查询、Access Token 中控及配置管理。

Requirements

Requirement: 系统必须支持微信 OAuth 2.0 授权登录

系统 SHALL 实现微信公众号 OAuth 2.0 授权流程,允许个人客户通过微信授权获取用户身份信息。

Scenario: 用户首次通过微信授权码登录成功

  • WHEN 用户在前端完成微信授权后端接收到有效的授权码code
  • THEN 系统调用微信 API 获取用户 OpenID、UnionID 和基本信息(昵称、头像)
  • THEN 系统在数据库中创建新的个人客户记录,保存微信 OpenID 和 UnionID
  • THEN 系统生成 JWT Token 并返回给客户端

Scenario: 已存在的微信用户再次登录

  • WHEN 用户通过微信授权码登录,且该 OpenID 已存在于数据库
  • THEN 系统查询到现有客户记录
  • THEN 系统更新客户的昵称和头像信息(保持最新)
  • THEN 系统生成 JWT Token 并返回给客户端

Scenario: 微信授权码无效或过期

  • WHEN 用户提交的授权码无效、过期或已被使用
  • THEN 系统调用微信 API 失败
  • THEN 系统返回错误码 1040微信 OAuth 授权失败)和中文错误消息"微信授权失败,请重试"

Scenario: 微信 API 服务不可用

  • WHEN 调用微信 API 时发生网络超时或微信服务异常
  • THEN 系统记录详细的错误日志(包含 Request ID
  • THEN 系统返回错误码 1040微信 OAuth 授权失败)和用户友好的中文错误消息

Requirement: 系统必须支持已有账号绑定微信

系统 SHALL 允许已注册的个人客户(通过手机号登录)绑定微信账号。

Scenario: 用户成功绑定微信账号

  • WHEN 已登录用户提交有效的微信授权码,且该用户尚未绑定微信
  • THEN 系统调用微信 API 获取 OpenID 和 UnionID
  • THEN 系统验证该 OpenID 未被其他用户绑定
  • THEN 系统更新该用户的 wx_open_id 和 wx_union_id 字段
  • THEN 系统返回成功响应和更新后的用户信息

Scenario: 尝试绑定已被使用的微信账号

  • WHEN 用户提交的微信授权码对应的 OpenID 已被其他用户绑定
  • THEN 系统返回错误码 1036微信账号已被绑定和中文错误消息"该微信账号已绑定其他用户"

Scenario: 用户已绑定微信后再次绑定

  • WHEN 已绑定微信的用户再次提交微信授权码
  • THEN 系统更新用户的昵称和头像信息
  • THEN 系统返回成功响应(允许更新信息,不报错)

Requirement: 系统必须支持通过 OpenID/UnionID 查询用户

系统 MUST 提供通过微信 OpenID 或 UnionID 查询个人客户的能力。

Scenario: 通过 OpenID 查询到用户

  • WHEN 调用 Store 层的 GetByWxOpenID 方法,传入有效的 OpenID
  • THEN 系统返回对应的个人客户记录

Scenario: 通过 OpenID 查询不到用户

  • WHEN 调用 Store 层的 GetByWxOpenID 方法,传入不存在的 OpenID
  • THEN 系统返回 nil无错误表示用户不存在

Scenario: 通过 UnionID 查询到用户

  • WHEN 调用 Store 层的 GetByWxUnionID 方法,传入有效的 UnionID
  • THEN 系统返回对应的个人客户记录

Requirement: 系统必须实现 Access Token 中控

系统 MUST 使用 Redis 缓存微信 Access Token支持多实例共享避免重复获取导致超出每日限额。

Scenario: 首次获取 Access Token

  • WHEN 系统首次调用微信 API 需要 Access Token
  • THEN 系统调用微信 API 获取 Access Token
  • THEN 系统将 Token 存储到 RedisKey: powerwechat.access_token.{MD5(appid+secret)}TTL: 7200秒
  • THEN 系统使用该 Token 完成 API 调用

Scenario: 从 Redis 缓存获取 Token

  • WHEN 系统调用微信 APIRedis 中存在有效的 Access Token
  • THEN 系统直接使用缓存的 Token不调用微信 API 获取新 Token

Scenario: Access Token 过期后自动刷新

  • WHEN 系统使用缓存的 Token 调用微信 API 返回 Token 过期错误
  • THEN 系统自动重新获取 Access Token
  • THEN 系统更新 Redis 缓存
  • THEN 系统重试原 API 调用

Requirement: API 必须遵循统一响应格式

所有微信相关 API MUST 返回统一的 JSON 响应格式。

Scenario: 成功响应格式

  • WHEN API 调用成功
  • THEN 系统返回 HTTP 200 和以下 JSON 格式:
    {
      "code": 0,
      "message": "success",
      "data": { /* 业务数据 */ },
      "timestamp": 1706789012345
    }
    

Scenario: 失败响应格式

  • WHEN API 调用失败(参数错误、业务逻辑错误、微信 API 错误)
  • THEN 系统返回对应的 HTTP 状态码400/401/500和以下 JSON 格式:
    {
      "code": 1040,
      "message": "微信授权失败,请重试",
      "data": null,
      "timestamp": 1706789012345
    }
    

Requirement: 系统必须记录完整的日志

所有微信 API 调用 MUST 记录完整的日志,便于排查问题。

Scenario: 记录微信 API 请求日志

  • WHEN 系统调用微信 API
  • THEN 系统记录 INFO 级别日志包含Request ID、API 端点、请求参数(脱敏)

Scenario: 记录微信 API 响应日志

  • WHEN 系统收到微信 API 响应
  • THEN 系统记录 INFO 级别日志包含Request ID、响应状态、响应时间、关键字段

Scenario: 记录微信 API 错误日志

  • WHEN 微信 API 调用失败
  • THEN 系统记录 ERROR 级别日志包含Request ID、错误码、错误消息、完整的错误详情

Requirement: 系统必须支持配置管理

微信公众号相关配置 MUST 通过 Viper + 环境变量管理。

Scenario: 从环境变量读取配置

  • WHEN 系统启动时
  • THEN 系统从环境变量读取以下配置:
    • JUNHONG_WECHAT_OFFICIAL_ACCOUNT_APP_ID(公众号 AppID
    • JUNHONG_WECHAT_OFFICIAL_ACCOUNT_APP_SECRET(公众号 AppSecret
    • JUNHONG_WECHAT_OFFICIAL_ACCOUNT_TOKEN(回调 Token
    • JUNHONG_WECHAT_OFFICIAL_ACCOUNT_AES_KEY(回调加密密钥)
    • JUNHONG_WECHAT_OFFICIAL_ACCOUNT_OAUTH_REDIRECT_URLOAuth 回调地址)

Scenario: 配置缺失时启动失败

  • WHEN 必填配置项AppID、AppSecret缺失
  • THEN 系统记录 FATAL 级别日志
  • THEN 系统启动失败并退出

Requirement: 微信配置源从 YAML 改为数据库动态读取

系统 MUST 将公众号/小程序授权配置源从 YAML 静态配置切换为数据库 tb_wechat_config 动态读取(is_active=true)。

  • 配置读取规则:
    • 公众号登录A2使用 app_id + app_secret
    • 小程序登录A3使用 miniapp_app_id + miniapp_app_secret
  • 适配接口:
    • POST /api/c/v1/auth/wechat-login
    • POST /api/c/v1/auth/miniapp-login

Scenario: 公众号登录读取数据库配置

  • WHEN 调用 A2 执行 OAuth code 换取 OpenID
  • THEN 系统 SHALL 从 tb_wechat_config 读取当前激活公众号配置

Scenario: 小程序登录读取数据库配置

  • WHEN 调用 A3 执行 jscode2session
  • THEN 系统 SHALL 从 tb_wechat_config 读取当前激活小程序配置

Requirement: 配置缺失或无激活记录时失败

系统 MUST 在缺少有效数据库配置时拒绝微信登录请求,并返回统一错误。

  • 错误码:
    • 1041 微信配置不可用
    • 1040 微信授权失败(第三方调用失败)

Scenario: 无激活配置

  • WHEN tb_wechat_config 中不存在 is_active=true 记录
  • THEN 系统 MUST 返回 1041

Scenario: 配置存在但第三方调用失败

  • WHEN 已获取数据库配置但调用微信接口失败
  • THEN 系统 MUST 返回 1040

Requirement: 旧 YAML 配置不再作为登录凭据来源

系统 SHALL 停止在登录链路中使用 wechat.official_account.* 静态配置作为 AppID/AppSecret 来源。

Scenario: 配置切换后行为一致

  • WHEN 运维在数据库中更新激活配置
  • THEN 后续登录请求 SHALL 使用新配置生效
  • THEN 无需重启服务加载 YAML