跳到正文

接入第三方 SaaS 订阅与支付 ​

通过 GoodVision 客户工作区,第三方 SaaS 可以接入套餐选择、订阅、支付和账单管理。本文介绍如何配置平台入口、处理登录和支付跳转,并同步订阅状态。

当前方案支持固定月付或年付 SaaS 使用费、套餐月度 Credits 和已发布的一次性加量包。Credits 表示使用额度,不是可提现储值余额;未声明的超额扣费不会自动启用。

接口使用 billing_interval=month|year 指定月付或年付周期。

当前可用性

客户的套餐、订阅、支付和账单页面由 GoodVision 客户工作区提供。Commerce Checkout Sandbox API Product 已实现,当前应用在开发者控制台获得对应调用配置后才能使用;Production 路径尚未开放。

可先完成平台跳转、OIDC BFF 和页面接入,再按已开通的 Scope 接收脱敏的订阅、支付和退款事件。

接入方式 ​

场景第三方产品GoodVision 平台
产品功能展示合作方自己的业务页面不复制第三方业务功能
定价、比较、FAQ用独立页面承载平台 iframe,并提供独立打开入口/console/pricing 提供个人/企业及月/年套餐
订阅、支付、账单、权益管理在弹窗中嵌入平台管理页,或独立打开/console/subscription 与 /console/billing 提供管理操作
Application、API Product、Webhook只显示 Developer Console 入口Developer Console 管理技术接入
产品权限判断按已开通接口查询必要状态根据订单、付款和权限检查返回当前结果

第三方不需要实现第二套本地套餐目录、订单或支付状态机。SaaSdemo 的 /app/pricing 在工作区中保留左侧导航并嵌入平台定价 iframe;/pricing 提供带官网顶栏的独立宿主页。两个入口的“我的订阅”都打开管理弹窗;平台价格页与管理页分别承载不同任务。侧栏在定价、订阅和账单之间保留所选 product,独立链接保留同一应用/环境/产品。第三方可以承接平台已冻结的支付返回导航,但价格、订单、支付、账单和使用权限仍由平台管理。

跳转到客户工作区 ​

在第三方服务端配置当前环境的客户工作区 URL。定价入口为 /console/pricing,订阅管理为 /console/subscription,账单为 /console/billing。配置示例请参见 SaaSdemo 的 platform.subscriptionUrl 和 platform.billingUrl。

可独立打开,也可在已登记的 Origin 下通过 iframe 嵌入。仅支持已公布的范围选择和展示参数:

参数必填性支持值/省略行为
embed可选1;省略时独立打开
locale可选zh-CN|en-US;省略时沿用当前语言
view可选subscription|billing;省略时沿用当前页面
theme可选light|dark;省略时沿用当前主题
application、environment🔴 条件必填定价入口或显式选择应用时成组填写:已授权 slug 和 sandbox|production
product🔴 条件必填多产品无法唯一确定时填写;可唯一确定时省略

例如 /console/pricing?application=<slug>&environment=sandbox&product=<code>&locale=zh-CN。参数只选择当前已授权范围,不授予权限;SaaSdemo 实例由服务端绑定应用和环境,URL 不匹配时拒绝。production 枚举不表示 Production 路径已开放。

不接受未发布的业务 Query 参数或第三方 handoff Token。不得附加 Organization、ProductTenant、Plan、金额、币种、Provider、伪造支付结果、Token、Secret 或任意 return_url。客户工作区根据实时身份和服务端权限确定操作范围。

iframe 未登录时会向父页面发送 goodvision.customer-billing.auth_required,父页面应使用固定 targetOrigin 把登录提升到顶层窗口,登录后刷新 iframe。支付方式更新和套餐操作仍校验 CSRF 与幂等键;Stripe Hosted Checkout 始终整页打开,不在第三方 iframe 内模拟支付完成。

标准独立页使用平台 Session;已开通嵌入合同的应用可使用 auth=parent-bff 通道,由宿主同源 BFF 转发平台页面的请求。双方验证精确 Origin、原 iframe 和封闭消息,服务端继续核验当前真人、企业、应用及能力。Token、Cookie 和 CSRF Secret 不穿过消息或 URL。Session 过期时恢复统一登录。

按应用打开方式返回 ​

应用内置到 Console,与平台定价/订阅页嵌入应用,是两个独立的接入方向。应用打开方式详见网页应用开发与配置。

平台商业 iframe 创建原付款后,向其直接父窗口发送:

json
{
  "type": "goodvision.customer-billing.checkout_started",
  "provider": "stripe",
  "checkout_url": "https://checkout.stripe.com/<平台返回的原付款路径>"
}

父窗口须核验平台配置的精确 Origin、原商业 iframe 的 event.source、消息字段及 HTTPS checkout.stripe.com 来源,再处理原 URL;不要仅凭消息名称接受任意地址。

应用打开方式付款与返回
跳转/独立访问顶层打开原付款 URL,支付服务商返回平台已冻结的应用入口,再读取原订阅
隔离 iframe 内置保留原 Console 和应用 iframe;用户点击后在独立付款窗口打开,完成或取消后恢复原应用订阅页
受信 qiankun 直挂同样保留原 Console 挂载;经应用自己的已登记来源处理付款返回,不把独立应用路径写入 Console 顶层地址

内置模式的窗口通信、关联值校验和清理由应用实现,步骤见处理订阅付款与回跳。平台不接受浏览器自定义 return_url,也不会把支付完成消息作为商业授权。弹窗被拦截、用户关闭或未收到回执时保留原订单;回读并恢复原付款。仅在原订阅、履约和使用权限均确认后开放相应功能。

