Files
gongxue-base/docs/refactor/auth-payment-provider-plan.md
2026-06-28 22:19:46 +08:00

7.5 KiB
Raw Blame History

国内认证与支付接入方案

Supabase 边界

Supabase 适合承担 PostgreSQL、RLS、Auth、Edge Functions、Webhook/Hooks 等底座能力,但它不是中国大陆支付网关,也不会内置微信支付、支付宝、阿里云短信、腾讯云短信这一整套商用配置。

对本项目更稳妥的落位是:

  • Supabase/PostgreSQL保存多租户、订单、支付事件、权益、审计、登录事件。
  • apps/api:实现业务 API、短信 provider、OAuth provider、支付 provider、回调验签和幂等。
  • app_private.tenant_secrets 或生产 Vault/KMS保存租户级密钥。
  • tenant_auth_providerstenant_payment_accounts:只保存非敏感公开配置。

Supabase Auth 可继续作为最终 JWT 用户体系目标;本地重构期先用 app_private.auth_sessions 签发 tk_ session保证 Web/Taro 能跑通端到端流程。

当前已实现

  • POST /api/auth/sms/send:手机号验证码发送,验证码只保存 HMAC hash。
  • POST /api/auth/sms/verify:验证码登录,自动创建或复用 platform_users
  • GET /api/auth/me:通过 Bearer token 获取当前用户。
  • POST /api/auth/logout:吊销迁移期 session。
  • POST /api/auth/oauth/wechat-miniapp:微信小程序 code2Session 登录,后端换取 openid/unionid签发 tk_ session。
  • POST /api/auth/oauth/wechat/qqprovider 占位,已固定 PROVIDER_NOT_CONFIGURED / PROVIDER_NOT_IMPLEMENTED
  • tenant_auth_providers:租户级公开认证配置。
  • sms_verification_codes:验证码审计表,不保存明文 code。
  • auth_login_events:登录事件审计。
  • app_private.auth_sessions:迁移期 session token hash。
  • 阿里云短信 SendSms provider使用租户级 AccessKey、签名、模板发送。
  • 腾讯云短信 SendSms provider使用租户级 SecretId/SecretKey、SdkAppId、签名、模板发送。

短信 Provider

本地默认是 AUTH_SMS_PROVIDER=mock,仅开发环境返回 debugCode。生产环境如果仍为 mock会直接拒绝发送。

真实 provider

  • aliyun / aliyun-sms:阿里云短信 SendSms,需要 AccessKey、签名、模板 ID。
  • tencent / tencent-sms:腾讯云短信 SendSms,需要 SecretId、SecretKey、SdkAppId、签名、模板 ID。

密钥策略:

  • AccessKey/SecretKey 不进入 tenant_settings.public_config
  • 租户级密钥写 app_private.tenant_secrets(secret_scope='sms') 或生产 Vault。
  • 前端只能看到 provider 是否启用、签名展示名、隐私协议链接等非敏感配置。
  • provider endpoint 默认使用官方域名,生产环境只允许 HTTPS 官方域名;本地测试可使用 localhost/127.0.0.1 fake server。

阿里云短信配置示例

{
  "provider": "aliyun",
  "status": "active",
  "configPublic": {
    "signName": "工学教育",
    "templateCode": "SMS_123456789",
    "regionId": "cn-hangzhou"
  },
  "secret": {
    "secretScope": "sms",
    "secretKey": "aliyun",
    "secretJson": {
      "accessKeyId": "LTAI...",
      "accessKeySecret": "..."
    }
  }
}

腾讯云短信配置示例

{
  "provider": "tencent",
  "status": "active",
  "configPublic": {
    "smsSdkAppId": "1400000000",
    "signName": "工学教育",
    "templateId": "123456",
    "region": "ap-guangzhou",
    "templateParamSet": ["{code}"]
  },
  "secret": {
    "secretScope": "sms",
    "secretKey": "tencent",
    "secretJson": {
      "secretId": "AKID...",
      "secretKey": "..."
    }
  }
}

微信/QQ 登录

微信小程序登录应由前端传 wx.login code 到 /api/auth/oauth/wechat-miniapp,后端调用微信 code2Session 换取 openid/session_key/unionid再落 user_identities

已实现微信小程序登录主链路:

  • 前端传 code 和可选 profile
  • 后端读取租户 wechat-miniapp / wechat_miniapp provider 配置。
  • appId 存在 config_publicappSecret 存在 app_private.tenant_secrets(secret_scope='oauth')
  • provider_subject 使用 appId:openid,避免不同小程序 openid 碰撞。
  • session_key 不返回前端,不写入公开 raw_profile;当前只记录 hasSessionKey 和更新时间标记。
  • 登录成功写 auth_login_events,并签发 tk_ session。

配置示例:

{
  "provider": "wechat-miniapp",
  "displayName": "微信小程序登录",
  "status": "active",
  "configPublic": {
    "appId": "wx...",
    "envVersion": "release"
  },
  "secret": {
    "secretScope": "oauth",
    "secretKey": "wechat-miniapp",
    "secretValue": "小程序 AppSecret"
  }
}

微信网页 OAuth 和 QQ OAuth 也必须在后端完成 code 换 token、获取 openid/unionid、验错、账号合并和登录事件审计。旧 PocketBase hooks 中的邀请码/销售归属逻辑后续应拆到 referral feature不继续堆在 auth 模块里。

支付 Provider

支付不走 Supabase 内置能力。推荐继续扩展 commerce

  • POST /api/commerce/orders 只负责创建订单,金额以后端套餐为准。
  • POST /api/commerce/payments/:provider/create 后续按 provider 创建支付参数或收银台地址。
  • POST /api/commerce/payments/:provider/notify 统一落 payment_events,先验签、再幂等、再更新订单和权益。
  • 支付成功继续复用 grantSvipEntitlement,避免微信/支付宝/XPay 各写一套开通逻辑。

B 端合作商年费、服务费、服务器资源费不走学生端 orders,而是走平台账务:

  • platform_saas_plans:平台售卖给合作商的 SaaS 套餐。
  • tenant_subscriptions:合作商当前订阅状态。
  • tenant_invoicestenant_invoice_items:合作商账单与明细。
  • tenant_invoice_payments:合作商账单收款记录。
  • tenant_usage_records:学生数、题量、存储等用量指标。

支持策略:

  • 平台代收:平台商户号收款,再给租户结算。
  • 租户自收:每个租户配置自己的商户号和密钥。
  • 服务商模式:平台服务商统一管理子商户。

真实接入前需要先明确微信支付、支付宝或聚合支付是否允许你们销售的题库会员形态,以及小程序端是否涉及虚拟支付限制。

需要准备的资料

  • 阿里云或腾讯云短信:签名、模板 ID、AccessKey/SecretKey、短信用途文案。
  • 微信小程序AppID、AppSecret、主体信息、合法域名、用户手机号授权能力。
  • 微信网页/公众号AppID、AppSecret、授权回调域名。
  • QQ 互联AppID、AppKey、回调域名。
  • 微信支付商户号、API v3 key、商户证书/平台证书、回调域名、AppID 绑定关系。
  • 支付宝AppID、应用私钥、支付宝公钥、回调地址、网页/手机网站/当面付产品开通情况。
  • 每个合作商租户的收款模式:平台代收、租户自收或服务商子商户。

参考资料