fix: 老小程序不改端,后端兼容扫码注册(dashouzhuce/wdlyhdl)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-08 18:20:45 +08:00
parent 7fe49775b9
commit e0c48073f1
4 changed files with 95 additions and 69 deletions

View File

@@ -0,0 +1,18 @@
"""老小程序兼容:统一 JSON 错误格式(勿改前端时靠后端适配)。"""
from rest_framework import status
from rest_framework.response import Response
def legacy_miniapp_error(code, message, http_status=status.HTTP_200_OK):
"""
业务错误返回 HTTP 200 + body.code。
老端 request.js 会把 HTTP 403 当成「请先登录」,导致只显示「注册失败」。
同时写 message 与 msg兼容 dashouzhuce / wdlyhdl 两种字段名。
"""
text = message or '操作失败'
return Response({
'code': code,
'message': text,
'msg': text,
'data': None,
}, status=http_status)

View File

@@ -42,11 +42,38 @@ def get_club_wx_credentials(club_id):
return '', '', club
def _invite_code_from_request(request):
data = getattr(request, 'data', None) or {}
if not isinstance(data, dict):
return ''
return (data.get('inviteCode') or data.get('invite_code') or '').strip()
def resolve_club_from_invite_code(invite_code):
"""老端无 Header/Referer 时,从管事邀请码反查俱乐部。"""
invite_code = (invite_code or '').strip()
if not invite_code:
return None
try:
from users.models import UserGuanshi
from jituan.services.club_user import resolve_invite_party_club
guanshi = UserGuanshi.query.select_related('user').get(yaoqingma=invite_code)
user = guanshi.user
club = resolve_invite_party_club(user, None)
if club:
return club
explicit = (getattr(user, 'ClubID', None) or '').strip()
return explicit or None
except Exception:
return None
def resolve_club_id_for_wechat_request(request):
"""
小程序请求解析 club_id登录/扫码注册)。
优先级X-Club-Id > body.appId > Referer 内 wx appid > 默认 xq。
老端 fighter.js 的 wdlyhdl 未带头时,靠 Referer 识别星之界等俱乐部
优先级X-Club-Id > body.appId > Referer > body.inviteCode 反查管事 > JWT 用户归属 > 默认 xq。
老端 fighter.js 的 wdlyhdl 未带头时,靠 Referer 或邀请码识别星之界。
"""
from jituan.services.club_context import resolve_club_id_from_request
@@ -72,6 +99,18 @@ def resolve_club_id_for_wechat_request(request):
if club:
return club.club_id
invite_club = resolve_club_from_invite_code(_invite_code_from_request(request))
if invite_club:
return invite_club
# 已登录走 dashouzhuce 时往往无 Referer用 JWT 用户归属俱乐部
user = getattr(request, 'user', None)
if user is not None and getattr(user, 'is_authenticated', False):
from jituan.services.club_user import get_user_club_id
user_club = get_user_club_id(user)
if user_club:
return user_club
return resolve_club_id_from_request(request)

View File

@@ -1,12 +1,20 @@
"""邀请码 / 邀请链俱乐部隔离。"""
import logging
from jituan.models import UserWxOpenid
from jituan.services.club_resolver import resolve_club_id_for_wechat_request
from jituan.services.club_user import resolve_invite_party_club
logger = logging.getLogger(__name__)
def _invitee_has_club_binding(user, club_id):
uid = getattr(user, 'UserUID', None)
if not uid or not club_id:
return False
return UserWxOpenid.query.filter(yonghuid=uid, club_id=club_id).exists()
def assert_invite_same_club(request, inviter_user, invitee_user=None):
"""
校验邀请人与被邀请人属于同一俱乐部,且与请求 club 一致。
@@ -28,11 +36,13 @@ def assert_invite_same_club(request, inviter_user, invitee_user=None):
if invitee_user is not None:
invitee_club = resolve_invite_party_club(invitee_user, club_id)
if invitee_club is not None and invitee_club != club_id:
logger.warning(
'invite_guard 被邀请人俱乐部不符 invitee=%s invitee_club=%s req_club=%s',
getattr(invitee_user, 'UserUID', '?'), invitee_club, club_id,
)
return False, '您的账号归属与当前小程序不一致,请使用对应俱乐部小程序'
# 老用户 ClubID 可能是 xq但扫的是本俱乐部管事码允许注册并回写 ClubID
if not _invitee_has_club_binding(invitee_user, club_id) and inviter_club != club_id:
logger.warning(
'invite_guard 被邀请人俱乐部不符 invitee=%s invitee_club=%s req_club=%s',
getattr(invitee_user, 'UserUID', '?'), invitee_club, club_id,
)
return False, '您的账号归属与当前小程序不一致,请使用对应俱乐部小程序'
if invitee_club is not None and invitee_club != inviter_club:
return False, '邀请码与您的俱乐部不匹配'