修复手机号认证完成后仍反复弹窗的问题

认证提交接口在仅上传头像时错误返回成功,检查接口也未兼容已有手机号的老数据。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-09 21:57:23 +08:00
parent 7443fef6de
commit 914e8c70f2
2 changed files with 65 additions and 9 deletions

View File

@@ -252,10 +252,24 @@ class CheckPhoneAuthView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
user = request.user
@staticmethod
def _phone_auth_completed(user):
"""是否已完成手机号认证(兼容 PhoneVerified 未写入的老数据)。"""
if bool(getattr(user, 'PhoneVerified', False)):
return True
phone = (getattr(user, 'Phone', None) or '').strip()
return len(phone) >= 11
if getattr(user, 'PhoneVerified', False):
def post(self, request):
uid = getattr(request.user, 'UserUID', None)
user = request.user
if uid:
try:
user = User.query.get(UserUID=uid)
except User.DoesNotExist:
user = request.user
if self._phone_auth_completed(user):
return Response({'code': 0, 'need_auth': False})
if self._dashou_meets_threshold(user):

View File

@@ -164,6 +164,7 @@ def huoquKehuduanIP(request):
class UserInfoUpdateView(APIView):
permission_classes = [permissions.IsAuthenticated]
parser_classes = [MultiPartParser, FormParser, JSONParser]
# 进程内缓存防止同一code被重复调用微信单进程安全多进程小概率重复但用户极少可忽略
_phone_cache = {}
@@ -173,6 +174,7 @@ class UserInfoUpdateView(APIView):
user = request.user
boss = self._get_or_create_boss(user)
result = {}
nick = request.data.get('nicheng')
# 诊断日志:记录入参和实例状态
logger.warning(
@@ -201,7 +203,6 @@ class UserInfoUpdateView(APIView):
return Response({'code': 2, 'msg': '头像上传失败', 'data': None}, status=500)
# 昵称
nick = request.data.get('nicheng')
if nick:
nick = str(nick).strip()
if len(nick) > 20:
@@ -209,9 +210,28 @@ class UserInfoUpdateView(APIView):
boss.nickname = nick
result['nicheng'] = nick
# 手机号 —— 失败不阻塞其他字段(头像/昵称)的保存
code = request.data.get('shoujihao_code')
# 手机号 —— multipart 表单字段兼容 request.data / request.POST
code = (
request.data.get('shoujihao_code')
or request.POST.get('shoujihao_code')
or ''
)
if isinstance(code, str):
code = code.strip()
else:
code = str(code or '').strip()
# 认证页仅上传头像+手机号,不带昵称
is_phone_auth_flow = bool(av) and not nick
phone_error = None
if is_phone_auth_flow and not code:
return Response({
'code': 6,
'msg': '未收到手机号授权,请重新点击获取手机号',
'data': None,
}, status=200)
if code:
phone = self._get_phone_safe(code, request)
if phone is None:
@@ -220,6 +240,7 @@ class UserInfoUpdateView(APIView):
user.Phone = phone
user.PhoneVerified = True
result['phone'] = phone
result['phone_verified'] = True
if not result and not phone_error:
logger.warning("[USERINFO_XIUGAI] 无更新result 为空")
@@ -237,15 +258,36 @@ class UserInfoUpdateView(APIView):
phone_error,
)
# 有字段更新时先保存(即使手机号失败,头像/昵称也应入库)
# 认证流:必须拿到手机号才算成功,避免只存头像却返回 code=0 导致反复弹窗
if is_phone_auth_flow and 'phone' not in result:
msg = phone_error or '手机号获取失败,请重新授权'
if result:
with transaction.atomic():
user_update_fields = []
if 'touxiang' in result:
user_update_fields.append('Avatar')
if user_update_fields:
user.save(update_fields=user_update_fields)
if 'nicheng' in result:
boss.save()
return Response({'code': 6, 'msg': msg, 'data': result or None}, status=200)
# 有字段更新时先保存(资料编辑:手机号失败不阻塞头像/昵称)
if result:
user_update_fields = []
if 'touxiang' in result:
user_update_fields.append('Avatar')
if 'phone' in result:
user_update_fields.extend(['Phone', 'PhoneVerified'])
with transaction.atomic():
user.save()
if user_update_fields:
user.save(update_fields=user_update_fields)
elif result:
user.save()
boss.save()
logger.warning("[USERINFO_XIUGAI] 保存成功 result_keys=%s", list(result.keys()))
if phone_error:
# 其他字段已保存,但手机号失败 —— 返回已保存的字段供前端更新缓存
return Response({'code': 6, 'msg': phone_error, 'data': result}, status=200)
return Response({'code': 0, 'msg': '更新成功', 'data': result})