fix: 扫码注册统一用户查找与俱乐部校验,修复wdlyhdl与自动注册失败

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-08 18:00:29 +08:00
parent f23c8a3360
commit aeaa54583a
4 changed files with 137 additions and 57 deletions

View File

@@ -1,8 +1,84 @@
"""用户所属俱乐部解析。"""
from django.db import IntegrityError
from jituan.constants import CLUB_ID_DEFAULT
from jituan.models import UserWxOpenid
def resolve_invite_party_club(user, request_club_id=None):
"""
邀请链校验用:只返回已落库的俱乐部归属。
未归属任何俱乐部时返回 None勿默认 xq避免星之界扫码误拦
"""
if not user:
return None
explicit = (getattr(user, 'ClubID', None) or '').strip()
if explicit:
return explicit
uid = getattr(user, 'UserUID', None) or getattr(user, 'yonghuid', None)
if not uid:
return None
req = (request_club_id or '').strip()
if req:
hit = UserWxOpenid.query.filter(yonghuid=uid, club_id=req).first()
if hit:
return req
binding = UserWxOpenid.query.filter(yonghuid=uid).order_by('id').first()
if binding:
return binding.club_id
return None
def find_user_by_wx_openid(club_id, openid):
"""按俱乐部 openid 绑定或 legacy OpenID/UserName 定位用户。"""
from users.business_models import User
if club_id and openid:
binding = UserWxOpenid.query.filter(club_id=club_id, openid=openid).first()
if binding:
user = User.query.filter(UserUID=binding.yonghuid).first()
if not user:
user = User.objects.filter(UserUID=binding.yonghuid).first()
if user:
return user
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_openid_binding(club_id, openid, user, unionid=''):
if not club_id or not openid or not user:
return None
uid = getattr(user, 'UserUID', None)
if not uid:
return None
binding = UserWxOpenid.query.filter(club_id=club_id, openid=openid).first()
if binding:
return binding
try:
return UserWxOpenid.query.create(
club_id=club_id,
openid=openid,
yonghuid=uid,
unionid=unionid or getattr(user, 'UnionID', None) or '',
)
except IntegrityError:
return UserWxOpenid.query.filter(club_id=club_id, openid=openid).first()
def get_user_club_id(user):
"""
解析用户归属 club注册/邀请链隔离用)。

View File

@@ -1,24 +1,27 @@
"""邀请码 / 邀请链俱乐部隔离。"""
from jituan.constants import CLUB_ID_DEFAULT
from jituan.services.club_resolver import resolve_club_id_for_wechat_request
from jituan.services.club_user import get_user_club_id
from jituan.services.club_user import resolve_invite_party_club
def assert_invite_same_club(request, inviter_user, invitee_user=None):
"""
校验邀请人与被邀请人属于同一俱乐部,且与请求 club 一致。
现网全部 xq 时行为与改造前一致
未归属俱乐部的被邀请人允许在本小程序完成首次注册
返回 (ok, message)
"""
club_id = resolve_club_id_for_wechat_request(request)
inviter_club = get_user_club_id(inviter_user)
inviter_club = resolve_invite_party_club(inviter_user, club_id)
if inviter_club is None and club_id == CLUB_ID_DEFAULT:
inviter_club = CLUB_ID_DEFAULT
if inviter_club != club_id:
return False, '邀请码不属于当前小程序俱乐部'
if invitee_user is not None:
invitee_club = get_user_club_id(invitee_user)
if invitee_club != club_id:
invitee_club = resolve_invite_party_club(invitee_user, club_id)
if invitee_club is not None and invitee_club != club_id:
return False, '您的账号归属与当前小程序不一致,请使用对应俱乐部小程序'
if invitee_club != inviter_club:
if invitee_club is not None and invitee_club != inviter_club:
return False, '邀请码与您的俱乐部不匹配'
return True, ''

View File

@@ -4,13 +4,18 @@ import random
import time
import uuid
from django.db import IntegrityError, transaction
from django.db import 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 jituan.services.club_user import (
ensure_user_club_id,
ensure_wx_openid_binding,
find_user_by_wx_openid,
)
from users.business_models import User
from users.models import UserBoss, UserDashou, UserGuanshi, UserShangjia, UserZuzhang, UserShenheguan
from gvsdsdk.models import Role
@@ -105,37 +110,6 @@ def _collect_role_status(user):
}
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=''):
"""
俱乐部微信登录核心逻辑。
@@ -164,9 +138,9 @@ def login_or_register_by_club(code, club_id=None, app_id=None, client_ip=''):
user = User.objects.filter(UserUID=binding.yonghuid).first()
if not user:
user = _find_user_by_openid_legacy(openid)
user = find_user_by_wx_openid(resolved_club_id, openid)
if user:
_ensure_wx_binding(resolved_club_id, openid, user, unionid)
ensure_wx_openid_binding(resolved_club_id, openid, user, unionid)
if not user:
user_uuid = uuid.uuid4().bytes
@@ -179,17 +153,18 @@ def login_or_register_by_club(code, club_id=None, app_id=None, client_ip=''):
UnionID=unionid or None,
)
try:
from django.db import IntegrityError
user.save()
except IntegrityError:
user = _find_user_by_openid_legacy(openid)
user = find_user_by_wx_openid(resolved_club_id, openid)
if not user:
raise
_ensure_wx_binding(resolved_club_id, openid, user, unionid)
ensure_wx_openid_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)
ensure_wx_openid_binding(resolved_club_id, openid, user, unionid)
if unionid and unionid != (user.UnionID or ''):
user.UnionID = unionid
@@ -198,7 +173,6 @@ def login_or_register_by_club(code, club_id=None, app_id=None, 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)