平台侧商业流程 ​

以下步骤全部发生在 GoodVision 平台和支付服务商页面中:

  1. 新客户创建企业、提交本人客户资料,经平台审核并完成合法账务和商业准备。创建企业不等于可以付款,不复制其它客户的账务账户。
  2. 定价页读取当前应用、环境和产品已发布的方案;Free 是否提供、个人/企业、周期、席位、FAQ 和优惠均由配置决定。
  3. 客户点击订阅,在确认弹窗核对条款、首期和续期金额;平台冻结原订单与订阅。
  4. 付费进入顶层 Stripe Hosted Checkout;免费方案明确接受后激活,不创建零金额 Stripe 付款。
  5. 平台通过可信 Webhook 或服务端查询确认原单付款,更新原订阅。年付 Credits 仍逐月发放,重放不会重复到账。
  6. 签名履约事件进入接入方 Inbox,完成产品开通并回传结果;确认 ProductAccess 后开放功能。
  7. 回跳原订阅,读取套餐、Credits 和投递结果;失败或结果不明时恢复原订单,不创建替代新购。

页面回跳只代表导航完成,不代表支付成功或权益生效。

第三方服务端职责 ​

  • Authorization Code + PKCE、同源 Session 和 CSRF。
  • 第三方产品自己的用户体验和业务 API。
  • 从运行时配置读取平台入口,不在前端硬编码环境地址。
  • 已开通对应 API 产品时,查询必要的 ProductAccess 状态或接收签名 Webhook。
  • 用户回到第三方产品后重新读取权限;未确认前保持受限状态。

第三方 BFF 可按已开通的嵌入合同转发平台页面的命令,但不拥有订单、支付意图或 Hosted Checkout 状态机。取消、退款、方案和付款方式操作仍由平台管理页发起并由对应 Owner 最终核验。

可选 API 与事件接入 ​

部分产品需要在后台感知访问状态或生命周期事件。只有 Developer Console 已为当前 Application 签发对应 API Product 时才实现:

  • ProductAccess/Entitlement 只读查询;
  • 订阅状态只读查询;
  • 版本化订阅、支付/退款和访问状态事件;
  • 通过签名 Webhook 进行幂等同步。

从当前应用的 API 配置获取 Base URL、Audience、Scope、路径、字段和事件 Schema。接收 Webhook 时验签,按 event_id 去重,并用 resource_version 防止旧事件覆盖新状态;版本缺口需通过已授权接口重新查询。

套餐/VIP 权限变更 ​

在 Developer Console 为 Application 申请 oem.access_context.changed.v1。该事件表示有效权限上下文已变化,不表示“用户被授予 VIP Role”。套餐等级属于 Plan/SaaSSubscription;产品可用能力由 ProductAccess/Entitlement 表达;Role/Capability 只表达管理和操作权限。

套餐和权限变更的 Webhook 同步流程

  1. 对原始 Body 校验 X-GV-Signature,校验 Header 与信封中的事件 ID/类型一致,并要求 data.open_platform_application_id + environment 与当前 Receiver 的服务端配置精确匹配;不得按客户 Organization 或应用 slug 回退。
  2. 按 event_id 持久化到 Inbox 后快速返回 2xx。
  3. 使用 data.access_revision 识别重复或旧版本。新版本进入 pending_readback,并立即限制对应成员的本地访问权限。
  4. 产品权限快照尚未向标准第三方应用开放,申请 Scope 不代表已经能够回查。需要处理新权限版本或版本缺口时,保持受限并通过支持渠道确认恢复方式;不要调用内部接口或猜测用户映射。
  5. 正式回查能力开放后,按公开合同确认同一应用、客户空间和成员,且查询结果版本不小于事件版本时,再一次性更新本地必要的权限记录。授权撤销、范围不匹配或查询失败时,继续限制访问。

使用接口定义的 Entitlement 判断套餐能力,例如合成值 relaydesk.tier.pro。role=VIP 表示角色,不能替代套餐权限判断;接入方也不维护 plan_code -> entitlement 的固定映射。

上线验收 ​

  • 定价宿主页、订阅管理弹窗和独立链接均消费平台页面,不维护第二套商业事实。
  • 客户商业入口来自服务端环境配置,且没有未发布 Query 参数。
  • /console/pricing、/console/subscription 与 /console/billing 仅在已登记 Origin 嵌入;第三方不能自行扩大 frame-ancestors。
  • 同一嵌入和独立链接保持已授权应用/环境/产品;错误范围拒绝,主题、FAQ 与原请求恢复保持稳定。
  • 独立认证或已批准的父 BFF 通道均核验当前身份,第三方不通过 URL 或消息传递 Token、Secret 或组织标识。
  • 支付页面回跳、Webhook 投递和登录成功都不直接开放产品功能。
  • 第三方只在 ProductAccess/Entitlement 已确认生效后开放受限能力。
  • Client Secret、支付凭证和完整卡片数据不进入浏览器、日志、监控或工单。
  • 未签发 SaaS Billing API Product 时,第三方不调用猜测的商业路径。

继续阅读 SaaSdemo 接入案例、SaaS 账务契约、认证与授权和接收 Webhook。

权限快照接口尚未向标准应用开放。接入前请查看产品权限快照回查,并通过支持渠道确认客户范围的读取权限。

开发者文档。第三方接入不需要内部运营平台权限。