56 lines
2.4 KiB
Python
56 lines
2.4 KiB
Python
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
|