fix(auth): 微信 unionid 账号打通逻辑修复(staging 部署版,含 profile_completed) #1740

Merged
xiaoxia merged 3 commits from fix/wechat-unionid-linking-develop into develop 2026-09-06 15:09:18 +08:00
Owner

背景

与 #1738(已合入 main)同一修复,目标分支为 develop——staging 环境跟踪 develop 部署。main 版部署 staging 时因 alembic 版本不匹配(staging DB 在 068,main 镜像只到 065)自动回滚,故按 develop 重新出 PR。

修改点(packages/application/auth/wechat_sync_use_case.py)

  1. 查找顺序改为先 unionid 后 openid(unionid 跨应用识别同一微信用户)。
  2. openid 命中老账号 + 请求带 unionid + 老账号 unionid 为空 → 补写 unionid(开放平台绑定前存量账号自动关联,本次故障核心)。
  3. unionid 命中但 openid 不同 → 新 openid 绑定到该用户(仅当不属于其他账号)。
  4. 三类冲突拒绝写入并返回 conflict,不静默串联账号:unionid/openid 分属两账号;补写 unionid 被他人占用;新 openid 属于第三个账号。
  5. 保留 develop 上的 profile_completed=False 新用户引导逻辑。

测试

  • tests/unit/test_wechat_sync_use_case.py:20 用例,覆盖补写/跨端绑定/三类冲突/新建等,本地 20/20。
  • 对应 main PR:#1738(CI 全绿 + AI Review 通过)。

⚠️ 仅部署 staging,不动生产。

## 背景 与 #1738(已合入 main)同一修复,目标分支为 develop——**staging 环境跟踪 develop 部署**。main 版部署 staging 时因 alembic 版本不匹配(staging DB 在 068,main 镜像只到 065)自动回滚,故按 develop 重新出 PR。 ## 修改点(packages/application/auth/wechat_sync_use_case.py) 1. 查找顺序改为**先 unionid 后 openid**(unionid 跨应用识别同一微信用户)。 2. **openid 命中老账号 + 请求带 unionid + 老账号 unionid 为空 → 补写 unionid**(开放平台绑定前存量账号自动关联,本次故障核心)。 3. unionid 命中但 openid 不同 → 新 openid 绑定到该用户(仅当不属于其他账号)。 4. 三类冲突拒绝写入并返回 conflict,不静默串联账号:unionid/openid 分属两账号;补写 unionid 被他人占用;新 openid 属于第三个账号。 5. 保留 develop 上的 `profile_completed=False` 新用户引导逻辑。 ## 测试 - tests/unit/test_wechat_sync_use_case.py:20 用例,覆盖补写/跨端绑定/三类冲突/新建等,本地 20/20。 - 对应 main PR:#1738(CI 全绿 + AI Review 通过)。 ⚠️ 仅部署 staging,不动生产。
xiaoxia added 2 commits 2026-09-06 15:01:45 +08:00
test(auth): 补充unionid补写/跨端绑定/冲突拒绝场景测试
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 30s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 31s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m15s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m25s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 1m37s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m42s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 2m30s
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
0fa5b31f4f

🚀 预览环境已部署

项目 详情
PR号 #1740
预览链接 https://pr-1740.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1740 | | 预览链接 | [https://pr-1740.preview.xiaoxiajianji.com](https://pr-1740.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
auto-approve-bot added 1 commit 2026-09-06 15:04:22 +08:00
style: auto-format with black + isort + prettier [skip ci-format-check]
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 6s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 5s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 11s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 18s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m15s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m27s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 1m29s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 1m56s
AI Code Review / AI Code Review (pull_request) Successful in 2m14s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m48s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 4m20s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 7s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 2m15s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 15s
Preview Deploy / Deploy Preview Environment (pull_request) Failing after 10m19s
3fba310b9e
Collaborator

【阻塞级判定】

  • 是否存在阻塞级问题:否
  • 阻塞级问题数量:0 个

📊 审查概览

  • 整体评价:通过
  • 建议级问题数量:2 个

🔴 阻塞级问题(必须修复)

💡 改进建议(不阻塞合并)

  1. [packages/application/auth/wechat_sync_use_case.py:122] 冗余的条件判断

    • 具体内容:在 elif unionid_user: 分支中,代码检查了 if openid_user is not None ...。由于前一个 if 条件 if unionid_user and openid_user: 已经处理了两者都存在的情况,进入 elif unionid_user: 分支时 openid_user 必然为 None,因此该检查是死代码,建议移除以简化逻辑。
  2. [packages/application/auth/wechat_sync_use_case.py:135] 冗余的数据库查询

    • 具体内容:在 elif openid_user: 分支中,当需要补写 unionid 时,代码再次调用了 self.user_repository.find_by_wechat_unionid(request.unionid)。由于代码开头已经查询过 unionid_user 且确定其为 None(否则会进入前面的分支),此处查询是多余的。建议直接复用开头的查询结果(即确认 unionid_user 为 None 后直接执行写入),减少一次数据库交互。

良好实践

  • 冲突检测机制完善:代码严格检测了 unionidopenid 分属不同账号的冲突情况,避免了账号错误关联的数据风险。
  • 测试覆盖全面:单元测试覆盖了新用户注册、老用户登录、UnionID 补写、账号冲突等多种场景,特别是针对冲突边界条件的测试非常充分。
  • 代码逻辑清晰:通过优先查询 UnionID 再查询 OpenID 的策略,准确实现了“跨应用识别优先”的业务需求。

格式检查通过 | 逻辑审查通过 | ⚠️ 建议关注性能


🤖 由 AI 代码审查机器人自动生成 | 2026-09-06 07:06:37 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:否 - 阻塞级问题数量:0 个 ### 📊 审查概览 - 整体评价:通过 - 建议级问题数量:2 个 ### 🔴 阻塞级问题(必须修复) 无 ### 💡 改进建议(不阻塞合并) 1. **[packages/application/auth/wechat_sync_use_case.py:122] 冗余的条件判断** - 具体内容:在 `elif unionid_user:` 分支中,代码检查了 `if openid_user is not None ...`。由于前一个 `if` 条件 `if unionid_user and openid_user:` 已经处理了两者都存在的情况,进入 `elif unionid_user:` 分支时 `openid_user` 必然为 `None`,因此该检查是死代码,建议移除以简化逻辑。 2. **[packages/application/auth/wechat_sync_use_case.py:135] 冗余的数据库查询** - 具体内容:在 `elif openid_user:` 分支中,当需要补写 unionid 时,代码再次调用了 `self.user_repository.find_by_wechat_unionid(request.unionid)`。由于代码开头已经查询过 `unionid_user` 且确定其为 `None`(否则会进入前面的分支),此处查询是多余的。建议直接复用开头的查询结果(即确认 `unionid_user` 为 None 后直接执行写入),减少一次数据库交互。 ### ✅ 良好实践 - **冲突检测机制完善**:代码严格检测了 `unionid` 与 `openid` 分属不同账号的冲突情况,避免了账号错误关联的数据风险。 - **测试覆盖全面**:单元测试覆盖了新用户注册、老用户登录、UnionID 补写、账号冲突等多种场景,特别是针对冲突边界条件的测试非常充分。 - **代码逻辑清晰**:通过优先查询 UnionID 再查询 OpenID 的策略,准确实现了“跨应用识别优先”的业务需求。 --- ✅ 格式检查通过 | ✅ 逻辑审查通过 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-09-06 07:06:37 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
xiaoxia merged commit 794793f992 into develop 2026-09-06 15:09:18 +08:00

🗑️ 预览环境已清理

PR #1740 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #1740 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.