Stripe 支付
Zion 通过 Stripe Payment Element 支持多币种单次支付、周期支付和退款。开始前,请先阅读支付功能概述,准备订单表并了解支付结果的处理方式。
开始前
- 注册或登录 Stripe 。
- 在 Stripe 控制台的 Developers → API keys 中复制 Publishable key,并显示 Secret key。测试密钥和正式密钥不能混用。
- 如需周期支付,在 Stripe 控制台创建产品和 Recurring Price,并复制 Price ID。参阅 Stripe 创建产品和价格 。
支付配置
配置支付配置
打开 行为 → 支付,点击 新建,填写配置名称,支付渠道 选择 Stripe,然后点击 创建并开始配置。如果这是项目中第一个支付配置,需要先绑定订单表。
填写商户信息
| 配置项 | 必填 | 填写方式 | 说明 |
|---|---|---|---|
| Publishable key | 是 | 文本 | Stripe 可公开的客户端密钥 |
| Secret key | 是 | Secret | Stripe 服务端密钥 |
| Endpoint secret | 是 | 生成并绑定 | Stripe Webhook 签名密钥,由 Zion 自动生成 |
先绑定 Secret key,再点击 Endpoint secret 旁的 生成并绑定。Zion 会用 Secret key 在 Stripe 中创建一个指向本配置 通知地址 的 Webhook,并把签名密钥保存为 Secret。
更换 Secret key 或通知地址后,点击 重新生成并绑定。Zion 会删除 Stripe 中指向同一地址的旧 Webhook,再创建新的 Webhook。
不要在 Stripe 控制台修改 Zion 创建的 Webhook 的事件或地址。需要处理其他 Stripe 事件时,另建一个带 Webhook 触发器的行为流,并在 Stripe 中为它单独创建 Webhook。
选择支付产品和客户端
在 支付产品 中勾选 Element,并在 客户端管理 中勾选 Web 应用的客户端。
配置支付结果处理
在 支付结果处理 中为 支付完成时、退款成功时、订阅状态变更时 和 订阅续费时 各绑定一个行为流,具体步骤见下文的配置支付结果行为流。
配置权限
打开 权限管理,按角色勾选允许通过这个配置发起的支付类型:
| 支付类型 | 默认 | 建议 |
|---|---|---|
| 单次支付 | 所有角色已开启 | 为需要付款的角色保留,例如已登录用户 |
| 订阅支付 | 所有角色已开启 | 为需要订阅的角色保留,用于发起和取消周期支付 |
| 退款 | 未开启 | 只为可信任的管理员角色开启 |
也可以在 设置 → 权限 → 支付 中统一查看和修改。
配置支付结果行为流
Stripe 有四种支付事件:支付完成时、退款成功时、订阅状态变更时 和 订阅续费时。只使用单次支付时,只需配置前两个。Zion 收到 Stripe 的通知后,先更新对应的支付记录,再运行对应的行为流。你需要在行为流中完成更新订单、发放或回收权益等业务。
支付完成时
用户付款成功后,支付记录变为 SUCCESSFUL,Zion 运行此行为流。支付失败或用户取消支付时不会运行。
添加入参
为行为流添加入参 payment_id(长整数),在支付配置中绑定 支付回调 → 支付 → id。
查询支付记录
添加 「数据库 - 获取数据」节点,查询支付表,条件为 id 等于 payment_id。
判断支付金额是否准确
由于实际支付的金额和订单记录中的金额可能不一致,需要判断金额准确后再做后续处理。
这一步非常重要。如果跳过,攻击者可以篡改支付金额,用远低于订单价格的金额完成支付,给你造成直接的经济损失。
添加 条件分支,用以下条件判断金额是否准确:
支付记录/总金额等于支付记录/order/{金额字段}。支付记录/币种等于支付记录/order/{币种字段}。
Stripe 的 总金额 以币种的最小单位保存,例如 10 美元保存为 1000。订单金额使用其他单位时,先换算再比较。
更新订单并发放权益
在条件成立的分支中:
- 添加 数据库 节点修改订单表,把订单状态改为已支付。
- 按业务需要发放权益,例如为对应的账户开通会员、增加积分,或发送通知。
配置完成后,行为流的结构如下:
退款成功时
退款有了结果后,退款记录变为 REFUNDED(退款成功)或 FAILED(退款失败),Zion 运行此行为流。退款成功和退款失败都会进入这个行为流,需要分别处理。
添加入参
添加入参 refund_id(长整数),在输入配置中绑定 支付回调 → 退款 → id。
查询退款记录和订单
添加 「数据库 - 获取数据」节点,查询退款表,条件为 id 等于 refund_id。
按退款结果分别处理
添加 条件分支:
退款记录/状态等于REFUNDED:退款成功。在这个分支中再添加 条件分支,判断是全额退款还是部分退款:退款记录/金额等于退款记录/支付/总金额:全额退款,修改订单状态,并回收全部已发放的权益。- 其他情况:部分退款,按业务需要修改订单状态,并回收对应部分的权益。
退款记录/状态等于FAILED:退款失败。按业务需要通知管理员或用户,订单保持原状态。
配置完成后,行为流的结构如下:
订阅状态变更时
订阅的状态或 周期结束时取消 发生变化时,Zion 更新周期性支付记录并运行此行为流,例如订阅生效、扣款逾期或订阅取消。只改变计费周期的通知不会运行。
添加入参
添加入参 recurring_payment_id(长整数),在输入配置中绑定 支付回调 → 周期性支付 → id。如需区分状态是从哪个状态变化而来,可以再添加一个文本入参,绑定 支付回调 → 变更前状态。
查询周期性支付记录
添加 「数据库 - 获取数据」节点,查询周期性支付表,条件为 id 等于 recurring_payment_id。
按订阅状态分别处理
添加 条件分支:
- 状态为
ACTIVE:为订阅账户开通或恢复订阅权益。 - 状态为
PAST_DUE或UNPAID:扣款未成功,按业务需要暂停权益或提醒用户。 - 状态为
CANCELED或INCOMPLETE_EXPIRED:订阅已终止,收回订阅权益。
在各分支中添加 数据库 节点更新数据时,可以用周期性支付记录中的字段作为过滤条件:
- 更新账户:条件为账户表的
id等于周期性支付记录/帐户id。 - 更新订单:条件为订单表的
id等于周期性支付记录/第一笔订单id。
用户取消订阅后,周期结束时取消 会先变为 true,此时订阅仍在当前周期内有效,可以按需提醒用户;周期结束后状态才会变为 CANCELED。
配置完成后,行为流的结构如下:
订阅续费时
订阅产生新一期账单时,Zion 为这一期创建支付记录并运行此行为流。这一期的支付记录还没有关联订单,此行为流的唯一任务时创建订单并返回订单 id。
这个行为流必须使用 同步执行,并把新订单的 id 作为出参返回。否则编辑器会提示错误,本期支付记录也无法关联订单。
设置执行方式和出参
把行为流设为 同步执行,并添加一个长整数类型的出参,用来返回新订单的 id。
添加入参
添加入参 payment_id(长整数),在输入配置中绑定 支付回调 → 支付 → id。
查询支付和订单记录
- 添加 「数据库 - 获取数据」节点,查询支付表,条件为
id等于payment_id。 - 添加 「数据库 - 获取数据」节点,查询订单表,条件为
id等于支付记录/周期性支付/第一笔订单id,获取首期订单记录。
创建本期订单
添加 数据库 节点在订单表中新增一条订单,金额、账户和商品等字段使用上一步获取到的订单记录填写,订单状态设为待支付。
返回订单 id
把新订单的 id 赋给出参。Zion 会把它写回本期支付记录。
配置完成后,行为流的结构如下:
这里只创建订单,不要发放权益。本期扣款成功后会触发 支付完成时,在那里按金额校验结果更新订单和发放本期权益。
配置前端支付行为
单次支付
添加创建订单行为
调用支付行为前,先在已绑定的订单表中创建订单。订单金额、商品和用户等业务数据应保存在订单表中。
添加支付行为
在按钮或其他组件的触发器中添加 支付,支付类型 选择 单次支付,支付配置 选择前面创建的Stripe配置,支付产品 选择 Element。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 订单表 id | 长整数 | 是 | 已绑定订单表中的订单记录 id |
| 货币 | 文本 | 是 | Stripe 支持的币种代码,如 USD |
| 金额 | 小数 | 是 | 使用币种的最小单位;例如收取 10 美元填写 1000 |
| 商品名 | 文本 | 否 | 收银台显示的商品名称 |
| 商品描述 | 文本 | 否 | 收银台显示的商品描述 |
不同币种有最低支付金额,详见 Stripe 文档 。
支付行为的 成功时 表示前端调用已成功返回,最终支付状态仍以 支付完成时 为准。出于安全考虑,成功时 不能配置修改数据的行为。
处理支付完成
支付成功后,Zion 把支付记录更新为 SUCCESSFUL,并运行 支付完成时 绑定的行为流,在其中更新订单和发放权益。配置方法见支付完成时。
显示最终结果
前端查询订单表或支付表显示最终状态。需要及时刷新时,可以采用订阅查询的方法。
退款
开放退款权限
退款权限默认不开放。在支付配置的 权限管理 中,只为可信任的管理员角色勾选 退款。
添加退款行为
添加 支付 行为,支付类型 选择 退款。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 支付表 id | 长整数 | 是 | 需要退款的支付记录 id,不是订单 id |
| 退款金额 | 小数 | 是 | 使用原支付币种的最小单位;超过剩余可退金额时,按剩余可退金额退款 |
可以用订单 id 作为过滤条件查询对应的支付记录,再绑定其 id。只有 SUCCESSFUL 或 PARTIALLY_REFUNDED 的支付记录可以退款。
处理退款结果
发起退款后,退款记录状态为 REFUNDING。Stripe 通知退款结果后,Zion 把退款记录更新为 REFUNDED 或 FAILED,并运行 退款成功时 绑定的行为流。Stripe 直接拒绝退款请求时,退款记录会变为 FAILED,退款行为进入 失败时。配置方法见退款成功时。
周期支付
发起订阅
添加 支付 行为,支付类型 选择 周期支付,类型 选择 发起,支付配置 选择前面创建的 Stripe 配置,支付产品 选择 Element。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 订单表 id | 长整数 | 是 | 首期订阅对应的订单记录 id |
| 价格 id | 文本 | 是 | Stripe Recurring Price 的 id |
| 商品名 | 文本 | 否 | 收银台显示的商品名称 |
| 商品描述 | 文本 | 否 | 收银台显示的商品描述 |
发起后,Zion 创建一条状态为 INCOMPLETE 的周期性支付记录和一条关联首期订单的支付记录。首期扣款成功时触发 支付完成时;订阅生效时触发 订阅状态变更时。前端分支只表示收银台交互结果,订阅是否生效以周期性支付记录的状态为准。
取消订阅
添加 支付 行为,支付类型 选择 周期支付,类型 选择 取消,并绑定需要取消的 周期支付表 id。
取消后订阅会在当前周期结束时终止:周期性支付记录的 周期结束时取消 立即变为 true,状态在周期结束时变为 CANCELED,此时触发 订阅状态变更时。
常见问题
- 生成并绑定按钮不可用:先绑定 Secret key,再生成 Endpoint secret。
- 收银台无法打开:确认 Publishable key 和 Secret key 来自同一个 Stripe 环境,并且支付行为的必填参数都已绑定。
- 支付状态没有更新:确认 Endpoint secret 是用当前 Secret key 生成的,并且支付配置已经发布。
- 扣款金额不符合预期:Stripe 金额使用币种的最小单位,绑定金额前确认币种的小数位数。
- 订阅已授权但权益未启用:以周期性支付记录的
ACTIVE状态为准,不要只依赖前端成功分支。 - 续费产生支付记录但没有订单:检查 订阅续费时 的行为流是否为同步执行,并返回了订单 id。