from django.core.signing import TimestampSigner, BadSignature, SignatureExpired from shop.models import WeChatUser import logging logger = logging.getLogger(__name__) def get_current_wechat_user(request): """ 根据 Authorization 头获取当前微信用户 增强逻辑:如果 Token 解析出的 OpenID 对应的用户不存在(可能已被合并删除), 但该 OpenID 是 Web 虚拟 ID (web_phone),尝试通过手机号查找现有的主账号。 """ auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): logger.warning(f"Authentication failed: Missing or invalid Authorization header. Header: {auth_header}") return None token = auth_header.split(' ')[1] signer = TimestampSigner() try: # 签名包含 openid openid = signer.unsign(token, max_age=86400 * 30) # 30天有效 user = WeChatUser.objects.filter(openid=openid).first() if user: return user # 如果没找到用户,检查是否是 Web 虚拟 OpenID # 场景:Web 用户已被合并到小程序账号,旧 Web Token 依然有效,指向合并后的账号 logger.info(f"User not found for openid: {openid}, checking for merged account...") if openid.startswith('web_'): try: # 格式: web_13800138000 parts = openid.split('_', 1) if len(parts) == 2: phone = parts[1] # 尝试通过手机号查找(查找合并后的主账号) user = WeChatUser.objects.filter(phone_number=phone).first() if user: logger.info(f"Found merged user {user.id} for phone {phone}") return user except Exception as e: logger.error(f"Error checking merged account: {e}") pass logger.warning(f"Authentication failed: User not found for openid {openid}") return None except SignatureExpired: logger.warning("Authentication failed: Signature expired") return None except BadSignature: logger.warning("Authentication failed: Bad signature") return None except Exception as e: logger.error(f"Authentication unexpected error: {e}") return None