wx登录
All checks were successful
Deploy to Server / deploy (push) Successful in 27s

This commit is contained in:
jeremygan2021
2026-03-02 16:47:40 +08:00
parent 5b4643c8f9
commit f0c62eb57c

View File

@@ -1049,82 +1049,65 @@ def wechat_login(request):
if mp_user and phone_user:
if mp_user != phone_user:
# 【合并场景】: 小程序用户 和 手机号用户 都存在且不同
# 规则: 只要手机号一致,强制合并。以当前 OpenID (mp_user) 为准,吸纳旧用户 (phone_user) 的数据。
# 检查 phone_user 是否已经是真实的 MP 用户 (防止覆盖已绑定的其他微信账号)
# 规则: 如果 phone_user.openid 不是以 'web_' 开头,说明它已经是一个微信用户
# 此时我们不能简单的合并,因为这意味着两个不同的微信账号绑定了同一个手机号(可能是异常或用户更换了微信号)
# 策略: 优先保留当前的 mp_user提示用户手机号已被占用或者这里简单处理为不合并手机号只登录 mp_user
# 1. 迁移订单
Order.objects.filter(wechat_user=phone_user).update(wechat_user=mp_user)
if not phone_user.openid.startswith('web_'):
print(f"冲突: 手机号 {phone_number} 已被用户 {phone_user.id} (OpenID: {phone_user.openid}) 绑定,无法合并到当前用户 {mp_user.id}")
# 这种情况下,我们让当前用户登录,但不更新手机号 (或者可以返回错误提示需人工解绑)
user = mp_user
# 也可以选择强制更新手机号到当前用户,并解绑旧用户(取决于业务规则,这里选择保守策略:不合并,仅登录)
else:
# 是 Web 虚拟用户,可以安全合并
# 1. 迁移订单
Order.objects.filter(wechat_user=phone_user).update(wechat_user=mp_user)
# 2. 迁移社区数据 (延迟导入避免循环引用)
from community.models import ActivitySignup, Topic, Reply
ActivitySignup.objects.filter(user=phone_user).update(user=mp_user)
Topic.objects.filter(author=phone_user).update(author=mp_user)
Reply.objects.filter(author=phone_user).update(author=mp_user)
# 3. 迁移分销员
if hasattr(phone_user, 'distributor') and not hasattr(mp_user, 'distributor'):
dist = phone_user.distributor
dist.user = mp_user
dist.save()
# 4. 迁移用户信息优先使用Web用户的信息覆盖小程序的信息保持体验一致
if phone_user.nickname:
mp_user.nickname = phone_user.nickname
if phone_user.avatar_url:
mp_user.avatar_url = phone_user.avatar_url
if phone_user.gender != 0:
mp_user.gender = phone_user.gender
# 迁移关联的系统用户 (用于管理员权限等)
if phone_user.user and not mp_user.user:
mp_user.user = phone_user.user
# 清除旧对象的关联,防止唯一约束冲突(虽然即将删除,但为了安全)
phone_user.user = None
phone_user.save()
# 标记拥有Web徽章
# 2. 迁移社区数据 (延迟导入避免循环引用)
from community.models import ActivitySignup, Topic, Reply
ActivitySignup.objects.filter(user=phone_user).update(user=mp_user)
Topic.objects.filter(author=phone_user).update(author=mp_user)
Reply.objects.filter(author=phone_user).update(author=mp_user)
# 3. 迁移分销员
if hasattr(phone_user, 'distributor') and not hasattr(mp_user, 'distributor'):
dist = phone_user.distributor
dist.user = mp_user
dist.save()
# 4. 迁移用户信息
# 如果 mp_user 尚未设置昵称头像(新用户),则沿用 phone_user 的
if not mp_user.nickname and phone_user.nickname:
mp_user.nickname = phone_user.nickname
if not mp_user.avatar_url and phone_user.avatar_url:
mp_user.avatar_url = phone_user.avatar_url
if mp_user.gender == 0 and phone_user.gender != 0:
mp_user.gender = phone_user.gender
# 迁移关联的系统用户 (用于管理员权限等)
if phone_user.user and not mp_user.user:
mp_user.user = phone_user.user
phone_user.user = None
phone_user.save()
# 标记拥有Web徽章 (如果旧用户是 Web 用户)
if phone_user.openid.startswith('web_') or phone_user.has_web_badge:
mp_user.has_web_badge = True
mp_user.save()
# 删除旧用户
phone_user.delete()
user = mp_user
# 更新手机号
user.phone_number = phone_number
user.save()
# 更新手机号
mp_user.phone_number = phone_number
mp_user.save()
# 删除旧用户
phone_user.delete()
user = mp_user
else:
# 同一个用户
user = mp_user
elif phone_user:
# 【绑定场景】: 只有手机号用户存在 (通常是 Web 用户) -> 升级为小程序用户
# 【绑定场景】: 只有手机号用户存在
# 无论是否 Web 用户,只要 OpenID 不同,都更新为最新的 OpenID
user = phone_user
# 只有当它是 Web 虚拟用户时,才覆盖 OpenID
if user.openid.startswith('web_') or not user.openid:
user.openid = openid
# 确保标记为拥有 Web 徽章 (虽然它本来就是 Web 用户转过来的)
if user.openid.startswith('web_'):
user.has_web_badge = True
if user.openid != openid:
print(f"用户更换 OpenID: {user.openid} -> {openid}, Phone: {phone_number}")
user.openid = openid
user.save()
elif user.openid != openid:
# 冲突: 手机号已被另一个真实 OpenID 绑定,但当前登录的是新的 OpenID
# 策略: 创建新用户,不合并 (避免安全风险)
# 检查 openid 是否已被其他用户占用 (理论上 mp_user 为 None 说明没有,但双重检查)
existing_openid_user = WeChatUser.objects.filter(openid=openid).first()
if existing_openid_user:
user = existing_openid_user
else:
user = WeChatUser.objects.create(openid=openid)
# 此时不绑定手机号,因为手机号被 phone_user 占用了
elif mp_user:
# 【更新场景】: 只有小程序用户存在 -> 更新手机号
@@ -1345,12 +1328,8 @@ def bind_phone(request):
return Response({'message': '已绑定该手机号'})
# 发现冲突,需要合并
# 策略:保留 current_user (MP User, with real OpenID),合并 existing_user (Web User) 的数据
# 仅当 existing_user 是 Web 用户 (openid startswith 'web_') 时才合并
# 如果 existing_user 也是 MP 用户 (real openid),则提示冲突,不允许绑定
if not existing_user.openid.startswith('web_'):
return Response({'error': '该手机号已被其他微信账号绑定,无法重复绑定'}, status=status.HTTP_409_CONFLICT)
# 策略:保留 current_user (MP User, with real OpenID),合并 existing_user (Phone User) 的数据
# 无论 existing_user 是否是 Web 用户,都允许合并,以 current_user 为主(覆盖旧 OpenID
# 执行合并
from django.db import transaction
@@ -1364,18 +1343,18 @@ def bind_phone(request):
Topic.objects.filter(author=existing_user).update(author=current_user)
# 4. 迁移 Reply
Reply.objects.filter(author=existing_user).update(author=current_user)
# 5. 迁移 Distributor (如果 Web 用户注册了分销员,且 MP 用户未注册)
# 5. 迁移 Distributor (如果用户注册了分销员,且用户未注册)
if hasattr(existing_user, 'distributor') and not hasattr(current_user, 'distributor'):
dist = existing_user.distributor
dist.user = current_user
dist.save()
# 6. 迁移用户信息 (优先使用 Web 用户信息)
if existing_user.nickname:
# 6. 迁移用户信息 (如果新用户尚未设置,则使用旧用户信息)
if not current_user.nickname and existing_user.nickname:
current_user.nickname = existing_user.nickname
if existing_user.avatar_url:
if not current_user.avatar_url and existing_user.avatar_url:
current_user.avatar_url = existing_user.avatar_url
if existing_user.gender != 0:
if current_user.gender == 0 and existing_user.gender != 0:
current_user.gender = existing_user.gender
# 7. 迁移系统用户关联
@@ -1384,10 +1363,11 @@ def bind_phone(request):
existing_user.user = None
existing_user.save()
# 8. 标记 Web 徽章
current_user.has_web_badge = True
# 8. 标记 Web 徽章 (如果旧用户是 Web 用户或已有徽章)
if existing_user.openid.startswith('web_') or existing_user.has_web_badge:
current_user.has_web_badge = True
# 删除旧 Web 用户
# 删除旧用户
existing_user.delete()
# 更新当前用户手机号