Files
marco 7fd70a264d feat(cps): 微信网页授权接入——落地页拿 openid/昵称头像,用户级群统计
- 服务号网页授权(WX_MP_APPID/SECRET,区别于 App 的 WECHAT_APP_ID):
  落地页 base 静默拿 openid;点「领券」补 userinfo 拿昵称头像(交互触发避快照页)
- 新表 cps_wx_user + cps_click 加 openid + 迁移;integrations/wx_oauth
- /c/{code} 授权链路 + 回调 /wx/oauth/cb + cookie 免重复授权;click 带 openid
- admin 群详情加「群内微信用户」(领券画像)端点
- 下单归因到人需 user-level sid,本期只做身份+领券侧

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:44:11 +08:00

44 lines
1.4 KiB
Python

"""cps_wx_user 数据访问:按 openid upsert。"""
from __future__ import annotations
from sqlalchemy import func, select
from sqlalchemy.orm import Session
from app.models.cps_wx_user import CpsWxUser
def get_by_openid(db: Session, openid: str) -> CpsWxUser | None:
return db.execute(
select(CpsWxUser).where(CpsWxUser.openid == openid)
).scalar_one_or_none()
def upsert(
db: Session, *, openid: str, code: str | None = None, group_id: int | None = None,
nickname: str | None = None, headimgurl: str | None = None, unionid: str | None = None,
) -> CpsWxUser:
"""按 openid upsert。
- 首次:建行,记来源 code/group。
- 已存在:仅在传入非 None 时更新昵称/头像/unionid(base 阶段为 None,不覆盖已有画像);
并刷新 last_seen(显式 set,因 onupdate 仅在字段有变更时触发)。
"""
u = get_by_openid(db, openid)
if u is None:
u = CpsWxUser(
openid=openid, first_code=code, first_group_id=group_id,
nickname=nickname, headimgurl=headimgurl, unionid=unionid,
)
db.add(u)
else:
if nickname is not None:
u.nickname = nickname
if headimgurl is not None:
u.headimgurl = headimgurl
if unionid is not None:
u.unionid = unionid
u.last_seen = func.now()
db.commit()
db.refresh(u)
return u