Files
Django/jituan/services/wechat_login.py
2026-07-08 17:43:39 +08:00

236 lines
7.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""俱乐部微信登录(多 openid 绑定,不修改旧 wechatlogin 逻辑)。"""
import logging
import random
import time
import uuid
from django.db import IntegrityError, transaction
from django.utils import timezone
from rest_framework_simplejwt.tokens import RefreshToken
from jituan.constants import CLUB_ID_DEFAULT
from jituan.models import UserWxOpenid
from jituan.services.club_resolver import jscode2session, resolve_club_by_appid
from users.business_models import User
from users.models import UserBoss, UserDashou, UserGuanshi, UserShangjia, UserZuzhang, UserShenheguan
from gvsdsdk.models import Role
logger = logging.getLogger(__name__)
def _generate_user_uid():
for _ in range(10):
timestamp_part = str(int(time.time()))[-5:].zfill(5)
random_part = str(random.randint(0, 99)).zfill(2)
user_id = timestamp_part + random_part
if len(user_id) == 7 and user_id.isdigit():
if not User.query.filter(UserUID=user_id).exists():
return user_id
raise RuntimeError('生成用户ID失败')
def _ensure_boss_profile(user):
try:
UserBoss.query.get(user=user)
except UserBoss.DoesNotExist:
UserBoss.query.create(user=user, nickname='板板大人')
def _ensure_consumer_role(user):
from users.business_models import UserRole as BizUserRole
normal_role = Role.objects.filter(RoleName='消费者').first()
if not normal_role:
return
exists = BizUserRole.objects.filter(UserUUID=user.UserUUID, RoleUUID=normal_role.RoleUUID).exists()
if not exists:
BizUserRole.objects.create(
UserRoleUUID=uuid.uuid4().bytes,
UserUUID=user.UserUUID,
RoleUUID=normal_role.RoleUUID,
CompanyUUID=uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes,
)
def _collect_role_status(user):
dashou_status = None
shangjia_status = None
guanshi_status = None
zuzhang_status = None
kaoheguan_status = 0
boss_nickname = '微信用户'
try:
boss = UserBoss.query.get(user=user)
boss_nickname = boss.nickname or '微信用户'
except UserBoss.DoesNotExist:
pass
try:
UserDashou.query.get(user=user)
dashou_status = 1
except UserDashou.DoesNotExist:
dashou_status = None
try:
UserShangjia.query.get(user=user)
shangjia_status = 1
except UserShangjia.DoesNotExist:
shangjia_status = None
try:
UserGuanshi.query.get(user=user)
guanshi_status = 1
except UserGuanshi.DoesNotExist:
guanshi_status = None
try:
UserZuzhang.query.get(user=user)
zuzhang_status = 1
except UserZuzhang.DoesNotExist:
zuzhang_status = None
try:
kg = UserShenheguan.query.get(user=user)
kaoheguan_status = 1 if kg.zhuangtai == 1 else 0
except UserShenheguan.DoesNotExist:
kaoheguan_status = 0
return {
'dashou_status': dashou_status,
'shangjia_status': shangjia_status,
'guanshi_status': guanshi_status,
'zuzhang_status': zuzhang_status,
'kaoheguan_status': kaoheguan_status,
'boss_nickname': boss_nickname,
}
def _find_user_by_openid_legacy(openid):
"""兼容旧登录/扫码注册User.OpenID 或 UserName 存的是 openid。"""
user = User.query.filter(OpenID=openid).first()
if not user:
user = User.objects.filter(OpenID=openid).first()
if not user:
user = User.query.filter(UserName=openid).first()
if not user:
user = User.objects.filter(UserName=openid).first()
return user
def _ensure_wx_binding(resolved_club_id, openid, user, unionid=''):
binding = UserWxOpenid.query.filter(
club_id=resolved_club_id, openid=openid,
).first()
if binding:
return binding
try:
return UserWxOpenid.query.create(
club_id=resolved_club_id,
openid=openid,
yonghuid=user.UserUID,
unionid=unionid or user.UnionID or '',
)
except IntegrityError:
return UserWxOpenid.query.filter(
club_id=resolved_club_id, openid=openid,
).first()
def login_or_register_by_club(code, club_id=None, app_id=None, client_ip=''):
"""
俱乐部微信登录核心逻辑。
- 通过 user_wx_openid(club_id, openid) 定位用户
- xq 俱乐部兼容:若绑定不存在但 User.OpenID 已存在,则自动建绑定(不新建用户)
"""
wx_data = jscode2session(code, club_id=club_id, app_id=app_id)
if not wx_data or 'openid' not in wx_data:
return None, wx_data.get('errmsg', '微信授权失败')
openid = wx_data['openid']
unionid = wx_data.get('unionid', '')
resolved_club_id = wx_data.get('club_id') or club_id or CLUB_ID_DEFAULT
with transaction.atomic():
binding = UserWxOpenid.query.filter(
club_id=resolved_club_id, openid=openid
).first()
user = None
created = False
if binding:
user = User.query.filter(UserUID=binding.yonghuid).first()
if not user:
user = User.objects.filter(UserUID=binding.yonghuid).first()
if not user:
user = _find_user_by_openid_legacy(openid)
if user:
_ensure_wx_binding(resolved_club_id, openid, user, unionid)
if not user:
user_uuid = uuid.uuid4().bytes
new_uid = _generate_user_uid()
user = User(
UserUUID=user_uuid,
UserUID=new_uid,
UserName=openid,
OpenID=openid if resolved_club_id == CLUB_ID_DEFAULT else None,
UnionID=unionid or None,
)
try:
user.save()
except IntegrityError:
user = _find_user_by_openid_legacy(openid)
if not user:
raise
_ensure_wx_binding(resolved_club_id, openid, user, unionid)
else:
created = True
_ensure_boss_profile(user)
_ensure_consumer_role(user)
_ensure_wx_binding(resolved_club_id, openid, user, unionid)
if unionid and unionid != (user.UnionID or ''):
user.UnionID = unionid
if client_ip:
user.IP = client_ip
user.UserLastLoginDate = timezone.now()
user.save()
from jituan.services.club_user import ensure_user_club_id
ensure_user_club_id(user, resolved_club_id)
roles = _collect_role_status(user)
refresh = RefreshToken.for_user(user)
token = str(refresh.access_token)
from merchant_ops.services.authz import staff_fields_for_login
from users.views import WechatMiniProgramLoginView
staff_fields = staff_fields_for_login(user)
login_view = WechatMiniProgramLoginView()
order_counts = login_view.jisuanOrderShuliang(user.UserUID)
group_info = login_view.huoquQunPeizhi()
data = {
'token': token,
'nicheng': roles['boss_nickname'],
'uid': user.UserUID,
'touxiang': user.Avatar or '',
'shangjiastatus': roles['shangjia_status'],
'dashoustatus': roles['dashou_status'],
'guanshistatus': roles['guanshi_status'],
'zuzhangstatus': roles['zuzhang_status'],
'kaoheguanstatus': roles['kaoheguan_status'],
'dingdantiaoshu': order_counts,
'dashouqun': group_info.get('dashouqun', ''),
'dashouqunid': group_info.get('dashouqunid', ''),
'guanshiqun': group_info.get('guanshiqun', ''),
'guanshiqunid': group_info.get('guanshiqunid', ''),
'club_id': resolved_club_id,
'is_new_user': created,
**staff_fields,
}
return data, None