接入文档 V0.1.0

为什么这么设计(含被否掉的方案)

这一页写给以后接手的人(包括六个月后的我们自己)。里面每条都是"不这么做会付出什么代价"的实测或官方口径。

核心决策:把微信能力收敂到一个独立站点

考虑过的方案结论原因
A. 每个业务站各自接微信否 网页授权域名只有 2 个名额、每月限改 5 次,且子域要逐个精确配(官方示例明确 pay.qq.com 不被 www.qq.com 覆盖);接入第 3 个站点就没名额了。密钥也会散落到多台机器。
B. 用 nginx 反代把多个域名伪装成一个否 网上有这种"授权域名做一级目录反代"的技巧,但它要求业务站能在子路径下运行、 Cookie 与 Host 会错乱,且属于钻空子而非合规路径。
C. 再申请一个服务号否 需要新的认证(300 元/次)+ 新备案域名,而且用户要关注两个号,推送分裂在两处,运营更差。
D. 微信第三方平台(代公众号运营)暂缓(未来多主体时用) 扫码授权换 authorizer_access_token 能绕开一堆域名限制,但需要开放平台第三方应用资质审核、 组件令牌体系与代运营协议。当前只有一个运营主体,收益不抵复杂度。
E. 本方案:统一中台 + 一次性票据中转采纳 授权域名只花 1 个名额、支付授权目录只花 1 条、密钥集中一处、新站点接入是"注册一条记录"而不是"改微信后台"。

关键取舍逐条

1) 为什么不接管公众号的「消息与事件推送 URL」

这个位置只能配一套,现在属于 edusoho。抢过来会让老系统的关注回复、菜单点击、关键词回复全部失效—— 而 edusoho 的服务器不在这次改造范围内。于是关注状态改为主动轮询(/user/get + /user/info/batchget)。

代价:关注状态有分钟级延迟、拿不到"刚刚关注"的即时事件,因此48 小时客服消息这条兜底通道在当前形态下不可用。 如果以后 edusoho 下线或迁走,把 URL 换到中台即可解锁即时事件与客服消息(代码里已预留 WxEventController 的位置)。

2) 为什么只用稳定版 access_token 的普通模式

token 是账号级的。普通版 /cgi-bin/token 重复获取会让上一个 token 失效; 强制刷新(force_refresh=true)更是立刻顶掉。中台与 edusoho 共用同一个公众号, 所以任何一处乱刷 token 都会让另一处业务当场瘫痪。稳定版普通模式在有效期内重复调用返回同一个 token,不互踢。

3) 为什么回跳用一次性票据,而不是 URL 里带 openid

URL 会进浏览器历史、Referer、以及站点自己的访问日志。把 openid(微信身份标识)长期外泄, 等于任何看到日志的人都能替该用户发起登录流程。票据 60 秒、单次、绑定站点,且兑换需要站点密钥签名。

4) 为什么支付走托管收银台,而小程序不走

JSAPI 支付校验的是"拉起收银台的页面 host 与路径"是否命中支付授权目录(共 5 条)。 把支付页收到中台一个 host 上,就只需 1 条目录覆盖所有站点。 但小程序 web-view 内嵌 H5 支付被微信限制,所以小程序必须用 scene=miniprogram 直接调起。

5) 为什么订阅授权引导页也放中台

wx-open-subscribe 要求页面 host 在「JS 接口安全域名」(5 条)里。放中台,所有站点共用 1 条。

6) 为什么 PC 支付用"带参数二维码 → 手机打开收银台"而不是 Native 扫码

Native 需要单独申请开通,且二维码内容必须由商户自己渲染(中台不引第三方二维码服务, 把订单号交给外部网站生成二维码是信息外泄)。用公众号自带的 qrcode/create + showqrcode, 扫码后进入同一个收银台链路,不额外开产品、不额外占域名。若以后必须支持"PC 直接扫钱包码支付", 再补 scene=native 的渲染分支即可(接口已实现)。

7) 为什么密钥不下放给站点,但 session_key 例外

AppSecret、商户私钥、APIv3 属于"全局凭据",一旦下放到 N 个站点就变成 N 倍泄露面。 而小程序的 session_key 只能由持有它的服务端解密手机号,属于"单用户短期凭据", 必须交给站点服务端 —— 代价是明确要求它不落日志、不下发前端。

8) 为什么一个商户号可以给多个站点用,但不能给别的法人用

一个商户号最多可关联 50 个 AppID,同主体多站点共用完全合规。 但用 A 公司的商户号收 B 公司的钱,属于无证经营支付业务(二清),是硬性红线。 所以模型设计成 pay_channels 多条:以后复制给其他机构时,每家机构填自己的商户号。

9) 为什么短信腿留在站点侧

腾讯云国内短信必须先做企业实名资质报备,签名要与营业执照主体一致, 平台审核后还要运营商报备 7–10 个工作日,长期不发会被闲置失效。 不同机构的签名与资质不同,集中代收反而成为阻塞点,所以中台只负责微信三档(模板/订阅/小程序), 把"触达不到"如实标成 skipped 交回站点降级。

已知边界(不是缺陷,但要知道)

如果以后要扩到多机构(复制发布)

  1. 每家机构:自己的服务号 + 小程序 + 商户号 → 在后台各自登记 profile 与 pay_channel。
  2. 域名:同主体可以继续用这一个中台 host(在它们的公众号后台填同一个授权域名即可, 前提是该域名的备案主体与它们一致);主体不同时,把中台代码整套部署到对方域名下 (本系统无状态、SQLite 单文件,可以按机构一份实例)。
  3. 站点注册表已经支持多站点、多账号、多通道路由,不需要改代码。

本页内容随代码一起版本化(V0.1.0)。发现文档与实际行为不一致,请当缺陷报告。