Files
Django/jituan/services/club_resolver.py

123 lines
3.9 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 解析。"""
import logging
import re
import requests
from django.conf import settings
from jituan.constants import CLUB_ID_DEFAULT
from jituan.models import Club
logger = logging.getLogger(__name__)
_REFERER_APPID_RE = re.compile(r'servicewechat\.com/(wx[0-9a-fA-F]+)/', re.I)
def resolve_club_by_appid(app_id):
if not app_id:
return None
try:
return Club.query.filter(wx_appid=app_id, status=1).first()
except Exception:
return Club.objects.filter(wx_appid=app_id, status=1).first()
def get_club_wx_credentials(club_id):
"""优先读 club 表xq 缺省时回退 settings 全局配置(兼容现网)。"""
club_id = club_id or CLUB_ID_DEFAULT
try:
club = Club.query.get(club_id=club_id)
except Club.DoesNotExist:
club = None
if club and club.wx_appid and club.wx_secret:
return club.wx_appid, club.wx_secret, club
if club_id == CLUB_ID_DEFAULT:
return (
getattr(settings, 'WEIXIN_APPID', ''),
getattr(settings, 'WEIXIN_SECRET', ''),
club,
)
return '', '', club
def resolve_club_id_for_wechat_request(request):
"""
小程序请求解析 club_id登录/扫码注册)。
优先级X-Club-Id > body.appId > Referer 内 wx appid > 默认 xq。
老端 fighter.js 的 wdlyhdl 未带头时,靠 Referer 识别星之界等俱乐部。
"""
from jituan.services.club_context import resolve_club_id_from_request
header = (request.META.get('HTTP_X_CLUB_ID') or '').strip()
if not header and hasattr(request, 'headers'):
header = (request.headers.get('X-Club-Id') or '').strip()
if header:
return header
app_id = ''
data = getattr(request, 'data', None) or {}
if isinstance(data, dict):
app_id = (data.get('appId') or data.get('app_id') or '').strip()
if not app_id:
referer = request.META.get('HTTP_REFERER', '') or ''
matched = _REFERER_APPID_RE.search(referer)
if matched:
app_id = matched.group(1)
if app_id:
club = resolve_club_by_appid(app_id)
if club:
return club.club_id
return resolve_club_id_from_request(request)
def wechat_jscode2session_for_request(request, code):
"""按请求上下文换取 openid多俱乐部小程序"""
club_id = resolve_club_id_for_wechat_request(request)
return jscode2session(code, club_id=club_id)
def jscode2session(code, club_id=None, app_id=None):
"""
按俱乐部微信配置换取 openid。
club_id 与 app_id 二选一app_id 用于从小程序 appId 反查 club。
"""
club = None
if app_id:
club = resolve_club_by_appid(app_id)
club_id = club.club_id if club else club_id
appid, secret, club = get_club_wx_credentials(club_id)
if not appid or not secret:
return {'errmsg': '俱乐部微信配置未设置'}
url = 'https://api.weixin.qq.com/sns/jscode2session'
params = {
'appid': appid,
'secret': secret,
'js_code': code,
'grant_type': 'authorization_code',
}
try:
response = requests.get(url, params=params, timeout=10)
result = response.json()
if 'openid' in result:
return {
'openid': result['openid'],
'session_key': result.get('session_key', ''),
'unionid': result.get('unionid', ''),
'club_id': club_id or CLUB_ID_DEFAULT,
'wx_appid': appid,
}
errcode = result.get('errcode', 'unknown')
errmsg = result.get('errmsg', '未知错误')
return {'errmsg': f'[{errcode}]{errmsg}'}
except requests.exceptions.Timeout:
return {'errmsg': '请求微信接口超时'}
except Exception as e:
logger.exception('jscode2session 异常 club_id=%s', club_id)
return {'errmsg': f'请求微信接口异常: {str(e)}'}