# Subotiz MCP Source: https://docs.subotiz.com/zh/ai/mcp Subotiz MCP 是基于 [Model Context Protocol](https://spec.modelcontextprotocol.io/) 的开放工具集服务器。AI 代理可通过标准化 MCP 工具与 Subotiz 支付与订阅能力交互(客户、商品、定价、订阅、交易、退款、发票、Webhook 及开发者文档查询等)。 **了解更多**:了解 Subotiz 产品与能力,请访问 [官网首页](https://www.subotiz.com/)。 ## 前置条件 1. 支持 Streamable Http MCP 的宿主(如 VS Code 1.101+、Claude Desktop、Cursor、Trae 等) 2. 有效的 Subotiz 访问凭证(Token) ## Subotiz MCP 地址 * sandbox 环境:[https://api.sandbox.subotiz.com/mcp](https://api.sandbox.subotiz.com/mcp) * prod 环境:[https://api.subotiz.com/mcp](https://api.subotiz.com/mcp) ## 对外 MCP 配置 连接官方托管服务时,只需配置 URL 与 `Authorization: Bearer`,**无需其他请求头**。 **Cursor** 配置示例(写入 Cursor 的 MCP 设置即可): ```json theme={null} { "mcpServers": { "my-remote-server": { "url": "{{MCP_URL}}", "headers": { "Authorization": "Bearer YOUR_TOKEN_HERE" } } } } ``` 将 `MCP_URL` 替换为您所需使用环境的 MCP 地址,将 `YOUR_TOKEN_HERE` 替换为您的 Subotiz 访问 Token 即可。在 VS Code、Cursor、Claude Desktop 等宿主中,把上述内容合并到各自的 MCP 配置(如 `servers` 或 `mcpServers`)中即可使用。 **API Key 获取**:配置中的 Token 即 Subotiz API Key。获取步骤与认证方式请参阅 [认证文档](/zh/api/authentication-1)。 *** ## 工具列表 完整工具列表(工具名、类别、path、说明)在单独文档中维护,便于同步更新: | 工具名 | 类别 | path | 说明 | | ----------------------- | ------- | ------------------------------------- | ------------------------- | | `create_customer` | 客户 | POST /api/v1/front/customer/create | 创建客户 | | `list_customer` | 客户 | GET /api/v1/front/customer | 列表查询客户 | | `list_products` | 商品 | GET /api/v1/products | 列表查询商品 | | `create_product` | 商品 | POST /api/v1/products | 创建商品 | | `list_prices` | 定价 | GET /api/v1/prices | 列表查询定价 | | `create_price` | 定价 | POST /api/v1/prices | 创建定价 | | `list_subscription` | 订阅 | GET /api/v1/subscription | 列表查询订阅 | | `list_trades` | 交易 | GET /api/v1/trades | 列表查询交易 | | `list_refund` | 退款 | GET /api/v1/trades/:trade\_id/refunds | 按交易查询退款列表 | | `list_invoice` | 发票 | GET /api/v1/invoices | 列表查询发票 | | `list_webhook_event_v2` | Webhook | GET /api/v2/webhook/events | 列表查询 Webhook 事件(v2) | | `get_llm_full_doc` | 开发者文档 | - | 获取完整 LLM 文档(llm-full.txt) | | `get_llm_doc` | 开发者文档 | - | 获取精简 LLM 文档(llm.txt) | *** # Subotiz CLI Source: https://docs.subotiz.com/zh/ai/subotiz-cli `subotiz-cli` 是 Subotiz API 的命令行客户端,适合开发者、运维人员和自动化 Agent 在本地或 CI 环境中快速调用 Subotiz API。 它提供配置管理、环境切换、Raw API 调用、请求预览、输出格式化等能力。命令输出遵循自动化友好的约定:可解析结果写入 stdout,调试、告警和错误信息写入 stderr,方便脚本和 Agent 稳定消费。 ## 一条命令快速安装 首次使用推荐直接运行: ```bash theme={null} npx @subotiz/cli@latest install ``` 这条命令会完成安装、初始化和基础配置引导: * 同步内置 Subotiz skills。 * 初始化本地配置文件。 * 可选交互式设置 API Key。 * 展示脱敏后的配置结果,便于确认当前环境和配置路径。 完成后可以立即检查版本: ```bash theme={null} subotiz-cli version ``` 当前 npm 包支持 macOS 和 Linux 的 `x64`、`arm64` 平台,内置预编译二进制,安装时不需要配置 Go 私有模块,也不需要额外下载 release 资产。 ## 适用场景 * 快速完成 Subotiz API 的本地调试和请求预览。 * 在 CI、脚本或 Agent 环境中调用支付、订阅、商品、价格等 API。 * 管理 `sandbox` 和 `prod` 等多环境配置。 * 通过 `--dry-run` 预览请求,降低误操作风险。 * 使用 JSON、NDJSON、CSV 或 `jq` 表达式处理 API 响应。 ## 在Agent中使用 cursor、claude code等编码agent的skills已经默认支持,若您的agent需要使用自定义的skills目录,请将`~/.agents/skills/`目录下对应skills拷贝过去 ## 关键指令 ### 查看版本 ```bash theme={null} subotiz-cli version ``` ### 查看当前配置 ```bash theme={null} subotiz-cli config show ``` `config show` 会对 API Key 等敏感字段做脱敏处理。 ### 查看环境列表 ```bash theme={null} subotiz-cli env list ``` ### 切换默认环境 ```bash theme={null} subotiz-cli env use sandbox ``` ### 新增或更新环境 ```bash theme={null} subotiz-cli env add sandbox \ --base-url https://api.sandbox.subotiz.com \ --api-key "$SUBOTIZ_API_KEY" ``` ### 预览 API 请求 使用 `--dry-run` 可以只输出脱敏后的请求预览,不会真正发送请求: ```bash theme={null} subotiz-cli api GET /api/v1/products \ --base-url https://api.sandbox.subotiz.com \ --api-key "$SUBOTIZ_API_KEY" \ --query '{"limit":20,"status":"active"}' \ --dry-run ``` ### 发送 POST 请求 ```bash theme={null} subotiz-cli api POST /api/v1/products \ --base-url https://api.sandbox.subotiz.com \ --api-key "$SUBOTIZ_API_KEY" \ --data '{"name":"demo-product","active":true}' \ --dry-run ``` 确认请求无误后,再移除 `--dry-run` 发送真实请求。 ### 从文件读取请求体 `--data` 支持内联 JSON,也支持 `@file`: ```bash theme={null} subotiz-cli api PATCH /api/v1/products/prod_demo \ --base-url https://api.sandbox.subotiz.com \ --api-key "$SUBOTIZ_API_KEY" \ --data @payload.json \ --dry-run ``` ## 环境变量 在 CI、脚本或 Agent 环境中,推荐使用环境变量传递运行参数: ```bash theme={null} SUBOTIZ_BASE_URL=https://api.sandbox.subotiz.com \ SUBOTIZ_API_KEY="replace-with-your-own-key" \ SUBOTIZ_ENV=sandbox \ subotiz-cli api GET /api/v1/products --dry-run ``` | 变量 | 说明 | | ------------------ | ----------------------------------- | | `SUBOTIZ_API_KEY` | 未提供 `--api-key` 时使用的 API Key。 | | `SUBOTIZ_ENV` | 未提供 `--env` 时使用的环境名称。 | | `SUBOTIZ_BASE_URL` | 未提供 `--base-url` 时使用的 API Base URL。 | `SUBOTIZ_ENV` 主要影响 API 请求时的环境解析,不会改变 `env list`、`env use`、`env add`、`env remove` 对配置文件的展示或修改语义。 ## 常用全局参数 | 参数 | 说明 | | ------------------------------ | ---------------------------------------------- | | `--env ` | 指定环境名称,覆盖 `SUBOTIZ_ENV` 和配置中的默认环境。 | | `--api-key ` | 指定 API Key,覆盖 `SUBOTIZ_API_KEY` 和配置中的密钥。 | | `--base-url ` | 指定 API Base URL,覆盖 `SUBOTIZ_BASE_URL` 和配置中的地址。 | | `--format ` | 指定 API 响应输出格式,默认 `json`。 | | `--jq ` | 使用 jq 表达式过滤 JSON 输出。 | | `--dry-run` | 输出脱敏后的请求预览,不发送请求。 | | `--debug` 或 `-v` | 开启 stderr 调试日志。 | | `--timeout ` | 设置请求超时时间,例如 `10s` 或 `1m`。 | | `--config ` | 指定配置文件路径。为空时使用默认配置路径。 | ## 输出约定 `subotiz-cli` 将机器可读输出和面向人的诊断信息分开: * stdout:JSON、NDJSON、CSV 或 dry-run JSON 预览。 * stderr:错误、告警、调试日志、request ID、trace ID 和排障提示。 自动化脚本应只解析 stdout。stderr 的内容用于排障,不建议作为稳定协议依赖。 ## 安全建议 * 不要在文档、Issue、Prompt、命令历史或共享日志中粘贴真实 API Key。 * 优先使用 `SUBOTIZ_API_KEY`、CI Secret 或配置占位符管理密钥。 * 调用生产环境写请求前,先使用 `--dry-run` 预览请求。 * 对 `prod` 或 `https://api.subotiz.com` 发起 `POST`、`PUT`、`PATCH`、`DELETE` 请求时,CLI 会向 stderr 输出生产写操作告警。 * `config show`、dry-run 输出、调试输出和错误输出会对 API Key、Bearer Token、secret、password、cookie、session 等敏感值做脱敏处理。 # 鉴权 Source: https://docs.subotiz.com/zh/api/authentication-1 Subotiz OpenAPI 使用 **API Key** 进行身份验证。每次请求都需要在 HTTP 请求头中携带有效的 API Key,网关会对其进行校验,通过后才会将请求转发至后端服务。 ## 获取 API Key 登录 Subotiz 商家后台,进入 **设置 > 开发者设置** 页面,即可查看和管理您的 API Key。 API Key 仅在创建时完整显示一次,请妥善保存。若遗失,需重新生成(原 Key 将立即失效)。 ## 发起鉴权请求 ### 请求头格式 所有 OpenAPI 请求都必须在 HTTP 请求头中包含以下字段: | 请求头 | 值 | 说明 | | --------------- | ----------------------- | ---------------------------------- | | `Authorization` | `Bearer {your_api_key}` | 将 `{your_api_key}` 替换为您的实际 API Key | ### 示例 ```bash theme={null} curl -X GET "https://api.subotiz.com/openapi/v1/orders" \ -H "Authorization: Bearer {your_api_key}" ``` ## 密钥轮换 当密钥存在泄露风险或需要定期更新时,可以在开发者设置页面对密钥进行**轮换**。 ### 轮换流程 1. 在开发者设置页面发起密钥轮换,系统将生成一个新的 API Key 2. 系统为旧 Key 设置过渡期(默认 3 分钟,可在轮换时自定义) 3. 在过渡期内,**新旧 Key 均可通过鉴权**,请尽快将您的服务切换至新 Key 4. 过渡期结束后,旧 Key 自动失效,仅新 Key 有效 请在旧 Key 失效前完成服务切换,避免请求中断。如果您配置了 Webhook,密钥轮换同样会影响 Webhook 的签名验证,建议在过渡期内同时支持新旧两个密钥验签,详见 [Webhook 概述](/zh/webhook/introduction-2)。 ## 错误处理 当鉴权失败时,接口将返回 HTTP `401` 状态码。以下是常见错误原因及处理建议: | 错误原因 | 处理建议 | | ----------------------- | ------------------------------------------ | | 请求未携带 `Authorization` 头 | 确认请求头中包含 `Authorization: Bearer {key}` | | API Key 无效或不存在 | 确认 Key 是否正确,或从后台重新获取 | | API Key 已过期或被撤销 | 在开发者设置中重新生成 Key | | `Authorization` 格式错误 | 确保格式为 `Bearer {key}`,注意 `Bearer` 后有且仅有一个空格 | ### 错误响应示例 ```json theme={null} { "code": "unauthorizedError", "message": "ApiKey authentication is required" } ``` # 业务对象 Source: https://docs.subotiz.com/zh/api/checkout-session-object 结账会话(Checkout Session)业务对象字段说明 | 属性名 | 类型 | 描述 | | ------------------------ | ------------------ | ---------------------------------------------------------------------------------------------------- | | id | int | checkout session id | | access\_no | string | 接入方编号 | | merchant\_id | string | 商户唯一标识 | | order\_id | string | 接入方订单号 | | trade\_id | string | 交易单ID | | customer | Customer | 顾客信息 | | status | string | checkout session 状态:
open: 创建成功
expire: 过期
complete: 交易完成 | | expire\_time | int | 有效期(秒), 使用创建时间加上有效期可计算过期时间 | | return\_url | string | 支付成功跳转地址 | | cancel\_url | string | 取消支付跳转地址 | | callback\_url | string | webhook 通知地址 | | session\_url | string | Checkout页面URL | | mode | string | 支付模式,用于判断是否校验商品信息:
checkout:校验商品数据,默认值
payment:不校验商品数据 | | total\_amount | string | 总金额 | | integration\_method | string | 集成模式:
hosted:托管式,默认为该模式
embedded :嵌入式集成 | | redirect\_on\_completion | string | 嵌入式ui模式的重定向行为
always: 支付成功后,会自动重定向到 return\_url
if\_required: 仅在有重定向的付款方式才会重定向到return\_url | | created\_at | string | 创建时间 | | payment\_token | string | 订阅支付时,返回的支付凭证,用于后续订阅续费 | | metadata | map\[string]string | 一组可附加到对象上的键值对,允许您以结构化格式存储附加信息。 | ## Customer | 属性名 | 类型 | 描述 | | --------- | ------ | -------- | | id | string | 顾客iD | | payer\_id | string | 接入方顾客的ID | | email | string | 顾客邮箱 | # 业务对象 Source: https://docs.subotiz.com/zh/api/customer-object 顾客(Customer)业务对象字段说明 | 属性名 | 类型 | 描述 | | ------------------- | ------------------ | ------------------------------------- | | customer\_id | string | 顾客 Id | | email | string | 顾客邮箱 | | name | string | 顾客姓名 | | type | string | 顾客类型
customer: 会员
guest: 游客 | | create\_at | string | 顾客创建时间 | | payer\_id | string | 接入方顾客 ID | | email\_subscription | int | 是否订阅营销电子邮件通知
1:不订阅
2:订阅 | | metadata | map\[string]string | 一组可附加到对象上的键值对,允许您以结构化格式存储附加信息。 | | address | CustomerAddress | 顾客地址 | ## CustomerAddress | 属性名 | 类型 | 描述 | | :----------- | :----- | :------ | | line1 | string | 地址行1 | | line2 | string | 地址行2 | | city | string | 城市 | | province | string | 省/州代码 | | postal\_code | string | 邮政编码 | | country | string | 国家/地区代码 | # 业务对象 Source: https://docs.subotiz.com/zh/api/customer-portal-object 顾客门户(Customer Portal)业务对象字段说明 | 属性名 | 类型 | 描述 | | :--------------------- | :----- | :------------- | | customer\_portal\_link | string | Subotiz 客户门户链接 | # 业务对象 Source: https://docs.subotiz.com/zh/api/discount-object 折扣(Discount)业务对象字段说明 | 属性名 | 类型 | 描述 | | ---------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------- | | id | string | 折扣对象的唯一 ID | | discount\_name | string | 折扣名称 | | status | string | 折扣状态:
draft:折扣已创建但尚未激活或对用户可见
not\_started:折扣已定义,但其开始时间尚未到达
ongoing:折扣当前处于活动状态并可供使用
completed:折扣已结束,不再可供使用 | | discount\_code | string | 在结账时应用的折扣代码 | | discount\_method | string | 折扣方式:仅当设置为 "discount\_code" 时才能使用折扣代码:
discount\_code:通过折扣代码折扣 | | starts\_at | string | 折扣开始时间(UTC 格式),空字符串表示无限制 | | ends\_at | string | 折扣结束时间(UTC 格式),空字符串表示无限制 | | created\_at | string | 创建时间,UTC 格式字符串 | | updated\_at | string | 最后更新时间,UTC 格式字符串 | # 业务对象 Source: https://docs.subotiz.com/zh/api/dispute-object | 属性名 | 类型 | 描述 | | --------------------- | ------ | ------------- | | id | string | Subotiz 争议 ID | | channel\_dispute\_id | string | 渠道争议 ID | | merchant\_id | string | 商户 ID | | order\_id | string | 交易单 ID | | payment\_channel | string | 支付渠道 | | payment\_method | string | 支付方式 | | dispute\_status | string | 争议状态 | | dispute\_reason | string | 争议原因 | | order\_amount | string | 订单金额 | | order\_currency | string | 订单币种 | | dispute\_amount | string | 争议金额 | | dispute\_currency | string | 争议币种 | | dispute\_create\_time | string | 争议创建时间 | | dispute\_update\_time | string | 最后更新时间 | | dispute\_due\_time | string | 回应截止日 | # 错误处理 Source: https://docs.subotiz.com/zh/api/errors Subotiz 使用常规 HTTP 响应代码来指示 API 请求的成功或失败。 常见错误码: * 2xx:表示成功。 * 4xx:表示客户端侧的错误(例如缺少必需参数、扣款失败等)。 * 5xx:表示 Subotiz 服务器处理过程中发生错误。 ## 错误格式 当请求错误时,会以固定形式返回错误提示: | **属性** | **类型** | **描述** | | :------ | :----- | :----- | | code | string | 业务错误码 | | message | string | 错误原因 | # 概述 Source: https://docs.subotiz.com/zh/api/introduction-1 Subotiz API 请求需要使用 HTTPS 并且符合 RESTful API 规范。 ## 要求 * 所有 API 请求都必须通过 HTTPS 发送 * 根据 Subotiz API 的规范,所有请求需要携带公共请求头 * 所有请求必须通过身份认证 * 使用 JSON 格式作为交互的数据格式 ## 公共请求头 | **Header** | **示例值** | **说明** | | ------------- | ------------------------------------ | ------------------------------------------------ | | Authorization | `Bearer {your_api_key}` | API Key 鉴权,获取方式参阅:[鉴权](/zh/api/authentication-1) | | Content-Type | application/json | 请求体格式 | | Request-Id | 1c801db7-dcda-4e93-8c06-d1414c426f0d | 请求的唯一id | # 业务对象 Source: https://docs.subotiz.com/zh/api/invoice-object 发票(Invoice)业务对象字段说明 | 属性名 | 类型 | 描述 | | --------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------ | | invoice\_id | string | 发票ID | | merchant\_id | string | 商户ID | | trade\_id | string | 交易单ID | | subscription\_id | string | 订阅ID | | price\_id | string | 定价方案ID | | customer\_id | string | Subotiz平台顾客ID | | order\_id | string | 第三方订单号 | | original\_invoice\_id | string | 原始发票ID,用于退款发票引用原始发票 | | refund\_order\_id | string | 关联的退款订单ID | | amount | string | 支付金额,截取两位小数 | | currency | string | 币种 | | biz\_status | string | 发票状态:
open: 初始化
pending: 处理中
success: 支付成功
failed: 支付失败
refunded: 全额退款
partially\_refunded: 部分退款 | | invoice\_type | string | 发票类型:
initial: 首次支付
trial: 试用期
renewal: 订阅续费
refund: 退款 | | paid\_at | string | 支付成功时间 | | cycle\_index | int | 订阅的当前周期索引 | | created\_at | string | 创建时间 | | metadata | map\[string]string | 一组可附加到对象上的键值对,允许您以结构化格式存储附加信息。 | | discounts | Discounts | 发票上的折扣,包括此发票的所有折扣信息 | | price\_version\_id | string | 定价方案版本 ID | ## Discounts | 属性名 | 类型 | 描述 | | --------------- | ------------------------ | --------- | | current\_period | CurrentPeriodDiscount\[] | 当前时期的折扣详情 | ## CurrentPeriodDiscount | 属性名 | 类型 | 描述 | | ---------------- | ------ | -------- | | discount\_id | string | 折扣的唯一标识符 | | discount\_amount | string | 折扣金额 | | discount\_code | string | 使用的折扣代码 | # 元数据 Source: https://docs.subotiz.com/zh/api/metadata Subotiz 支持为多个核心资源对象添加 metadata 字段,用于存储额外的结构化信息。metadata 是键值对(key-value)格式的数据,不会影响 Subotiz 核心支付、订阅等业务逻辑,仅作为开发者自定义数据的载体,方便关联自有系统信息、追踪业务流程或标注资源属性。 ## 核心特性与限制 ### 字段限制 * 最多支持 **20 个键(key)**,超出会返回参数校验错误 * 键(key)长度最多 **40 个字符**,值(value)长度最多 **500 个字符** * 键和值均以字符串(string)形式存储,不支持嵌套 JSON、数字、布尔值等类型 ### 支持的资源对象 metadata 可用于以下 Subotiz 资源,支持创建时添加、后续查询和更新:Checkout Session、Subscription、Invoice、Trade、Customer、Refund Order ## 常见使用场景 1. **关联自有系统 ID**:将您的订单号(order\_id)、用户 ID(user\_id)绑定到 Subotiz 资源,例如给 Checkout Session 添加 metadata: ```json theme={null} { "your_order_id": "ORD123456", "your_user_id": "U789" } ``` 2. **退款追踪**:存储退款原因、操作人等信息。例如给 Refund Order 添加 metadata: ```json theme={null} { "refund_reason": "product_defect", "operator": "admin_001" } ``` 3. **业务流程标注**:给 Subscription 添加 metadata,用于自有系统识别订阅等级 ```json theme={null} { "plan_level": "premium", "renewal_reminder": "true" } ``` 4. **跨资源关联**:通过 Checkout Session 的透传规则,实现数据向后续生成资源(如 Subscription、Trade)的传递 ## Metadata 继承机制 Subotiz 的 metadata 采用「独立存储 + 按需透传」机制,**不自动继承父资源 metadata**。支持通过 Checkout Session 创建时指定的参数,将数据透传到后续生成的资源中。 * **无商品路径**(mode=payment) ```mermaid theme={null} graph LR A[商户] -->|调用创建结账会话接口
指定:trade_data.metadata 参数| B[Checkout Session] B -->|用户支付触发生成 Trade
透传 trade_data.metadata| C[Trade] ``` * **有商品路径**(mode=checkout) ```mermaid theme={null} graph LR A[商户] -->|调用创建结账会话接口
指定:subscription_data.metadata 参数| B[Checkout Session] B -->|支付成功触发创建 Subscription
透传 subscription_data.metadata| C[Subscription] C -->|续订生成 Invoice
通过 subscription_id 关联查询 metadata| D[Invoice] ``` ### 透传规则 * **参数隔离**:metadata(自身)、trade\_data.metadata、subscription\_data.metadata 是独立参数,需分别指定。 * **独立存储**:每个资源仅保存自身被透传的参数,修改上游资源的 metadata 不会影响已生成的下游资源。 * **关联查询**:下游资源若需获取上游未直接透传的 metadata,需通过关联 ID(如 subscription\_id)主动查询对应资源详情。
## 注意事项 * **禁止存储敏感信息**:不要在 metadata 中存储银行卡号、身份证号等敏感数据,仅用于非敏感业务标识。 * **透传参数必填性**:若需向 Trade/Subscription 透传 metadata,需在创建 Checkout Session 时明确指定对应参数,否则下游资源的 metadata 为空。 * **字段校验**:超过键数量、字符长度限制会返回 400 Bad Request,错误信息会明确提示超限字段。 # 业务对象 Source: https://docs.subotiz.com/zh/api/payment-object 支付流水(Payment)业务对象字段说明 | 属性名 | 类型 | 描述 | | ------------------------ | -------------------- | --------------------- | | id | string | 数据库主键ID(雪花ID,字符串格式) | | out\_trans\_id | string | 支付流水ID | | trade\_id | string | 订单ID / 交易ID | | merchant\_id | string | 商户ID | | payment\_method | string | 支付方式 | | payment\_channel | string | 支付渠道 | | status | string | 支付状态 | | amount | string | 支付金额,截断到两位小数 | | currency | string | 币种 | | channel\_trade\_id | string | 渠道交易ID | | order\_trans\_id | string | 订单交易ID(全局唯一,代表一次支付尝试) | | channel\_payment\_method | ChannelPaymentMethod | 支付方式信息 | | created\_at | string | 创建时间 | | channel\_ret\_code | string | 渠道返回码 | | channel\_ret\_msg | string | 渠道返回消息 | ## ChannelPaymentMethod | 属性名 | 类型 | 描述 | | ---- | -------- | ------------- | | type | string | 类型,固定值 "card" | | card | CardInfo | 卡片信息 | ## CardInfo | 属性名 | 类型 | 描述 | | ------- | ------ | ------------- | | brand | string | 卡片品牌 | | country | string | 发卡国家 | | last4 | string | 卡号后4位 | | funding | string | 卡片类型(信用卡/借记卡) | # 业务对象 Source: https://docs.subotiz.com/zh/api/price-object 定价方案(Price)业务对象字段说明 | 属性名 | 类型 | 描述 | | ------------------ | ------------------ | ---------------------------------------------------- | | id | string | 定价方案ID | | price\_name | string | 定价方案名称 | | price\_alias | string | 定价方案别名 | | product\_id | string | 关联商品ID | | merchant\_id | string | 商户ID | | currency | string | 币种 | | billing\_type | string | 计费类型:one\_time-一次性、recurring-周期性 | | price\_val | string | 一次性付费价格,billing\_type为one\_time时必填 | | description | string | 定价描述 | | price\_plan | PricePlan | 定价计划 | | biz\_status | string | 状态:
draft: 草稿
active: 已激活
frozen: 已冻结 | | has\_trial | boolean | 是否启用试用期:
0: 否
1: 是 | | trial\_period | TrialPeriod | 试用期配置 | | created\_at | string | 创建时间 | | price\_type | string | 定价模型 | | usage\_amount | string | 资源包用量 | | usage\_unit | string | 资源包用量单位 | | model\_type | string | 定价模型二级类型 | | billing\_threshold | string | 扣费金额阈值 | | trial\_type | int | 试用类型
0: 免费试用
1: 付费试用 | | trial\_amount | string | 试用价格 | | metadata | map\[string]string | 一组可附加到对象上的键值对,允许您以结构化格式存储附加信息。 | ## PricePlan | 属性名 | 类型 | 描述 | | --------------------- | ------------ | ----------------------------- | | id | string | 定价计划ID,系统生成的唯一标识 | | name | string | 计划名称,显示给用户的名称 | | billing\_cycle\_unit | string | 计费周期单位,如:day、week、month、year等 | | billing\_cycle\_count | int | 计费周期数量,如:1个月、3个月等 | | is\_infinite | boolean | 是否无限期,true表示永久有效 | | base\_price\_val | string | 基础价格,计划的基础定价 | | plan\_description | string | 计划描述,详细的计划说明信息 | | price\_plan\_tiers | PriceTier\[] | 分级定价明细,不同周期的具体价格 | ## PriceTier | 属性名 | 类型 | 描述 | | --------------------- | ------ | ------------------------ | | billing\_cycle\_index | int | 计费周期索引,表示第几个周期 | | price\_val | string | 价格值,该周期的具体价格 | | discount\_type | string | 优惠类型,如:percentage、fixed等 | | discount\_value | string | 优惠值,具体的优惠金额或比例 | ## TrialPeriod | 属性名 | 类型 | 描述 | | -------------------- | ------ | -------------------------- | | trial\_period\_unit | string | 试用期单位,必填,如:day、week、month等 | | trial\_period\_count | int | 试用期数量,必填,如:7天、1个月等 | # 业务对象 Source: https://docs.subotiz.com/zh/api/product-object 商品(Product)业务对象字段说明 | 属性名 | 类型 | 描述 | | --------------------- | ------------------ | ------------------------------ | | product\_id | string | 商品ID (唯一标识) | | product\_name | string | 商品名称 | | product\_status | string | 商品状态 | | merchant\_product\_id | string | 商品ID | | category\_id | string | 商品类型ID | | description | string | 商品描述 | | image\_url | string | 商品图片地址 | | category\_name | string | 商品类型名称 | | created\_by | string | 创建者 | | created\_at | string | 创建时间 | | features | ProductFeature\[] | 商品权益 | | metadata | map\[string]string | 一组可附加到对象上的键值对,允许您以结构化格式存储附加信息。 | ## ProductFeature | 属性名 | 类型 | 描述 | | ---- | ------ | ----------------------------------------------------- | | id | string | 权益ID | | name | string | 权益名称 | | type | string | 权益类型
quantitative - 定量权益
qualitative - 定性权益 | # 业务对象 Source: https://docs.subotiz.com/zh/api/refund-object 退款(Refund)业务对象字段说明 | 属性名 | 类型 | 描述 | | --------------- | ------------------ | ------------------------------------------------------------- | | refund\_id | string | 退款单ID | | trade\_id | string | 交易单ID | | currency | string | 金额对应的交易币种,编码遵照ISO4217 | | callback\_url | string | Webhook通知回调地址 | | reason | string | 退款原因 | | refund\_amount | string | 退款金额 | | refund\_status | string | 退款状态
pending: 处理中
failed: 退款失败
succeeded: 退款成功 | | metadata | map\[string]string | 元数据 | | failure\_reason | FailureReason | 退款失败原因 | | ref\_arn | string | 发卡行侧返回退款凭证 | | finished\_at | string | 退款完成时间 | ## FailureReason | 属性名 | 类型 | 描述 | | ---------------- | ------ | ---------- | | code | string | 系统返回交易返回码 | | message | string | 系统返回交易返回说明 | | channel\_code | string | 渠道返回码 | | channel\_message | string | 渠道返回说明 | | raw\_error | string | 原始错误信息 | # 业务对象 Source: https://docs.subotiz.com/zh/api/subscription-object 订阅(Subscription)业务对象字段说明 | 属性名 | 类型 | 描述 | | ---------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | id | string | 订阅唯一标识 | | customer\_id | string | Subotiz 顾客唯一标识 | | email | string | 顾客邮箱 | | cycle\_index | int | 订阅当前所处周期 | | metadata | map\[string]string | 元数据 | | cancel\_reason | string | 终止订阅的原因 | | sub\_merchant\_id | string | 商户唯一标识 | | status | string | 订阅业务状态:
init - 待生效
trial - 试用期
active - 生效中
paused - 已暂停
past\_due - 逾期
unpaid - 未支付
canceled - 已终止
incomplete - 未完成 | | price\_id | string | 商品定价方案唯一标识 | | total\_cycles | int | 总周期数(0表示无限期) | | current\_period\_start | string | 当前计费周期开始时间 | | current\_period\_end | string | 当前计费周期结束时间 | | next\_invoice\_date | string | 下一次续订时间 | | created\_at | string | 创建时间 | | updated\_at | string | 更新时间 | | cancel\_at | string | 终止订阅时间(可选) | | order\_id | string | 接入方订单 id,创建 checkout session 时传入的 order\_id 一致。 | | source\_trade\_id | string | 来源交易订单 ID | | price\_type | string | 定价模型 | | price\_version\_id | string | 商品定价方案版本唯一标识 | | first\_source\_channel | string | 该结账会话的首次创建来源 | | last\_source\_channel | string | 该结账会话的最后访问来源 | | fixed\_term | string | 固定期限期数。`"0"` 表示持续订阅(无固定期限) | | is\_renewable | bool | 是否支持到期后自动转为持续订阅 | | end\_at | string | 订阅结束时间。空字符串表示持续订阅(无结束时间) | | current\_period | int | 当前周期序号 | | is\_canceling | bool | 是否正在取消中 | | launch\_cancel\_at | string | 发起取消的时间 | | expected\_cancel\_at | string | 预期取消的时间 | # 业务对象 Source: https://docs.subotiz.com/zh/api/trade-object 交易单(Trade)业务对象字段说明 | 属性名 | 类型 | 描述 | | ----------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | trade\_id | string | 交易单ID | | access\_no | string | 接入方编号 | | merchant\_id | string | 商户ID | | amount | string | 支付金额,截取两位小数 | | currency | string | 币种 | | customer\_id | string | 平台顾客 ID | | callback\_url | string | webhook 通知回调地址 | | metadata | map\[string]string | 一组可附加到对象上的键值对,允许您以结构化格式存储附加信息。 | | last\_payment\_error | LastPaymentError | 最后一次支付错误信息,如果该字段有值,则表示支付失败。 | | next\_action | NextAction | 下一步操作 | | order\_id | string | 接入方订单号 | | last\_trans\_id | string | 订单流水ID。 | | paid\_at | string | 支付成功时间 | | payment\_mode | string | 支付业务模式:
subscription:首次订阅支付,需要收集顾客支付信息,传入 payment\_method\_data 字段,支付成功时会返回 payment\_token 用于后续订阅续费
recurring\_payment:订阅续订支付,需要传入 payment\_token 完成支付,无需收集用户支付信息 | | payment\_token | string | 订阅支付时,返回的支付凭证,用于后续订阅续费 | | payment\_method | string | 支付方式 | | payment\_channel | string | 支付渠道 | | return\_url | string | 在类似 3DS 跳转支付场景时,支付渠道受理成功后重定向的页面 | | trade\_status | string | 支付单状态:
requires\_payment\_method:初始状态
payment\_failed:支付失败
processing:支付处理中
succeeded:支付成功
closed:已关闭 | | txn\_time | string | 交易发起时间,客户端发起接口的时间 | | created\_at | string | 创建时间 | | refund\_status | string | 退款状态:
no\_refund:无退款
partially\_refunded:部分退款
refunded:退款完成 | | total\_refunded\_amount | string | 退款金额,截取两位小数 | | session\_id | string | Session 唯一标识 | | session\_url | string | Session 的访问地址 | | refer\_info | ReferInfo | 顾客的来源信息 | | order\_type | string | 在不同采购或计费场景下生成的订单类型:
onetime\_payment: 一次性付款请求创建的交易订单
subscription: 发起订阅付款请求创建的交易订单
recurring\_payment: Subotiz订阅续订服务创建的交易订单
token\_payment: 商家使用现有订阅合同令牌向客户扣款时创建的交易订单 | | line\_items | LineItem\[] | 客户购买的商品明细 | | discounts | Discounts | 应用于交易的折扣,包括此交易的所有折扣信息 | | closed\_at | string | 交易关闭时间 | | closed\_reason | string | 关闭原因
timeout: 交易支付超时
renewal\_failed: 订阅续订扣费失败(含重试) | | first\_source\_channel | string | 交易关联的结账会话首次创建来源渠道 | | last\_source\_channel | string | 交易关联的结账会话最后访问的来源渠道 | | billing\_address | BillingAddress | 顾客的账单地址信息 | ## ReferInfo | 属性名 | 类型 | 描述 | | ------------- | ------ | ------------------------------------------------------------------------ | | country\_code | string | 客户下单时的国家 (ISO 2格式) | | ip | string | 客户下单时的 IP | | device | string | 客户设备的类型
pc:指个人电脑设备类型,包括台式机和笔记本电脑。
mobile:指移动端设备类型,包括智能手机和平板电脑。 | | user\_agent | string | 客户端的 user agent | ## NextAction | 属性名 | 类型 | 描述 | | -------- | ------------------ | -------------------------------- | | type | string | 客户端下一步需要操作的类型:
redirect:重定向 | | redirect | NextActionRedirect | 重定向信息 | | client | NextActionClient | 客户端操作信息 | ## NextActionRedirect | 属性名 | 类型 | 描述 | | --- | ------ | ------- | | url | string | 重定向 URL | ## NextActionClient | 属性名 | 类型 | 描述 | | ------------------- | ------ | ---------------- | | confirm\_url | string | 确认支付 URL | | apple\_pay\_session | string | ApplePay 创建使用的数据 | ## LastPaymentError | 属性名 | 类型 | 描述 | | ------- | ------ | ---------- | | code | string | 系统返回交易返回码 | | message | string | 系统返回交易返回说明 | ## LineItem | 属性名 | 类型 | 描述 | | ----------- | ------ | ---------------- | | product\_id | string | 所购买商品的商品 ID | | price\_id | string | 与所购买商品关联的定价方案 ID | | price | string | 应用任何折扣之前的价格 | | quantity | int | 购买的商品数量 | ## Discounts | 属性名 | 类型 | 描述 | | --------------- | ------------------------ | --------- | | current\_period | CurrentPeriodDiscount\[] | 当前时期的折扣详情 | ## CurrentPeriodDiscount | 属性名 | 类型 | 描述 | | ---------------- | ------ | -------- | | discount\_id | string | 折扣的唯一标识符 | | discount\_amount | string | 折扣金额 | | discount\_code | string | 使用的折扣代码 | ## BillingAddress | 属性名 | 类型 | 描述 | | :---------------- | :----- | :---------------------- | | name | string | 收件人全名 | | address\_line1 | string | 地址行1,主要街道地址 | | address\_line2 | string | 地址行2,附加地址信息 | | country\_code | string | 国家代码,ISO2格式(如:US、GB、CN) | | province\_code | string | 省/州代码(如:CA代表加利福尼亚州) | | city | string | 城市名称 | | area | string | 区域/区/县名称 | | postal\_code | string | 邮政编码 | | phone | string | 不含国家代码的电话号码 | | phone\_area\_code | string | 电话国家代码(如:+1、+44、+86) | | email | string | 用于账单通知和联系的电子邮件地址 | # 创建结账会话 Source: https://docs.subotiz.com/zh/api/v1-checkout-session-create-checkout-session openapi/v1-zh.yaml POST /api/v1/session 创建结账会话 # 过期结账会话 Source: https://docs.subotiz.com/zh/api/v1-checkout-session-expire-checkout-session openapi/v1-zh.yaml POST /api/v1/session/{session_id}/expire 主动使结账会话过期 主动使结账会话过期 # 获取结账会话详情 Source: https://docs.subotiz.com/zh/api/v1-checkout-session-get-checkout-session openapi/v1-zh.yaml GET /api/v1/session/{session_id} 结账会话详情 结账会话详情 # 获取结账会话列表 Source: https://docs.subotiz.com/zh/api/v1-checkout-session-list-checkout-session openapi/v1-zh.yaml GET /api/v1/session 查询结账会话列表 查询结账会话列表 # 创建顾客 Source: https://docs.subotiz.com/zh/api/v1-customer-create-customer openapi/v1-zh.yaml POST /api/v1/front/customer/create 创建顾客 # 删除顾客 Source: https://docs.subotiz.com/zh/api/v1-customer-delete-customer openapi/v1-zh.yaml POST /api/v1/front/customer/delete 删除顾客 # 获取顾客详情 Source: https://docs.subotiz.com/zh/api/v1-customer-get-customer openapi/v1-zh.yaml GET /api/v1/front/customer/{customer_id} 获取顾客详情 # 获取顾客列表 Source: https://docs.subotiz.com/zh/api/v1-customer-list-customer openapi/v1-zh.yaml GET /api/v1/front/customer 获取顾客列表 # 顾客门户 API 认证 Source: https://docs.subotiz.com/zh/api/v1-customer-portal-api-auth openapi/v1-zh.yaml POST /api/v1/customer_portal/auth 顾客门户 API 认证 # 更新顾客 Source: https://docs.subotiz.com/zh/api/v1-customer-update-customer openapi/v1-zh.yaml POST /api/v1/front/customer/update 更新顾客 # 结束折扣 Source: https://docs.subotiz.com/zh/api/v1-discount-end-discount openapi/v1-zh.yaml POST /api/v1/discount/{id}/end 结束折扣 # 获取折扣详情 Source: https://docs.subotiz.com/zh/api/v1-discount-get-discount openapi/v1-zh.yaml GET /api/v1/discount/{id} 获取折扣详情 # 列出折扣 Source: https://docs.subotiz.com/zh/api/v1-discount-list-discount openapi/v1-zh.yaml GET /api/v1/discount 列出折扣 # 获取争议单详情 Source: https://docs.subotiz.com/zh/api/v1-dispute-get-dispute openapi/v1-zh.yaml GET /api/v1/disputes/{dispute_id} 按 ID 查询单笔争议详情 按 ID 查询单笔争议详情 # 获取争议单列表 Source: https://docs.subotiz.com/zh/api/v1-dispute-list-dispute openapi/v1-zh.yaml GET /api/v1/disputes 按条件分页查询争议列表 按条件分页查询争议列表 # 获取发票详情 Source: https://docs.subotiz.com/zh/api/v1-invoice-get-invoice openapi/v1-zh.yaml GET /api/v1/invoices/{invoice_id} 查询发票详情 查询发票详情 # 获取发票列表 Source: https://docs.subotiz.com/zh/api/v1-invoice-list-invoice openapi/v1-zh.yaml GET /api/v1/invoices 查询发票列表 查询发票列表 # 按交易ID查询支付流水列表 Source: https://docs.subotiz.com/zh/api/v1-payment-list-payments-by-trade-id openapi/v1-zh.yaml GET /api/v1/payments 根据交易ID获取支付流水列表。返回指定交易的所有支付流水(包括重试记录)。 根据交易ID获取支付流水列表。返回指定交易的所有支付流水(包括重试记录)。 # 按时间范围查询支付流水列表 Source: https://docs.subotiz.com/zh/api/v1-payment-query-payments openapi/v1-zh.yaml GET /api/v1/payments/list 根据时间范围和筛选条件查询支付流水。支持基于游标的分页导航。商户可以根据创建时间筛选支付记录。 根据时间范围和筛选条件查询支付流水。支持基于游标的分页导航。商户可以根据创建时间筛选支付记录。 # 变更定价方案状态 Source: https://docs.subotiz.com/zh/api/v1-price-change-price-status openapi/v1-zh.yaml POST /api/v1/prices/{price_version_id}/status 变更定价方案状态 # 创建定价方案 Source: https://docs.subotiz.com/zh/api/v1-price-create-price openapi/v1-zh.yaml POST /api/v1/prices 创建定价方案 # 获取商品定价详情 Source: https://docs.subotiz.com/zh/api/v1-price-get-price openapi/v1-zh.yaml GET /api/v1/prices/{price_id} 定价方案详情 定价方案详情 # 查询定价方案版本 Source: https://docs.subotiz.com/zh/api/v1-price-get-price-version openapi/v1-zh.yaml GET /api/v1/prices/version/{price_version_id} 查询定价方案版本详情 查询定价方案版本详情 # 获取商品定价列表 Source: https://docs.subotiz.com/zh/api/v1-price-list-price openapi/v1-zh.yaml GET /api/v1/prices 定价方案列表 定价方案列表 # 查询定价方案版本列表 Source: https://docs.subotiz.com/zh/api/v1-price-list-price-version openapi/v1-zh.yaml GET /api/v1/prices/version 查询定价方案版本列表 # 更新商品状态 Source: https://docs.subotiz.com/zh/api/v1-product-change-product-status openapi/v1-zh.yaml POST /api/v1/products/{product_version_id}/status 更新商品状态 # 创建商品 Source: https://docs.subotiz.com/zh/api/v1-product-create-product openapi/v1-zh.yaml POST /api/v1/products 创建商品 # 获取商品详情 Source: https://docs.subotiz.com/zh/api/v1-product-get-product openapi/v1-zh.yaml GET /api/v1/products/{product_id} 商品详情 商品详情 # 获取商品版本详情 Source: https://docs.subotiz.com/zh/api/v1-product-get-product-version openapi/v1-zh.yaml GET /api/v1/products/version/{product_version_id} 获取商品版本详情 # 获取商品列表 Source: https://docs.subotiz.com/zh/api/v1-product-list-product openapi/v1-zh.yaml GET /api/v1/products 商品列表 商品列表 # 获取商品类别 Source: https://docs.subotiz.com/zh/api/v1-product-list-product-categories openapi/v1-zh.yaml GET /api/v1/product-categories 获取商品类别 # 获取商品版本列表 Source: https://docs.subotiz.com/zh/api/v1-product-list-product-version openapi/v1-zh.yaml GET /api/v1/products/version 获取商品版本列表 # 创建退款单 Source: https://docs.subotiz.com/zh/api/v1-refund-create-refund openapi/v1-zh.yaml POST /api/v1/trades/{trade_id}/refunds 创建退款单 # 获取退款单详情 Source: https://docs.subotiz.com/zh/api/v1-refund-get-refund openapi/v1-zh.yaml GET /api/v1/trades/{trade_id}/refunds/{refund_id} 退款单详情 退款单详情 # 获取退款单列表 Source: https://docs.subotiz.com/zh/api/v1-refund-list-refund openapi/v1-zh.yaml GET /api/v1/trades/{trade_id}/refunds 退款单列表 退款单列表 # 取消订阅 Source: https://docs.subotiz.com/zh/api/v1-subscription-cancel-subscription openapi/v1-zh.yaml POST /api/v1/subscription/{subscription_id}/cancel 取消订阅 # 获取订阅详情 Source: https://docs.subotiz.com/zh/api/v1-subscription-get-subscription openapi/v1-zh.yaml GET /api/v1/subscription/{subscription_id} 订阅详情 订阅详情 # 查询指定期数的订阅使用量 Source: https://docs.subotiz.com/zh/api/v1-subscription-get-subscription-usage openapi/v1-zh.yaml GET /api/v1/subscription/{subscription_id}/usage 商家查询指定期数的订阅使用量 商家查询指定期数的订阅使用量 # 获取订阅列表 Source: https://docs.subotiz.com/zh/api/v1-subscription-list-subscription openapi/v1-zh.yaml GET /api/v1/subscription 查询订阅合同列表 查询订阅合同列表 # 暂停订阅 Source: https://docs.subotiz.com/zh/api/v1-subscription-pause-subscription openapi/v1-zh.yaml POST /api/v1/subscription/{subscription_id}/pause 暂停订阅 # 数量变更试算 Source: https://docs.subotiz.com/zh/api/v1-subscription-preview-subscription-quantity openapi/v1-zh.yaml GET /api/v1/subscription/{subscription_id}/quantity-preview 按给定数量只读试算下期预计金额,供席位变更前展示;仅 active 且 billing_dimension=quantity 订阅支持,无副作用 按给定数量只读试算下期预计金额,供席位变更前展示;仅 active 且 billing\_dimension=quantity 订阅支持,无副作用 # 上报使用量 Source: https://docs.subotiz.com/zh/api/v1-subscription-record-subscription-usage openapi/v1-zh.yaml POST /api/v1/subscription/{subscription_id}/record_usage 商家上报使用量 商家上报使用量 # 订阅续订 Source: https://docs.subotiz.com/zh/api/v1-subscription-renewal-subscription openapi/v1-zh.yaml POST /api/v1/subscription/{subscription_id}/renewal 商家发起续订 商家发起续订 # 重启订阅 Source: https://docs.subotiz.com/zh/api/v1-subscription-resume-subscription openapi/v1-zh.yaml POST /api/v1/subscription/{subscription_id}/resume 重启订阅 # 撤回取消订阅 Source: https://docs.subotiz.com/zh/api/v1-subscription-revoke-cancel-subscription openapi/v1-zh.yaml POST /api/v1/subscription/{subscription_id}/revoke-cancel 撤回取消订阅 # 撤回待生效价格变更 Source: https://docs.subotiz.com/zh/api/v1-subscription-revoke-price-change openapi/v1-zh.yaml POST /api/v1/subscription/{subscription_id}/revoke-price-change 撤回通过 effective_type=end_of_period 安排、尚未到下一计费周期生效的价格变更;已立即生效的变更无法撤回 撤回通过 effective\_type=end\_of\_period 安排、尚未到下一计费周期生效的价格变更;已立即生效的变更无法撤回 # 订阅价格变更 Source: https://docs.subotiz.com/zh/api/v1-subscription-update-subscription openapi/v1-zh.yaml POST /api/v1/subscription/{subscription_id} 商家发起订阅定价方案变更 商家发起订阅定价方案变更 # 修改订阅固定周期 Source: https://docs.subotiz.com/zh/api/v1-subscription-update-subscription-fixed-term openapi/v1-zh.yaml POST /api/v1/subscription/{subscription_id}/update/fixed_term 修改订阅固定周期 # 创建交易单 Source: https://docs.subotiz.com/zh/api/v1-trade-create-trade openapi/v1-zh.yaml POST /api/v1/trades 创建交易单 # 获取交易单详情 Source: https://docs.subotiz.com/zh/api/v1-trade-get-trade openapi/v1-zh.yaml GET /api/v1/trades/{trade_id} 交易单详情 交易单详情 # 获取交易单列表 Source: https://docs.subotiz.com/zh/api/v1-trade-list-trade openapi/v1-zh.yaml GET /api/v1/trades 查询交易单列表 查询交易单列表 # Webhook 端点列表 Source: https://docs.subotiz.com/zh/api/v1-webhook-list-endpoint openapi/v1-zh.yaml GET /api/v2/webhook/endpoints 获取 webhook 端点配置列表 获取 webhook 端点配置列表 # Webhook事件列表 V1 Source: https://docs.subotiz.com/zh/api/v1-webhook-list-webhook-event openapi/v1-zh.yaml GET /api/v1/webhook-event 查询通过接口指定 callback_url 创建的 webhook v1版本事件 查询通过接口指定 callback\_url 创建的 webhook v1版本事件 # Webhook事件列表 V2 Source: https://docs.subotiz.com/zh/api/v2-webhook-list-event openapi/v1-zh.yaml GET /api/v2/webhook/events 查询通过端点配置创建的 webhook 事件 查询通过端点配置创建的 webhook 事件 # 业务对象 Source: https://docs.subotiz.com/zh/api/webhook-object Webhook 业务对象字段说明 | 属性名 | 类型 | 描述 | | ------------- | ------ | --------------------------------------------------------------------- | | id | string | Webhook事件的唯一ID | | business\_id | string | 事件关联的业务实体ID | | event\_type | string | 事件类型 | | event\_status | string | 事件送达状态
pending: 事件送达处理中
success: 事件成功送达
failed: 事件送达失败 | | url | string | Webhook回调URL | | content | string | Webhook事件内容,JSON格式字符串 | # 设置 Source: https://docs.subotiz.com/zh/faq/settings 如需自定义结账页面,登录 Subotiz 后台,进入 **设置 > 结账页配置 > 结账页**。 配置页面分为两个标签: * **组件配置页** —— 用于自定义页头、订单摘要、订单详情、支付表单和邮件字段等结账模块 * **UI 配置页** —— 用于调整颜色、字体、圆角和内边距 右侧实时预览面板可切换桌面端和移动端视图查看效果。保存按钮仅在检测到修改时才可点击,点击后修改立即生效。 可以。结账页面的邮件字段提供三种配置选项,可从下拉菜单中选择: * **必填(默认)** —— 客户必须填写邮箱才能完成结账 * **可选** —— 客户可自行决定是否填写邮箱 * **隐藏** —— 结账页面上的整个联系人部分将被隐藏,不要求客户提供邮箱 当邮件字段设置为必填或可选时,会出现联络表单标题开关,并展示营销邮件订阅复选框供客户选择。将邮件字段设置为隐藏后,包含营销订阅复选框在内的整个联系人部分都将被移除。 可以。Subotiz 提供默认的预览订单商品,但可以自定义: 1. 点击预览区域底部的**修改预览订单商品**,打开配置弹窗。 2. 通过定价名称或定价 ID 搜索目标商品,选择后点击**确认**关闭弹窗,预览界面自动更新。 自定义的预览商品会自动保存以便后续使用。如果已保存的商品或定价不可用,系统会自动恢复为默认预览商品。注意预览仅用于展示——返回按钮、立即订阅按钮等交互元素在预览模式下不具备实际功能。 客户门户是一个自助管理界面,客户可以在其中查看和管理订阅、支付方式、发票和账单记录。Subotiz 会自动生成安全的门户登录链接。商家可以在 **设置 > 客户端配置 > 客户门户** 的客户门户链接区域复制该链接,并将其放置在网站导航、应用或账单通知邮件中供客户使用。客户通过该链接使用 Magic Link(邮件无密码登录)访问门户——输入邮箱后系统发送登录邮件,点击邮件中的按钮即可直接登录,无需密码,登录链接有效期为 30 分钟。 订阅详情页会展示: * 订阅状态 * 下次账单日期与金额 * 绑定支付方式 * 折扣信息(如适用) * 固定期限信息(如适用) 门户中展示的模块和客户可执行的操作,取决于商家在后台的设置。 可以,但前提是商家在门户设置中开启了相应操作权限。在 Subotiz 后台进入 **设置 > 客户端配置 > 客户门户**。 在订阅模块的订阅操作控制部分,可以独立开启或关闭以下操作: * **暂停或恢复订阅** * **取消订阅** —— 含取消时间和退款规则配置 * **修改订阅** —— 升级、降级或切换计划,含生效时间和分摊规则配置 对于固定期限订阅,可额外配置两项专属操作: * **转为持续订阅** —— 允许客户在满足条件时将固定期限订阅转换为持续订阅 * **取消固定期限订阅** —— 允许客户对固定期限订阅执行取消操作 如果商家未开启某项操作,客户在门户中不会看到对应入口。 可以。在门户修改订阅规则中,有一个可选定价方案范围的设置,可以明确指定客户被允许切换的目标定价方案。支持选择多个方案。只有选中的方案才会显示在客户的修改订阅选项中,未选中的方案不会展示。这样可以控制客户可用的升降级路径,而不必暴露所有方案。如果修改订阅操作本身未启用,此设置无效。 当门户设置中启用了历史账单模块后,客户可以在历史账单部分执行以下操作: * 查看所有历史账单记录 * 查看支付金额和支付状态 * 生成并下载发票文件 * 直接从账单记录中对失败的支付发起重试 这个部分让客户对自己的扣费历史有完整的了解,并能在无需联系商家的情况下处理支付失败问题。如果门户设置中未启用历史账单模块,该部分不会向客户展示。 会。客户在客户门户的客户信息部分更新信息后(如姓名、邮箱、账单地址或营销邮件订阅偏好),修改会同步更新至 Subotiz 后台对应的客户记录。客户信息部分展示的字段由商家在门户设置的客户信息模块中配置。客户可以直接查看和更新这些字段,商家将在后台客户资料中看到更新后的信息。 会。客户门户使用 Magic Link(邮件无密码登录)。当客户请求登录时,系统会发送一封包含一键登录按钮和备用链接的邮件。登录链接有效期为30分钟。如果链接在客户点击前过期,客户需要返回门户登录页面,再次输入邮箱申请新的登录邮件。无需重置密码——只需重新申请一个新的 Magic Link 即可。 不是。平台服务费取决于使用的支付渠道。通过 Subotiz Payments 完成的交易不收取平台服务费。通过 PayPal、Airwallex 等第三方支付供应商处理的交易,当前按 1% 收取 SaaS 平台服务费,具体费率以后台显示为准。所有交易仍需支付支付服务商(PSP)收取的标准手续费,不受渠道影响。佣金统一按 USD 计算,其他币种按交易时实时汇率换算。 平台服务费不会在每笔交易后立即扣除,而是采用**累计计费模式**:佣金持续累加,当累计金额达到预设起扣条件后才发起扣费。 根据支付渠道不同,有两种计费方式: * **Auto-Billing(后扣费)** —— 佣金先累计,满足起扣条件后生成账单并统一扣费。 * **Partner Fee(实时扣费)** —— 适用于特定渠道(如 PayPal),在交易完成时实时扣除佣金,不参与累计与起扣条件。 同一时间只能存在一笔未支付账单,当前账单支付后才会生成下一笔——但未支付期间产生的交易仍会继续计入佣金累计。 会,退款会直接减少累计佣金,且余额可以变成负数。规则如下: * **佣金扣减** —— 退款后,对应佣金从累计金额中扣减。支持部分退款,按退款比例计算调整。最后一笔退款会自动进行尾差调整,确保总佣金准确。 * **负值允许** —— 当退款金额超过原交易金额时,累计佣金可能为负数。负值累计佣金是允许的,会自动计入后续计费结算。 这确保了佣金收费准确反映实际净收入。 会。拒付在佣金计算中按退款处理。发生拒付时,对应交易的佣金会被冲回并从累计佣金余额中扣减。这意味着拒付对累计佣金的影响与退款相同——会减少累计总额,扣减金额足够大时累计佣金可能变为负数。负值累计佣金是允许的,会自动计入后续计费结算。 佣金扣款支持两种支付方式: * **信用卡** —— 支持 Visa、Mastercard 等主流国际卡,填写卡号、持卡人姓名、有效期和 CVV 完成绑定,绑定成功后显示卡品牌和卡号后四位。 * **PayPal** —— 通过 PayPal 授权登录流程完成绑定,绑定后用于自动佣金和账单扣款。 可同时绑定多种支付方式,扣费触发时系统自动选择可用方式,一种方式不可用时自动切换其他方式。必须始终保持至少一种有效支付方式——最后一种方式无法解绑。 可以: 1. 进入 **设置 > 套餐和账单 > 计费详情**,在支付方式区域找到需要解绑的方式。 2. 点击**解绑**。 3. 在确认弹窗中点击**确认**完成操作。 **重要限制:** 当仅剩一种已绑定支付方式时,无法执行解绑操作,解绑按钮不可用。如需解绑唯一的支付方式,需先绑定新的支付账户,再解绑旧的。建议在移除任何方式前先绑定替代方式,并避免在账单生成或扣费节点前进行账户变更。 如需查看账单的交易佣金明细,进入 **设置 > 套餐和账单 > 我的账单**。找到目标账单,点击**更多(...)**,选择**交易佣金明细**。 页面显示该账单内所有计费交易记录,字段包括: * 交易时间 * 交易单 ID * 外部订单 ID * 退款单 ID * 订单金额及币种 * 订单类型 * 支付供应商 * 支付方式 * 佣金比例 * 实际扣除佣金金额(USD) 支持按交易单 ID 或外部订单 ID 搜索。如需导出,点击右上角**导出**,选择导出全部或筛选结果,下载 CSV 文件。 可以,但仅限已支付的账单。只有账单状态为扣款成功时,才能下载对应账单文件。操作方式:进入 设置 > 套餐和账单 > 我的账单,找到状态为扣款成功的账单,点击更多(...),选择下载账单,文件会自动下载至本地。状态为扣款中或扣款失败的账单不会显示下载账单选项。建议每次扣款成功后及时下载账单用于财务留存。 佣金扣款失败后,系统通过站内信通知商家(含扣款金额和账单编号)并自动重试扣款。如扣款持续失败,以下规则基于首次失败时间执行。系统每次扣款后(成功或失败)均发送站内信通知。首次失败满7天后,店铺进入受限状态。受限期间:后台仅套餐和账单板块可正常操作,其他板块仅可浏览。重要:店铺C端交易在受限期间仍可正常进行,不受后台限制影响。如存在多笔未支付账单,每笔独立计时,任意一笔超过7天均可触发店铺受限。冻结执行前1小时会发送最后一封警告邮件。完成账单支付后,账户自动解除限制,系统自动生成下一笔账单。 佣金扣款失败共有三种邮件通知场景: 1. **扣款成功邮件** —— 扣款成功后立即发送,仅发送 1 次。 2. **扣款失败提醒邮件** —— 首次扣款失败后立即发送,之后每 24 小时发送一次。停止条件:扣款成功或进入第 7 天冻结流程。 3. **冻结前最后提醒邮件** —— 在首次失败满 7 天、冻结操作执行前发送,仅发送 1 次(最后一封提醒)。此后不再发送任何提醒邮件。 计时基准从首次扣款失败时间开始。若扣款在任何时间点成功(无论是自动重试还是手动支付),所有待发邮件立即停止。 常见扣款失败原因及处理方式: * **银行卡过期** —— 解绑过期卡并绑定有效卡。 * **账户余额不足** —— 确保绑定账户有足够余额覆盖扣款金额。 * **授权失效** —— 在设置中重新完成支付方式授权。 * **支付方式被禁用** —— 联系支付服务商或更换其他已绑定的支付方式。 查看具体失败原因:进入 **设置 > 套餐和账单 > 我的账单**,找到对应账单,点击**更多(...)> 扣款记录**,查看失败提示信息。原因解决后,进入 **设置 > 套餐和账单 > 计费详情**,根据需要更新支付方式,点击**立即支付**重试,或等待系统自动重试。 可以。因未支付佣金账单导致店铺受限时,C端交易仍可正常进行,不受后台限制影响。受限仅影响商家后台——除套餐和账单外,其他后台模块均变为仅可浏览,无法操作。客户仍可正常完成购买、订阅和支付。如需恢复完整后台访问权限,进入 设置 > 套餐和账单 > 计费详情,点击立即支付完成欠款支付。支付成功后账户自动恢复正常。 是的。存在多笔未支付佣金账单时,每笔账单从各自首次扣款失败时间独立计时。任意一笔账单达到7天未支付状态,均可触发店铺受限——即使其他账单尚未达到该阈值。因此,有多笔逾期账单的商家应优先处理最早未支付的那笔,以降低账户受限风险。如需查看所有未支付账单及其状态,进入 设置 > 套餐和账单 > 我的账单。 我的账单列表中的 GMV 字段显示的是账单周期内按 USD 计算的累计总交易额。如果 GMV 与预期不符,请检查以下几点: * **货币换算** —— 非 USD 交易按付款时实时汇率换算为 USD,不同交易日的汇率波动可能导致换算结果与预期不一致。 * **退款** —— 退款交易会同步减少 GMV 和累计佣金,支付交易金额字段显示实际支付金额,退款交易金额字段显示账单周期内的累计退款金额。 如需逐笔核对,点击账单的**更多(...)> 交易佣金明细**,查看每笔交易的原始币种、订单金额和换算后的 USD 交易金额。 不会。Subotiz 采用单账单规则:同一时间只能存在一笔未支付的佣金账单。当前未支付账单完成支付之前,系统不会生成新的账单。但未支付期间产生的交易仍会持续计入佣金累计。完成当前账单支付后,系统自动根据累计结果生成下一笔账单。这意味着延迟支付不会导致任何佣金漏计——只是延后下一笔账单的生成时间。 # 基础操作 Source: https://docs.subotiz.com/zh/faq/workspace-basics Subotiz 是一款专为订阅业务打造的智能平台,适用于从 AI SaaS 到 Web3 的各类应用。平台支持 Web2 与 Web3 灵活收款方式、优化转化的智能结账体验,以及免代码的方案管理、账单管理与用户访问控制。 适合多种业务类型: * 使用分级或用量计费的 SaaS 产品 * AI 与效率工具 * 提供会员制或内容付费的内容平台 * 为多商户代收代付的综合平台 * 支持加密货币与法币支付的 Web3 服务 * 需要嵌入订阅计费功能的技术合作伙伴 会。Subotiz 集成了 Stripe Tax,根据客户所在地与交易信息自动计算并收取 Sales Tax、VAT 或 GST。系统会持续更新税率规则,商户无需手动管理税率变更。Subotiz 还支持生成合规报表,无需额外手动设置。税务计算覆盖大多数全球市场所需的主要税种,并在结账时自动生效。 支持。Subotiz 提供完整的白标计费基础设施,支持合作伙伴以自有品牌推出订阅计费服务,包括: * 自定义域名、Logo、结账页面、通知邮件与客户门户; * 子账号(商户)后台,支持独立计费逻辑; * 结构化交易记录与完整账单历史; * 法币与加密货币收款支持。 这让平台方、金融科技公司、代理商、应用市场与 SaaS 经销商可以快速搭建专属品牌的计费系统,无需从零开发。 Subotiz 后台左侧导航包含以下主要模块: * **数据** —— 交易与订阅表现分析,包含交易概览、订阅概览和报表。 * **商品** —— 商品目录与计费结构,包含商品管理、商品定价和价格表。 * **交易** —— 计费执行与支付处理,包含交易订单、退款单和争议订单。 * **订阅** —— 订阅生命周期管理。 * **折扣** —— 折扣活动创建与管理。 * **资金** —— 余额(实时可用资金)和提现(结算转账记录)。 * **客户** —— 统一客户档案与账单历史。 * **电子邮件** —— 交易邮件、营销邮件和发件域名设置。 * **发票** —— 所有计费事件记录。 * **设置** —— 系统配置,包含支付供应商、员工管理、客户端配置和收入恢复规则。 * **开发者** —— 接入设置和 Webhooks。 集成凭证位于开发者模块。在 Subotiz 后台进入 开发者 > 接入设置。该页面显示核心集成凭证,包括商户 ID、访问号和访问密钥。还可以在此页面配置支付成功与取消后的跳转地址。如需配置 Webhook 接收实时事件通知,进入 开发者 > Webhooks。 可以。Subotiz 支持在单一账号下管理多个店铺,每个账号最多可创建100个店铺,每个店铺独立运营,拥有各自的商品、支付配置和数据,互不影响。如需进入店铺管理,点击后台左下角的店铺名称或 Logo 打开店铺面板,再点击管理店铺。在店铺管理页面,可查看所有店铺、按名称或店铺 ID 搜索、按状态筛选、切换店铺,以及进行所有权转让。每个店铺可在新标签页中独立管理。 Subotiz 中的店铺有三种状态: * **生效中** —— 店铺完全可用,所有功能正常访问。 * **转让中** —— 正在进行所有权转让,转让期间店铺仍可正常运营,所有功能不受影响。 * **已冻结** —— 仅可查看或处理账单相关信息,其他功能均为只读状态,无法执行新操作。 店铺被冻结时,商家应解决相关问题以恢复完整访问权限。 只有当前店铺所有者才能发起转让。在店铺面板中点击管理店铺,找到目标店铺,点击操作菜单选择转让所有权。输入接收人邮箱(不可与当前账号邮箱相同)和可选备注。完成身份验证——点击发送验证码,系统向当前账号邮箱发送6位验证码,验证码30分钟内有效。确认信息后提交。提交后店铺状态变为转让中,接收人需在72小时内接受。接受后,原所有者失去所有访问权限,店铺出现在接收人账号中。转让完成后有24小时冷却期,期间不可再次发起转让。在接收人接受前,可随时取消转让。 店铺所有权转让完成后,原所有者会被自动从该店铺中移除,不再拥有任何访问权限,店铺也不再出现在原所有者的店铺列表中。接收人成为新的店铺所有者,店铺出现在其账号中。店铺状态从转让中恢复为生效中。转让完成后进入24小时冷却期,期间不可再次发起转让。如果原所有者需要重新获得访问权限,需由新所有者发起新的转让操作。 创建新店铺时,有两个必填字段:主体名称(显示于结账页面及客户门户)和国家/地区。两个可选字段:店铺 Logo(用于品牌标识)和详细地址。提交后系统自动创建店铺,默认状态为生效中,创建者自动成为该店铺的所有者。每个账号最多可创建100个店铺。 如果接收人在72小时内未接受转让,转让请求会自动过期失效。店铺状态恢复为生效中,原所有者保留完整访问权限,如仍需转让需重新发起。转让在接收人接受前随时可以取消。如需取消,在店铺管理页面找到状态为转让中的店铺,点击操作菜单选择撤销转让,确认后转让立即终止,接收人失去接收资格,如需再次转让需重新发起流程。 可以。后台语言支持在英文和简体中文之间切换。如需更改,点击后台左下角的店铺名称或 Logo 打开店铺面板,点击语言,选择所需语言即可。语言设置仅影响后台界面显示语言,不会影响店铺前台内容、结账页面或任何面向客户的通信内容。 符合。Subotiz 满足 PCI DSS v4 标准,这是最高级别的支付安全认证,确保交易处理安全。商家无需自行处理复杂的合规步骤,Subotiz 负责认证要求。结合自动执行的 KYC 和 AML 检测(验证客户身份并标记可疑活动),Subotiz 为商家提供安全合规的支付环境,无需商家具备专业合规背景。 访问 [www.subotiz.com](http://www.subotiz.com),点击 Get started。输入用户名、邮箱和密码(8-20位,至少包含大写字母、小写字母、数字或符号中的三类,不允许空格)。点击下一步,填写企业信息:主体名称(必填)、国家/地区、省份/州和城市(必填)、企业地址,并勾选同意《服务条款》和《隐私政策》。点击注册提交。提交后系统发送验证邮件,点击邮件中的 Verify Email 按钮激活账号。验证链接有效期为24小时。 如果注册后未收到验证邮件,请先确认注册时填写的邮箱地址是否正确。然后检查垃圾邮件文件夹,验证邮件有时会被过滤至此。若仍未找到,返回验证页面点击重新发送邮件申请新的验证链接。请注意,如果多次申请验证邮件,只有最后一封邮件中的链接有效,旧链接会自动失效。验证链接有效期为24小时,如已过期请从同一页面重新申请。 邮箱验证成功后,Subotiz 会引导您完成一个可选的快速设置流程,用于收集基础业务信息并协助初始化工作空间。包含三个步骤:选择主要商品类型(如 SaaS、软件、在线视频内容、信息服务或电子书)、选择企业规模(按月收入区间)、选择计划接入的支付机构。这些信息仅用于内部推荐,不会对外共享。快速设置为可选流程,可以跳过。完成或跳过后,首次进入后台时系统可能会显示功能导览,帮助了解核心模块。 如需重置密码,访问 [www.subotiz.com](http://www.subotiz.com) 点击登录,在登录页面点击忘记密码。输入注册时使用的邮箱地址,点击发送重置链接。查收密码重置邮件,点击邮件中的重置链接继续操作。重置链接有效期为24小时。在重置页面输入新密码并再次确认。密码需8-20位,至少包含大写字母、小写字母、数字或符号中的三类,不允许空格。点击确认保存新密码。如果多次申请重置邮件,只有最后一封有效。 Subotiz 密码需满足以下要求:长度必须在8至20位之间,密码必须包含以下四类中的至少三类:大写字母、小写字母、数字和符号,不允许使用空格。这些规则适用于初始账号创建和后续的密码重置。重置时若两次输入不一致,系统会显示错误提示,重置不会继续执行。 可以。Subotiz 支持多成员管理与基于角色的权限控制。如需新增团队成员,进入 Subotiz 后台 > 设置 > 员工管理。可以新增多个成员,并为每人分配对应角色,控制其可访问的后台功能——例如管理订阅、查看报表或处理交易。不同角色拥有不同的访问权限,商家可以为每位成员分配其职责范围内的权限。 如需移除或停用团队成员,进入 Subotiz 后台 > 设置 > 员工管理。找到需要操作的成员,停用其账户或调整角色权限。停用后该成员将无法登录后台。如果只需要减少成员的访问权限而不是完全移除,也可以将其角色调整为权限更受限的角色。 会。Subotiz 中每个商店 ID 建议只对应一个 App 或产品。如果同一个商店在不同 App 中使用,所有交易会合并在同一个数据源下,系统无法按 App 区分交易,导致难以追踪各产品的表现或单独对账。建议为不同 App 建立独立的商店 ID,或在同一商店下为不同 App 生成各自的支付链接,以保持数据清晰。 使用 Subotiz 不需要编写代码即可开始。提供两种整合方式: * **Hosted Checkout(无代码)** —— Subotiz 生成可直接分享或嵌入网站的支付链接,无需任何开发工作,适合希望快速简便上线的商家。 * **SDK / API 整合(开发者)** —— 商家可使用 Subotiz API 和 SDK 在自己的 App 或平台中构建完全自定义的结账体验,需要开发资源,但提供更高的灵活性和对结账流程的控制权。 两种方式均支持 Subotiz 的全部功能,包括订阅、试用期和退款。 Subotiz 支持国际主流货币进行交易,包括美元(USD)、欧元(EUR)、港币(HKD)、加拿大元(CAD)等常用币种。商家可直接在 Subotiz 后台配置首选交易币种。结算币种在账户注册时选择——一旦创建了交易,结算币种将无法更改。完整的支持币种列表请参考后台货币设置页面。 Webhook 是一种系统通知机制,当 Subotiz 中发生关键事件(如付款成功、订阅更新或退款)时,系统会自动将实时事件数据发送到您配置的 URL,让您的系统与 Subotiz 保持同步,无需手动查询。在 Subotiz 中设置 Webhook,进入 开发者 > Webhooks,配置回调地址(Webhook 端点 URL)和签名密钥。配置完成后,Subotiz 会在支持的事件发生时自动向您的 URL 发送通知。如需完整的支持事件列表和技术细节,请参阅 Subotiz 开发者文档。 可以。Subotiz 提供 API,支持商家与外部系统整合,包括自有会员或用户账户系统、CRM 平台和发票服务。通过 Subotiz API,您可以自动化数据同步、根据付款或订阅事件触发操作,并将 Subotiz 连接至现有业务流程。API 凭证(商户 ID、访问号和访问密钥)可在后台 开发者 > 接入设置 中获取。如需 API 文档和整合指南,请参阅 Subotiz 开发者文档。 # 嵌入式表单 Source: https://docs.subotiz.com/zh/integration/embedded-form Subotiz 支持通过嵌入式表单(embedded 模式)完成结账流程。提供低代码支付集成方案,可便捷创建可定制的支付表单,助您快速完成支付流程。 ## 场景演示 本页介绍如何使用嵌入式结账模式,即通过 Subotiz 的商品、定价和支付能力,快速构建一体化结账体验。 如果您只需接入支付功能,请前往 [支付模式](/zh/integration/embedded-form-payment)。 #### 嵌入完整 Checkout 页面 #### 嵌入部分组件元素 ## 支付流程 1. 当客户准备完成购买时,从您的客户端(client)向您的服务端(server)发起结账请求。您的服务端应使用 Subotiz API 创建一个 Checkout Session,并在创建 Session 时以参数形式传入 order\_id(接入方订单 ID,业务唯一),以便后续关联交易单。 2. Checkout Session 会提供一个 Session ID,您的客户端可使用 SDK 唤起 Subotiz 的支付表单并展示给客户。 3. 客户会在 Subotiz 表单中输入支付信息并完成交易。 4. 交易完成后,Subotiz 会以 webhook 方式通知您的服务端,通知包含支付成功事件,该事件中包含创建 session 时传入的 order\_id,借此可关联接入方订单和 Subotiz 的交易单。 ```mermaid theme={null} sequenceDiagram participant Customer as 顾客 participant Client as Merchant Client participant Server as Merchant Server participant SubotizAPI as Subotiz API Customer->>Client: 1. 发起订单 Client->>Server: 2. 获取 session ID Server->>SubotizAPI: 3. 创建 Checkout Session SubotizAPI-->>Server: 4. 返回session 信息 Server-->>Client: 5. 返回 session id Client->>Client: 6. 使用 SDK 唤起表单 Client-->>Customer: 7. 展示支付表单 Customer->>Client: 8. 填写支付信息并确认 Client->>Client: 9. 处理支付 Client-->>Customer: 10. 返回支付结果 SubotizAPI->>Server: webhook 通知支付结果 ``` ## 接入步骤 在 Subotiz 管理平台中创建商品和商品定价,将商品信息和价格信息保存在服务端中。创建 Checkout Session 时需依赖商品定价的 price\_id 来动态获取商品信息。 您的程序需要提供顾客支付成功的展示页面,并确保能够在公网中访问。顾客付款完成后,Subotiz 会将客户重定向到该页面。 创建一个事件接收地址,以接收您账户上发生的事件。当有事件发生时,Subotiz 会发送 HTTPS POST 请求将 [Webhook](/zh/webhook/introduction-2) 事件通知到该端点,请求体内容是 JSON 格式的事件对象。您可以通过关注事件来同步变更您系统的业务数据。 您的客户端可以使用 [Subotiz SDK](/zh/resources/subotiz-sdk) 集成 Subotiz Checkout。 #### 1. 加载 Subotiz.js ```html theme={null} ``` #### 2. 提供容器节点 ```html theme={null}
``` #### 3. 创建 Checkout Session 使用 [Subotiz API ](/zh/api/introduction-1)创建[Checkout Session ](/zh/api/v1-checkout-session-create-checkout-session) ,并将响应结果返回前端。 **embedded 模式创建 Checkout Session 示例:** ```bash theme={null} curl --location 'https://api.subotiz.com/api/v1/session' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer {your_api_key}' \ --header 'Request-Id: dd7fb126-be31-4144-a1af-e4bf4203eb92' \ --data-raw '{ "access_no": "77d52a21dc032b4", "sub_merchant_id": "2816433", "order_id": "123e4567-e89b-12-a456-426622201a", "payer_id": "customer_id_001", "customer_id": "", "email": "zhangsan@subotiz.com", "line_items": [ # 商品信息,checkout 模式必传 { "price_id": "543321366326164797", "quantity": "1" } ], "return_url": "https://www.subotiz.com", "cancel_url": "https://www.subotiz.com", "mode": "checkout", # 有商品选择 checkout 模式 "integration_method": "embedded", # 选择嵌入式集成 "redirect_on_completion": "if_required" # 根据业务场景选择是否跳转,这里示例仅在必要的时候进行重定向 }' ``` #### 关键参数 * `order_id`:为接入方订单 ID,用于后续关联业务数据 * `integration_method`:设置为 `embedded`,表示使用嵌入式表单模式接入 * `return_url`: 客户在 Subotiz Checkout 页面支付成功之后跳转的页面 * `mode`:有商品数据时选择 `checkout` 模式 #### 4. 初始化结账页面 ```javascript theme={null} // After importing via the script tag, Subotiz is automatically attached to the window object const { Subotiz } = window; // Create an SDK instance const subotiz = Subotiz(); // Initialize checkout const checkout = await subotiz.initEmbeddedCheckout({ fetchSessionUrl: async() => { // Fetch the sessionUrl from your server const response = await fetch('/api/session'); const data = await response.json(); return data.sessionUrl; }, environment: 'SANDBOX', // 'SANDBOX' | 'PRODUCTION' // The callback function when the payment completed only triggers when `redirect_on_completion` is set to `if_required` during Checkout session creation onComplete: () => { console.log('Payment completed!'); } }); // Mount to the page checkout.mount('#checkout-container'); ```
# 嵌入式表单 Source: https://docs.subotiz.com/zh/integration/embedded-form-payment Subotiz 支持通过嵌入式表单(embedded 模式)完成结账流程。提供低代码支付集成方案,可便捷创建可定制的支付表单,助您快速完成支付流程。 ## 场景演示 本页介绍如何使用支付模式,即仅调用 Subotiz 的支付引擎,自行构建前端界面与业务逻辑。 如果您需要完整的商品管理、定价与支付能力,请前往 [嵌入式结账模式](/zh/integration/embedded-form)。 #### 嵌入完整 Checkout 页面 #### 嵌入部分组件元素 ## 支付流程 1. 当客户准备完成购买时,从您的客户端(client)向您的服务端(server)发起结账请求。您的服务端应使用 Subotiz API 创建一个 Checkout Session,并在创建 Session 时以参数形式传入 order\_id(接入方订单 ID,业务唯一),以便后续关联交易单。 2. Checkout Session 会提供一个 Session ID,您的客户端可使用 SDK 唤起 Subotiz 的支付表单并展示给客户。 3. 客户会在 Subotiz 表单中输入支付信息并完成交易。 4. 交易完成后,Subotiz 会以 webhook 方式通知您的服务端,通知包含支付成功事件,该事件中包含创建 session 时传入的 order\_id,借此可关联接入方订单和 Subotiz 的交易单。 ```mermaid theme={null} sequenceDiagram participant Customer as 顾客 participant Client as Merchant Client participant Server as Merchant Server participant SubotizAPI as Subotiz API Customer->>Client: 1. 发起订单 Client->>Server: 2. 获取 session ID Server->>SubotizAPI: 3. 创建 Checkout Session SubotizAPI-->>Server: 4. 返回session 信息 Server-->>Client: 5. 返回 session id Client->>Client: 6. 使用 SDK 唤起表单 Client-->>Customer: 7. 展示支付表单 Customer->>Client: 8. 填写支付信息并确认 Client->>Client: 9. 处理支付 Client-->>Customer: 10. 返回支付结果 SubotizAPI->>Server: webhook 通知支付结果 ``` ## 接入步骤 创建一个事件接收地址,以接收您账户上发生的事件。当有事件发生时,Subotiz 会发送 HTTPS POST 请求将 [Webhook](/zh/webhook/introduction-2) 事件通知到该端点,请求体内容是 JSON 格式的事件对象。您可以通过关注事件来同步变更您系统的业务数据。 您的客户端可以使用 [Subotiz SDK](/zh/resources/subotiz-sdk) 集成 Subotiz Checkout。 #### 1. 加载 Subotiz.js ```html theme={null} ``` #### 2. 提供容器节点 ```html theme={null}
``` #### 3. 创建 Checkout Session 使用 [Subotiz API ](/zh/api/introduction-1)创建[Checkout Session ](/zh/api/v1-checkout-session-create-checkout-session) ,并将响应结果返回前端。 **embedded 模式创建 Checkout Session 示例:** ```bash theme={null} curl --location 'https://api.subotiz.com/api/v1/session' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer {your_api_key}' \ --header 'Request-Id: dd7fb126-be31-4144-a1af-e4bf4203eb92' \ --data-raw '{ "access_no": "77d52a21dc032b4", "sub_merchant_id": "2816433", "order_id": "123e4567-e89b-12-a456-426622201a", "payer_id": "customer_id_001", "customer_id": "", "email": "zhangsan@subotiz.com", "return_url": "https://www.subotiz.com", "cancel_url": "https://www.subotiz.com", "mode": "payment", # 无商品选择 payment 模式 "total_amount": "10", # 传入需要收款的金额,payment 模式必传 "integration_method": "embedded", # 选择嵌入式集成 "redirect_on_completion": "if_required" # 根据业务场景选择是否跳转,这里示例仅在必要的时候进行自动跳转 }' ``` #### 关键参数 * `order_id`:为接入方订单 ID,用于后续关联业务数据 * `integration_method`:设置为 `embedded`,表示使用嵌入式模式接入 * `return_url`: 客户在 Subotiz Checkout 页面支付成功之后跳转的页面 * `mode`:选择 `payment` 模式 * `total_amount`:本次结账的金额 #### 4. 初始化结账页面 ```javascript theme={null} // 通过script标签引⼊后,Subotiz会⾃动挂载到window对象 const { Subotiz } = window; // 创建SDK实例 const subotiz = Subotiz(); // 初始化结账 const checkout = await subotiz.initEmbeddedCheckout({ fetchSessionUrl: async() => { // 从服务器获取sessionId const response = await fetch('/api/session'); const data = await response.json(); return data.sessionUrl; }, environment: 'SANDBOX', // 'SANDBOX' | 'PRODUCTION' // 支付完成时的回调函数仅在创建Checkout Session时将`redirect_on_completion` 设置为 `if_required` 时触发。 onComplete: () => { console.log('⽀付完成!'); } }); // 挂载到⻚⾯ checkout.mount('#checkout-container'); ```
## 续订收费 Subotiz 支持续订付款功能。用户完成首次支付后,系统将生成支付凭证,后续该用户产生的订阅费用可使用此支付凭证进行扣费,无需用户重新填写支付信息。 #### 续订流程 1. 用户完成首次支付后,保存支付成功事件([trades.succeeded](/zh/webhook/trade-1))中的 `payment_token` 数据,用于发起续订扣费。 2. 使用 Subotiz API 中的[创建交易单(Trade)](/zh/api/v1-trade-create-trade)接口发起扣费。 3. 主动查询交易单或等待异步通知以获取支付结果,并将支付结果通知顾客。 ```mermaid theme={null} sequenceDiagram participant Customer as 顾客 participant AccessSystem as 接入方系统 participant Subotiz as Subotiz Customer->>AccessSystem: 1. 完成首次支付 Subotiz->>AccessSystem: 2. webhook 通知支付结果 AccessSystem->>AccessSystem: 3. 保存支付结果 Customer->>AccessSystem: 4. 续订支付 AccessSystem->>Subotiz: 5. 创建交易单发起支付 Subotiz->>AccessSystem: 6. 返回提交支付结果 AccessSystem->>Subotiz: 7. 查询交易单获取支付结果 Subotiz->>AccessSystem: 8. 返回支付结果 AccessSystem->>Customer: 9. 通知支付结果 Subotiz->>AccessSystem: webhook 通知支付结果 ``` # 托管式页面 Source: https://docs.subotiz.com/zh/integration/hosted Subotiz 支持以托管页面(hosted 模式)的方式完成结账流程。当客户需要结账时,您可以使用 Subotiz API 创建一个 Checkout Session ,然后重定向到 Subotiz 支付页面来完成整个支付过程。 ## Checkout 流程描述 1. 当客户准备完成购买时,从您的客户端(client)向您的服务端(server)发起结账请求,您的服务端应该使用 Subotiz API 创建一个 Checkout Session。 2. Checkout Session 会提供一个结账页的 URL,您可以将客户重定向到 Subotiz 结账页。 3. 客户会在 Subotiz 结账页输入支付信息并完成交易。 4. 交易完成之后 Subotiz 会以 webhook 的方式通知您的服务端。 ```mermaid theme={null} sequenceDiagram participant Client as Merchant Client participant Server as Merchant Server participant SubotizAPI as Subotiz API participant SubotizCheckout as Subotiz Checkout Client->>Server: 1. 发起订单 Server->>SubotizAPI: 2. 创建 Checkout Session SubotizAPI-->>Server: 3. 返回结账页地址 Server->>SubotizCheckout: 4. 重定向到结账页 note right of SubotizCheckout: 5. 客户完成付款 SubotizCheckout->>Client: 6. 客户重定向到应用程序 SubotizAPI->>Server: webhook 通知支付结果 ``` ## 接入步骤 在 Subotiz 管理平台中创建商品和商品定价,将商品信息和价格信息保存在服务端中。创建 Checkout Session 时需依赖商品定价的 price\_id 来动态获取商品信息。 您的程序需要准备两个页面 URL,分别是顾客支付成功和取消支付时跳转的 URL,并确保能够在公网中访问,以便 Subotiz 能够将客户重定向到这些页面中。(两者允许使用同一页面) 创建一个事件接收地址,以接收您账户上发生的事件。当有事件发生时,Subotiz 会发送 HTTPS POST 请求将 [Webhook](/zh/webhook/introduction-2) 事件通知到该端点,请求体内容是 JSON 格式的事件对象。您可以通过关注事件来同步变更您系统的业务数据。 您的系统客户端中需要提供一个用于发起结账的入口,例如在订单预览页的结账按钮。当客户点击按钮时,在您的服务端应该调用 [Subotiz API ](/zh/api/introduction-1)创建 [Checkout Session ](/zh/api/v1-checkout-session-create-checkout-session),并根据订单信息修改调用参数,创建 Checkout Session 时传入的参数决定客户在结账页看到的内容,例如:商品信息、订单价格等。待接口响应后,将客户重定向到 Subotiz 结账页。 #### Hosted 模式创建 Checkout Session 示例 ```bash theme={null} curl --location 'https://api.subotiz.com/api/v1/session' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer {your_api_key}' \ --header 'Request-Id: 9913dca8-90f8-4e20-98bc-565f0222ffa8' \ --data-raw '{ "access_no": "77d52a21dc032b4", "sub_merchant_id": "2816433", "order_id": "123e4567-zzzaa20daw11a", "payer_id": "customer_id_0012", "line_items": [ { "price_id": "543321366326164797", "quantity": "1" } ], "email": "zhangsan@subotiz.com", "integration_method": "hosted", "cancel_url": "https://www.subotiz.com", "return_url": "https://www.subotiz.com" }' ``` #### 关键参数 * `order_id`:为接入方订单 ID,用于后续关联业务数据 * `integration_method`:设置为 `hosted`,表示使用托管式页面模式接入 * `cancel_url`:客户在 Subotiz Checkout 页面取消支付时跳转的页面 * `return_url`: 客户在 Subotiz Checkout 页面支付成功之后跳转的页面 Subotiz 在客户完成结账之后会重定向回成功页面,完成一次完整的结账流程。并且 Subotiz 会以 Webhook 的形式通知到您的服务端,您可以在服务端处理成功订阅之后的逻辑。 # 概述 Source: https://docs.subotiz.com/zh/integration/overview Subotiz 主要支持两种集成模式:结账模式和付款模式。 ## Checkout 模式 Checkout 是 Subotiz 为订阅制业务设计的端到端交易解决方案。其核心优势在于**整合了产品管理、订阅生命周期管理、多渠道支付处理和全球化运营能力**。此模式适用于需要完整交易闭环的场景(例如:AI 工具、SaaS 平台、Web3 应用)。 ### 核心能力包括 * **产品与订阅管理**:创建产品、配置灵活的定价(免费试用、分级定价、优惠券),并管理订阅周期(月/年)及周期中调整。 * **智能结算体验**:可定制的结算流程(标准/快捷/两步),移动端优化布局,以及内置的全球税务合规性。 * **多支付方式**:支持信用卡、借记卡、PayPal、Apple Pay、Google Pay 等,并通过智能路由提升支付成功率。 * **全球化支持**:支持 18 种以上语言(中文/英文/日文/西班牙文等)自动切换,并支持多币种。 ### 集成方式 * **托管页面**:Subotiz 提供托管结算页面。商户通过 API 创建 Checkout Session,然后将客户重定向到此托管页面完成支付,从而省去前端开发工作。 * **嵌入式表单**:使用我们的 SDK 将结算功能直接嵌入到您自己的网页中。支持通过无代码编辑器进行界面定制(样式、组件、流程),确保品牌一致性。 | 维度 | [托管页面](/zh/integration/hosted) | [嵌入式表单](/zh/integration/embedded-form) | | :---- | :----------------------------- | :------------------------------------- | | 技术难度 | 低(仅 API + Webhook;无需前端开发) | 中(SDK 集成;提供无代码编辑器) | | 定制化程度 | 中(Logo/颜色;固定流程) | 高(完整 UI 样式、组件布局、交互流程) | | 品牌识别度 | 中 | 高(完全嵌入商户页面) | | 开发周期 | 1-3 天(主要关注 API) | 3-7 天(UI 定制 + 测试) | | 适用场景 | 中小企业需要快速上线 | 需要深度定制且具备前端资源的品牌 | ## Payment 模式 Payment 是 Subotiz 的**轻量级解决方案,专注于支付处理**。核心能力涵盖收款、退款、对账和 Token 续订(无需重复收集支付信息,使用 token 直接付款)。不包含产品/订阅管理。此模式适用于拥有现有系统(例如 ERP/CRM)但仅需要支付处理的商户。 ### 核心优势 * **多渠道支持**:与 Checkout 共享支付网络(信用卡、Google/Apple Pay)。 * **无缝嵌入**:完全自定义 UI,无 Subotiz 品牌标识。 ### 集成方式 | 维度 | [嵌入式表单 (Payment 模式)](/zh/integration/embedded-form-payment) | | :---- | :---------------------------------------------------------- | | 技术难度 | 中(SDK 集成 + 续订逻辑) | | 定制化程度 | 高(完全由商户设计 UI;无 Subotiz 品牌标识) | | 核心优势 | Token 续订 + 多种支付提供商 | | 开发周期 | 3-5 天(SDK + 逻辑适配) | | 适用场景 | 拥有现有订阅系统的企业 | ## 对比 | 维度 | Checkout | Payment | | :---- | :----------------------- | :------------------- | | 范围 | 完整周期(产品 + 订阅 + 支付) | 仅支付(包括续订) | | 价值 | 内置结算优化,提升订阅转化率 | 与现有系统集成,专注支付效率与续订稳定性 | | 订阅 | 内置(方案、修改、自动续订) | 无(自行管理) | | 定制化程度 | 无代码结算编辑器:支持定制结算流程和 UI 样式 | 仅限于支付界面 | | 全球化支持 | 多语言/币种/税务合规性 | 多语言/币种/税务合规性 | | 集成方式 | 托管页面 + 嵌入式表单 | 仅嵌入式表单 | ## 场景匹配指南 ### Checkout 模式推荐 * **业务类型**:SaaS、AI 工具、Web3 应用、移动游戏 * **需求**:产品目录/订阅管理或结算优化 * **技术资源**:前端开发能力有限或偏好无代码方案 * **全球化**:多区域客户需要本地支付方式 ### Payment 模式推荐 * **业务类型**:拥有成熟订阅系统的企业 * **需求**:纯粹的支付处理能力 * **技术资源**:具备前端能力进行自定义 UI 设计 * **品牌控制**:不希望有第三方页面重定向 # 介绍 Source: https://docs.subotiz.com/zh/quick-start/overview ## 欢迎来到 Subotiz 开发者中心 Subotiz 开发者中心为全球开发者提供了一站式、全面的支付与订阅集成工具链。通过标准化的 API、丰富的开发资源和灵活的集成模式,开发者可以快速构建和部署支付流程,而无需管理底层支付渠道集成或合规复杂性。无论您是初创公司的技术团队还是大型企业的开发部门,我们精简的技术解决方案都能让您轻松将 Subotiz 强大的支付能力直接嵌入到您的业务系统中。 ### 我们的核心承诺 * 效率:无需从零搭建,少量步骤即可完成第一个支付流程的接入并上线。 * 灵活性:支持多种集成模式,从完全托管到高度定制化。 * 可靠性:基于支撑全球商户高并发交易的基础设施构建,保障服务的高可用与稳定性。 ## Subotiz 功能一览 ### 快速开始 快速完成基础支付集成 测试与生产环境的接入信息 ### 集成指南 集成方式与整体流程总览 托管式 / 嵌入式结账页接入 嵌入式支付表单接入 ### AI 开发者 让 AI 助手直接调用 Subotiz 命令行管理与调试 ### 开发者资源 Web SDK(subotiz.js)用法 测试卡号与沙盒环境 支付错误码对照速查 ### Webhook 事件通知机制与签名校验 全部 Webhook 事件类型 ## 开发者旅程:如何快速上手 本指南支持快速完成 Subotiz 支付功能的基础集成,使您能够使用我们的托管结账页面(托管模式)快速实现支付流程。 ### 前置条件 #### 注册 Subotiz 商户账户 注册 Subotiz 商户账户,立即开始构建您的集成。 注册 #### 创建商品和定价 ### 快速入门步骤 完成上述前置条件后,请继续进行集成。 [快速入门指南](/zh/quick-start/quick-start) ## 安全与合规,我们为您守护 ### PCI DSS 合规性 作为一级(Level 1)服务提供商,我们承担了最复杂的合规工作。通过使用我们的 SDK 或托管页面,您可以显著减少甚至消除自身的合规审计范围。 ### 数据加密 所有数据传输均使用 TLS 1.2 或更高版本进行加密。敏感数据也经过静态加密。 ### 兼容 GDPR/CCPA 我们的工具旨在帮助您轻松满足 GDPR 和 CCPA 等数据隐私法规要求。 ## 获取支持 ### 技术支持 如遇技术问题,请联系我们的工程团队([developer@subotiz.com](mailto:developer@subotiz.com))获取支持。 # 快速入门 Source: https://docs.subotiz.com/zh/quick-start/quick-start 本指南帮助您完成 Subotiz 支付功能的基础集成——通过托管式结账页面([hosted mode](/zh/integration/hosted))快速实现支付流程。Subotiz 提供完整的支付能力,支持订阅管理、交易处理等核心功能,适用于 AI、SaaS 等各类业务场景。 ## 前置条件 1. 已注册 Subotiz 商户账号(注册地址) 2. 完成 Subotiz 支付入网及支付方式配置 3. 完成商品和定价创建 ## 集成步骤 登录 [Subotiz 管理平台](https://admin.subotiz.com/),完成以下两项配置: #### 1. 配置支付回调地址 * `return_url`:客户支付成功之后跳转的 URL,创建 checkout session 时的默认值 * `cancel_url`:客户取消支付之后跳转的 URL,创建 checkout session 时的默认值 优先级规则:创建会话时传入的地址将覆盖此处的默认设置。为确保灵活性,建议在此设置通用默认地址,并在特定场景下通过 API 传入自定义地址。 #### 2. 获取平台接入信息 * `access_no`:接入方唯一识别号 * `merchant_id`:商户唯一标识 * `API Key`:API 鉴权密钥,获取方式参阅 [鉴权](/zh/api/authentication-1)(**严格保密,勿暴露在客户端**) 在 Subotiz 管理平台中创建商品和商品定价,将商品信息和价格信息保存在服务端中。创建 Checkout Session 需要依赖商品定价的 `price_id` 来动态获取商品信息。 通过 API 创建结账会话,获取支付页面 URL,引导用户完成支付。 **请求示例:** ```bash theme={null} curl --location 'https://api.sandbox.subotiz.com/api/v1/session' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer {your_api_key}' \ --header 'Request-Id: 07949371-7868-2282-78af-2a8d5c043760' \ --data-raw '{ "access_no": "{您的access_no}", "sub_merchant_id": "{您的merchant_id}", "order_id": "test_order_001", "email": "customer@example.com", "line_items": [ { "price_id": "{商品定价ID}", "quantity": "1" } ], "return_url": "https://your-app.com/success", "cancel_url": "https://your-app.com/cancel" }' ``` #### 1. 获取支付页面 URL 接口响应成功后,取 `data.session_url`(支付页面 URL)。 #### 2. 访问支付页面 在浏览器中打开该链接,即可看到 Subotiz 托管的支付页面。 #### 3. 使用测试卡号完成支付 使用测试卡号完成支付(Subotiz Payment 渠道): * 支付成功:卡号 `4242424242424242`,CVC 为任意 3 位,有效期需为未来日期 * 支付失败:卡号 `4000000000000002`,CVC 为任意 3 位,有效期需为未来日期 #### 1. 重定向回 return\_url 支付完成后,用户被重定向至 `return_url`(成功场景)。 #### 2. 接收 Webhook 通知 Subotiz 同时发送 Webhook 通知(事件类型 `trades.succeeded`)。 #### 3. 验证 Webhook 签名 1. **提取参数**:从请求头获取 X-Timestamp 时间戳(记为 `timestamp`),并获取原始请求体内容(记为 `body`)。 2. **构造签名原串**:格式为 `${timestamp}.${body}`。 3. **计算签名**:使用 Subotiz 分配的 `API Key` 作为密钥,通过 HMAC-SHA256 算法计算签名值(示例见下)。 4. **比对验证**:将计算得到的签名与请求头中的 X-Signature 值比对,一致则为合法请求。 ```go theme={null} // 计算签名 func CalcSignature(timestamp int64, body []byte, secret string) string { mac := hmac.New(sha256.New, []byte(secret)) mac.Write([]byte(fmt.Sprintf("%d", timestamp))) mac.Write([]byte(".")) mac.Write(body) return hex.EncodeToString(mac.Sum(nil)) } ``` ## 验证结果 1. 登录 Subotiz 管理平台,查看交易记录和订阅记录 2. 验证订单金额、商品信息是否正确 # Subotiz 商家 Source: https://docs.subotiz.com/zh/quick-start/subotiz-merchants 本页汇总 Subotiz 自营商家的环境配置信息,涵盖测试环境与线上环境的核心地址与使用说明,供商家完成支付、订阅等功能的开发集成与上线部署。 ## 线上环境 #### 环境说明 * **适用场景**:仅面向已完成 Subotiz 自营商户资质审核、系统配置,计划正式上线运营或已处于稳定运营阶段的接入方。 * **核心用途**:作为官方生产环境,用于处理真实用户支付交易、订阅订单全生命周期管理、资金结算对账、业务数据实时同步等正式业务操作。 #### 环境地址 * Subotiz 管理平台地址:[https://admin.subotiz.com](https://admin.subotiz.com/) * API 地址:[https://api.subotiz.com](https://api.subotiz.com/) ## 沙箱环境 #### 环境说明 * **适用场景**:面向处于开发集成阶段、尚未完成正式上线审核的接入方,或已上线接入方进行功能迭代测试、版本升级验证及故障排查时使用。 * **核心用途**:用于接入方调试 API 接口兼容性、验证业务流程完整性、测试订阅功能逻辑(如计费规则、状态回调、异常场景处理)等场景。环境不涉及真实资金流转,测试数据与线上环境完全隔离,可安全开展各类功能验证与流程调试操作。 #### 环境地址 * Subotiz 管理平台地址:[https://admin.sandbox.subotiz.com](https://admin.sandbox.subotiz.com) * API 地址:[https://api.sandbox.subotiz.com](https://api.sandbox.subotiz.com) # Subotiz · PayPal 商家 Source: https://docs.subotiz.com/zh/quick-start/subotiz-paypal-merchants 本页汇总 Subotiz · PayPal 商家的环境配置信息,涵盖测试环境与线上环境的核心地址与使用说明,供商家完成支付、订阅等功能的开发集成与上线运营。 启用生产环境收款前,需先在 PayPal 官网注册 PayPal 收款账户,并将该账户授权绑定至 Subotiz · PayPal。 ## 线上环境 #### 环境说明 * **适用场景**:仅面向已完成 Subotiz 商户资质审核、流程配置,且准备正式上线运营或已处于运营阶段的 Subotiz · PayPal 商家。 * **核心用途**:作为生产环境,用于处理真实的用户支付交易、订阅订单管理、资金结算、客户信息同步等正式业务操作。 #### 环境地址 * Subotiz 管理平台地址:[https://admin.paypal.subotiz.com/](https://admin.paypal.subotiz.com/) * API 地址:[https://api.subotiz.com](https://api.subotiz.com/) ## 沙箱环境 #### 环境说明 * **适用场景**:面向处于开发集成阶段、未完成正式上线审核的 Subotiz · PayPal 商家,或需进行功能迭代测试、问题排查的已上线商家。 * **核心用途**:用于开发者调试 API 接口、验证支付流程、测试订阅功能(如试用周期、计费逻辑)、模拟交易状态变更等,不涉及真实资金流转,测试数据与线上环境完全隔离,可安全进行各类功能验证操作。 #### 环境地址 * Subotiz 管理平台地址:[https://admin.sandbox.paypal.subotiz.com](https://admin.sandbox.paypal.subotiz.com) * API 地址:[https://api.sandbox.subotiz.com](https://api.sandbox.subotiz.com) # 支付错误码 Source: https://docs.subotiz.com/zh/resources/payment-error-code | 归类 | 系统返回码定义 | 系统返回码说明EN | 系统返回码说明CN | | :------- | :------ | :------------------------------------------------------------------------------- | :-------------------- | | 成功类 | 100000 | Success | 交易成功 | | | | | | | 金额错误类 | 100100 | Insufficient balance | 余额不足 | | | 100101 | Amount exceeds the maximum limit | 超过最大金额 | | | 100102 | Amount below the minimum limit | 低于最低金额 | | | 100103 | Invalid amount format | 金额格式非法 | | | 100104 | Incorrect original amount | 原始金额不正确 | | | 100105 | Amount mismatch (cumulative) | 金额(累计)不匹配 | | | 100106 | Amount update not supported | 金额不允许更新 | | | 100107 | Invalid currency | 货币错误 | | | 100108 | Currency not supported | 货币不支持 | | | | | | | 账户(卡)错误类 | 100201 | Account information mismatch | 账户信息不匹配 | | | 100202 | Bank account does not exist | 无此账号 | | | 100203 | Lost bank account | 挂失卡 | | | 100204 | Confiscated bank account | 没收卡 | | | 100205 | Stolen bank account | 被窃卡 | | | 100206 | Expired bank account | 过期卡 | | | 100207 | Unsupported bank account | 不支持的卡 | | | 100208 | Fraudulent bank card | 诈骗卡 | | | 100209 | Suspected counterfeit card | 怀疑伪造卡 | | | 100210 | Pick-up card (Contact issuer) | 问题卡,需要联系发卡方 | | | 100211 | Card blacklisted | 黑名单卡 | | | 100212 | Card data error | 卡信息错误 | | | 100213 | Account frozen | 账户已冻结 | | | 100214 | Account closed | 账号(卡)已关闭 | | | 100215 | Account locked | 账户被锁定 | | | 100216 | Account purged | 已清户 | | | 100217 | Bank account declined | 被拒的银行账户 | | | 100218 | Account and name mismatch | 账户和户名不符合 | | | 100219 | Restricted account | 受限制的账户 | | | 100220 | Account unusable | 账户无法使用 | | | 100221 | Account verification failed | 账户校验失败 | | | 100222 | Card decline rate limit exceeded | 卡支付频率超出限制而被拒绝 | | | 100223 | Invalid account type | 账户(卡)类型错误 | | | 100224 | Incorrect cvv | 卡的安全码错误 | | | 100225 | Incorrect card address | 卡地址错误 | | | 100226 | Incorrect card ZIP code | 卡邮编错误 | | | 100227 | Incorrect expiration month | 卡有效期月份错误 | | | 100228 | Incorrect expiration year | 卡有效期年份错误 | | | 100229 | Incorrect expiration date | 卡有效期错误 | | | 100230 | Invalid customer payment account | 客户付款账户无效 | | | | | | | 风控错误类 | 100300 | Suspected fraud | 涉嫌欺诈 | | | 100301 | High-risk transaction | 交易风险过高 | | | 100302 | Security violation | 安全违规 | | | 100303 | Violation of the law | 交易存在违法法律行为 | | | 100304 | Email blacklisted | 邮箱在黑名单中 | | | | | | | 参数校验错误类 | 100400 | Not authorized | 未授权 | | | 100401 | Missing pickup address | 物流地址未填写 | | | 100402 | Invalid pickup address | 物流地址非法 | | | 100403 | Unsupported shipping type | 不支持的物流方式 | | | 100404 | Missing postal code | 邮编缺失 | | | 100405 | Invalid postal code | 邮编非法 | | | 100406 | Invalid phone number | 非法手机号 | | | 100407 | Invalid country code | 国家码非法 | | | 100408 | Invalid province | 省份非法 | | | 100409 | Invalid city | 城市非法 | | | 100410 | Agreement not found | 协议不存在 | | | 100411 | API rate limit exceeded | API接口请求超限 | | | 100412 | API key error | API密钥错误 | | | 100413 | Invalid merchant | 非法商户 | | | 100414 | Invalid parameter | 参数非法 | | | 100415 | Unsupported payment type | 不支持的交易类型 | | | 100416 | Provider not found | 无此渠道 | | | 100417 | Invalid currency | 币种非法 | | | 100418 | Currency not supported | 币种不支持 | | | 100419 | Platform API key expired | API密钥过期 | | | 100420 | Invalid email address | 无效邮箱 | | | | | | | 通用错误类 | 100600 | Invalid token | 非法token信息 | | | 100601 | Token expired | token过期 | | | 100602 | Transaction refused | 交易拒绝 | | | 100603 | Transaction cancelled by the merchant | 商家取消交易 | | | 100604 | 3D Secure authentication cancelled by the cardholder | 持卡人取消3D授权 | | | 100605 | Cardholder failed 3D Secure authentication | 持卡人未通过3D服务授权 | | | 100606 | 3D Secure authentication timeout | 3D授权操作超时 | | | 100607 | Transaction declined by card issuer | 发卡方拒绝交易 | | | 100608 | Order expire | 订单已过期 | | | 100609 | Do not honour | 交易不予兑现 | | | 100610 | Original transaction failed | 原始交易失败 | | | 100611 | Transaction already revoked; cannot revoke repeatedly | 交易已撤销,不能再次撤销 | | | 100612 | Transaction already cancelled; cannot cancel repeatedly | 交易已取消,不能再次取消 | | | 100613 | Exceeds PIN retry limit | 超过pin重试次数 | | | 100614 | Incorrect password | 密码错误 | | | 100615 | Incorrect PIN | PIN错误 | | | 100616 | Exceeds withdrawal amount limit | 超出账户提现限制 | | | 100617 | Payment instrument declined | 当前方式被受理方或者银行拒绝 | | | 100618 | Payment voided | 支付单作废 | | | 100619 | Duplicate transaction | 重复的交易 | | | 100620 | Record not found | 交易不存在 | | | 100621 | Transaction not in current batch | 撤销交易不在当前批次 | | | 100622 | Authentication unfinished | 授权未完成 | | | | | | | 未知错误 | 100998 | Payment failed. Please try again with another payment method or try again later. | 交易失败,请尝试使用其他支付方式或稍后再试 | | 无法明确错误码 | 100999 | Other error | 其他错误 | # 沙箱环境 Source: https://docs.subotiz.com/zh/resources/sandbox Subotiz 沙箱环境是专为开发者、测试人员提供的功能验证与调试环境,用于在不影响线上真实业务数据和流程的前提下,开展产品功能测试、接口联调、兼容性验证等工作。该环境配置与线上环境核心逻辑一致,仅在时间流速、数据性质等方面存在差异,可用于高效完成测试验证工作。 ## 环境信息 具体参考文档:[环境信息](/zh/quick-start/subotiz-merchants) # Subotiz A/B 实验 SDK Source: https://docs.subotiz.com/zh/resources/subotiz-ab-test-sdk Subotiz A/B 实验前端 SDK。在浏览器中拉取实验分组数据、支持按需上报转化事件。 * 浏览器优先,**不依赖任何 UI 框架**(React / Vue / 原生页面均可) * 原生 TypeScript 支持,类型完整 *** ## 通过 CDN 加载 可通过 CDN 引入 SDK。 CDN 模式调用语法:`abSubotiz(方法名, ...参数)` ```html theme={null} ``` *** ## 上报事件 业务事件通过 `track(eventName, properties?)` 上报,常用于实验转化分析(注册完成、按钮点击、自有收入 / LTV 等平台无法自动采集的指标): ```typescript theme={null} abSubotiz.track('signup_complete'); // 计数 / 去重类指标 abSubotiz.track('add_to_cart', { source: 'cta' }); // 额外标签随事件透传 abSubotiz.track('ltv', { value: 99.9 }); // 数值类指标(求和 / 均值) abSubotiz.track('checkout_success', { value: 99, currency: 'USD' }); // value + 额外标签 ``` 特性: * **永远上报、永不丢弃**——SDK 不在客户端做白名单拦截,任意 `eventName` 都会发往后端。是否计入某个实验由后端归因,无需前端关心 * **永远成功返回**,不抛出异常 * 网络失败 / 5xx → 入 `localStorage` 离线队列,回到在线状态时自动重发 * 4xx → 静默丢弃(事件本身不合法) * `init` 未完成时调用 → 静默跳过 不要在事件参数中传用户隐私数据(手机号、邮箱、身份证、地址等)。SDK 不做过滤,由调用方自行约束。 ### 数值指标:`properties.value` 需要**求和 / 平均值**类聚合的指标(如收入、LTV、停留时长),把数值放在 `properties.value` 上: ```typescript theme={null} abSubotiz.track('ltv', { value: 99.9, tier: 'pro' }); ``` * `value` 必须是**有限数字**(`typeof === 'number'` 且非 `NaN` / `Infinity`)才会被后端纳入数值聚合。 * 非法的 `value`(字符串 `'99.9'`、`NaN`、`null` 等)不会污染数值统计,会作为普通标签原样透传,由后端按"非数值"降级处理。 * 计数 / 去重类指标(如 `signup_complete`)**无需**传 `value`,直接 `track('signup_complete')` 即可。 * `properties` 中除 `value` 外的其他字段都作为附加标签随事件上报,字段名自定。 ### 调试:指标白名单提示 后台为实验声明的指标 key 会随分桶结果下发,SDK 在 **`debug: true`** 时据此做拼写提示:当 `track` 的 `eventName` **不在**任何运行中实验声明的指标里,控制台会 `warn`(提示可能拼写错误 / 大小写不符,并打印当前白名单)。 这**只是调试提示**——事件依然正常上报。生产模式(`debug: false`)下完全无此开销,不影响上报行为。 ### 曝光事件 实验首次命中时 SDK 会**自动**上报曝光事件,不需要手动调用。粘性缓存中已存在的实验不重复上报。 *** ## Pricing 链接自动注入 实验对象类型为 `price_list` 时,SDK 会在返回的价格表链接中,追加以下 query 参数。业务方拿到的链接已经是注入完毕的: | 参数 | 值 | | -------------- | ---------------------------------------------- | | `ab_sbt_sid` | 当前商家 id | | `ab_sbt_uid` | 当前用户 id | | `ab_sbt_utype` | `'user'` 或 `'anonymous'` | | `ab_sbt_sch` | 来源渠道(仅当 `init` 传入了合法 `sourceChannel` 时才追加,见下文) | ```typescript theme={null} // → https://checkout.subotiz.com/pricing-v2?ab_sbt_sid=store_123&ab_sbt_uid=user_456&ab_sbt_utype=user const exp = experiments['pricing_redirect_test']; if (exp && exp.objectType === 'price_list') { window.location.href = exp.config!.link as string; } ``` *** ## 来源渠道定向 (sourceChannel) `init` 时可传入 `sourceChannel`,用于让后端按**流量来源**做实验定向分流(例如"仅对来自 facebook 的流量开启某实验")。其余定向维度(设备、语言、国家、IP)由后端从 HTTP 请求头自动解析,**SDK 不采集任何浏览器指纹 / UA / 地理位置信息**。 ```typescript theme={null} abSubotiz.init({ storeId: 'your_store_id', sourceChannel: 'facebook', }); ``` 传入后,SDK 会在两处携带该值: 1. **分桶请求**:写入 `POST /sdk/v1/ab/assign` 请求体的 `attributes.source_channel`,供后端定向规则匹配。 2. **Pricing 链接**:对 `price_list` 类型实验的链接追加 `ab_sbt_sch` query 参数(与上面的值同源)。 ### 取值与归一化规则 SDK **不做枚举校验、不做大小写转换**,取值口径(如 `facebook` / `google` / `tiktok`)由您与产品侧自行约定。携带前仅做如下处理: | 传入值 | 处理结果 | | --------------------------- | ---------------------------------------- | | 正常字符串 | **trim 后**携带(保留原始大小写) | | `undefined` / `null` / 非字符串 | 视为未传,不携带 `source_channel` 字段(不是空串占位) | | 空字符串 / 纯空白 | 视为未传,不携带 | | trim 后长度 ≥ 50 | 视为未传,不携带(`debug: true` 时控制台 `warn` 提示超长) | **稳定性**:`sourceChannel` 在单次会话内被视为稳定值,仅 `init` 时确定一次。后续不监听变化、不会因渠道变化重新拉取分桶。 未携带优于截断:超长 / 非法值一律不携带,避免后端拿到被静默改写的值后与您的埋点配置产生偏差。 *** ## API 参考 ### `init(config)` 初始化 SDK。在每个 SDK 实例上**只能调用一次**,重复调用会被忽略。立即返回,不阻塞主线程。 * **参数** `config: SubotizSDKConfig` * **返回** `void` #### 配置项 `init(config)` 接受一个 `SubotizSDKConfig` 对象: | 字段 | 类型 | 默认 | 说明 | | --------------- | --------- | ------- | --------------------------------------------------- | | `storeId` | `string` | — | **必填**。商家 ID(Subotiz 后台店铺 access no) | | `sourceChannel` | `string` | — | 可选。来源渠道,用于后端流量定向。详见 [来源渠道定向](#来源渠道定向-sourcechannel) | | `timeout` | `number` | `30000` | 分桶请求超时毫秒数 | | `debug` | `boolean` | `false` | 打开调试日志,并允许 `forceVariant` 生效。**生产环境保持关闭** | ### `onReady(onSuccess, onError?)` 注册就绪回调。SDK 已就绪时同步触发,未就绪时异步触发。可重复注册多个。 ```typescript theme={null} abSubotiz.onReady( (experiments) => { /* 实验数据已就绪 */ }, (error) => { /* 网络异常且无缓存 */ }, ); ``` * **参数** * `onSuccess: (experiments: SubotizExperimentMap) => void` * `onError?: (error: ABTestError) => void` * **返回** `void` ### `waitReady()` `onReady` 的 Promise 版本。 ```typescript theme={null} const experiments = await abSubotiz.waitReady(); ``` * **返回** `Promise` * **失败时**:抛出 `ABTestError`(与 `onReady` 的 `onError` 等价) ### `isReady()` 同步检查 SDK 是否已就绪。 * **返回** `boolean` ### `getExperiments()` 同步获取当前所有命中实验。 * **返回** `SubotizExperimentMap | null` * `null` —— 未初始化、未就绪、或当前没有任何命中实验 * `Record` —— 实验映射表,键为 `experimentId` ### `track(eventName, properties?)` 上报自定义业务事件。任意事件都会上报,是否计入实验由后端归因。 ```typescript theme={null} abSubotiz.track('signup_complete'); // 计数 / 去重 abSubotiz.track('ltv', { value: 99.9, tier: 'pro' }); // 求和 / 均值,value 必须是有限数字 ``` * **参数** * `eventName: string` —— 事件名 * `properties?: Record` —— 事件附加属性。其中 `value`(有限数字)用于求和 / 均值类指标;其余字段作为附加标签透传 * **返回** `void`(永不抛错) * **行为** * 永远上报,不在客户端做白名单丢弃 * `debug: true` 且 `eventName` 不在后台声明的指标白名单中 → 控制台 `warn` 拼写提示(仅提示,不影响上报) * `init` 未完成时调用 → 静默跳过 ### `forceVariant(experimentId, variantKey)` **仅 `debug: true` 时生效**。本地强制覆盖某实验的变体,便于开发期验证不同变体的 UI。 ```typescript theme={null} abSubotiz.forceVariant('homepage_hero_test', 'variant_b'); ``` * **参数** `experimentId: string`、`variantKey: string` * **返回** `void` *** ## 错误处理 `onReady(_, onError)` 与 `waitReady()` 失败时返回 `ABTestError`: ```typescript theme={null} interface ABTestError { code: ABTestErrorCode; message: string; cause?: unknown; } ``` 错误码: | 错误码 | 含义 | | ------------------ | -------------------------- | | `NETWORK_TIMEOUT` | 请求超时(弱网) | | `NETWORK_ERROR` | 网络请求失败(离线、跨域被拦截) | | `HTTP_ERROR` | 后端返回非 2xx | | `INVALID_RESPONSE` | 响应格式异常 | | `NOT_INITIALIZED` | `init` 校验失败(如缺少 `storeId`) | ```typescript theme={null} abSubotiz.onReady( (experiments) => render(experiments), (error) => { if (error.code === "NOT_INITIALIZED") { console.error('init 配置非法', error.message); } // do something }, ); ``` ### 降级策略 SDK 内置降级策略,业务方只需关心三件事: 1. **首次渲染走对照组** —— `await waitReady()` 在网络异常时最长会等 `timeout` 秒,不要用它阻塞首屏 2. **`onReady` / `waitReady` 中切换变体** —— 用户视觉冲击最小 3. **`onError` 时保持对照组** —— 不展示空白或异常 UI | 场景 | SDK 行为 | | ------------------ | --------------------------- | | 二次访问 + 网络异常 | 自动用 `localStorage` 缓存进入就绪态 | | 首次访问 + 网络异常 | 触发 `onError` | | `track` 时 5xx / 离线 | 入离线队列,`window.online` 时自动重发 | | `track` 时 4xx | 静默丢弃 | *** ## 调试 打开 `debug: true` 后,SDK 会在控制台输出请求与队列状态: ```typescript theme={null} abSubotiz.init({ storeId: 'store_123', debug: true }); ``` | 日志 | 含义 | | ------------------------------------------------------------ | ---------------------------- | | `[ab-sdk] reportExposure: sending N event(s)` | 曝光上报中 | | `[ab-sdk] track: sending N event(s)` | 自定义事件上报中 | | `[ab-sdk] track event queued (offline)` | 事件入离线队列 | | `[ab-sdk] 4xx error, track event dropped` | 4xx 静默丢弃 | | `[ab-sdk] MetricKeyRegistry rebuilt: N keys` | 分桶成功后重建指标白名单(含 key 预览) | | `[ab-sdk] track('xxx') did not match the metric_keys ...` | `track` 事件名未命中白名单的拼写提示(仍会上报) | | `[ab-sdk-subotiz] sourceChannel length N >= 50, omitted ...` | `sourceChannel` 超长被忽略 | | `[ab-sdk] Forced variant: xxx → yyy` | `forceVariant` 调用 | ### 重置 SDK 状态 ```typescript theme={null} Object.keys(localStorage) .filter((k) => k.startsWith('_ab_sdk_') || k.startsWith('ab_event_queue_')) .forEach((k) => localStorage.removeItem(k)); ``` ### 本地存储键 SDK 在 `localStorage` 中使用以下键: | 键名 | 内容 | | -------------------------------------------- | ---------------- | | `_ab_sdk_uuid` | 匿名用户 UUID(跨租户共享) | | `_ab_sdk_exp_{storeId}_{userId}` | 实验分配快照(有效期 60 天) | | `ab_event_queue_{storeId}_{userId}_track` | 离线事件上报队列 | | `ab_event_queue_{storeId}_{userId}_exposure` | 离线曝光事件队列 | *** ## 常见问题 ### SDK 加载之前业务代码已经渲染了,会拿不到实验数据? 会。让业务代码先渲染对照组,再在 `onReady` / `waitReady` 中切换到变体。粘性缓存保证用户刷新后稳定看到自己的变体(首次访问会有"对照组 → 变体"的瞬时切换)。 ### `track` 调用了,后端没收到怎么排查? 按顺序检查: 1. `abSubotiz.isReady()` 是否为 `true`?未就绪时 `track` 静默跳过。 2. 打开 `debug: true`,看控制台是否有 `track: sending` 日志。 3. 看浏览器网络面板有没有 `POST /sdk/v1/ab/events` 请求。 4. 响应是 4xx 还是 5xx?4xx 会被丢弃,5xx 会入队等待重发。 5. 看 `localStorage.ab_event_queue_*_track` 是否积压事件。 ### 我传了 `sourceChannel`,但实验定向没生效 按顺序检查: 1. 打开 `debug: true`,看分桶请求体 `attributes.source_channel` 是否带上了您的值。 2. 确认值合法:trim 后非空、长度 \< 50。超长会被忽略(控制台有 `warn`)。 3. 确认值与后台定向规则**完全一致**——SDK 不做大小写转换,`Facebook` ≠ `facebook`。 4. 定向规则匹配在后端完成;命中与否可用 `getExperiments()` 看是否拿到该实验。 ### `track` 的 `value` 没有进入求和 / 均值统计 `value` 必须是**有限数字**(`typeof === 'number'` 且非 `NaN` / `Infinity`)才会被纳入数值聚合。常见错误是传入字符串:`track('ltv', { value: '99.9' })`(字符串)会被当成普通标签,不参与 sum / average,应改为 `{ value: 99.9 }`。 ### 同一个实验,刷新前后变体不一致 SDK 粘性缓存保证 60 天内变体稳定。出现不一致通常是: * `localStorage` 被清除(隐私模式 / 用户主动清空) * 后台开启了**用户强制分配**,会覆盖粘性缓存 ### 实验在生产没生效,怎么排查 按顺序检查: 1. `storeId` 是否正确(错误的 storeId 不报错,只是拿不到任何实验) 2. 后台实验是否处于"运行中"状态(暂停 / 草稿状态不会下发) 3. 用户是否命中实验定向规则(设备 / 国家由后端从 HTTP 请求头解析) 4. 用 `getExperiments()` 看返回结果,确认是不是变体决策本身就是对照组 ### 我想让某个用户完全不参与实验 SDK 不提供"退出实验"接口。变通方案:业务代码自行判断(如登录态 / 角色),命中条件时不读 `experiments` 直接走默认渲染。 ### `getExperiments()` 为什么返回 `null` 而不是空对象 `null` 表示"未就绪"或"无任何命中实验",便于做存在性判断: ```typescript theme={null} const all = ab.getExperiments(); if (!all) return renderDefault(); ``` 避免写 `Object.keys(all).length === 0`。 ### React 服务端组件 / Edge Runtime 能用吗 不能。SDK 依赖 `localStorage` / `document.cookie` / `window` 等浏览器接口。 *** ## 浏览器兼容性 依赖原生 `fetch` / `Promise` / `localStorage`。支持: * Chrome / Edge ≥ 最近 2 个大版本 * Safari ≥ 最近 2 个大版本 * Firefox ≥ 最近 2 个大版本 不支持 IE。SDK 不内置任何兼容垫片。 # Subotiz SDK Source: https://docs.subotiz.com/zh/resources/subotiz-sdk **文档索引** 获取完整文档索引:[https://docs.subotiz.com/llms.txt](https://docs.subotiz.com/llms.txt) 您可以通过该文件了解全部可用页面,再进一步浏览所需内容。 ## 使用说明 ### CDN地址 ```text theme={null} https://cdn.subotiz.com/static/subotiz/v0/subotiz.js ``` ### SDK实例化 通过以下代码完成SDK实例创建: ```javascript theme={null} const subotiz = window.Subotiz() ``` ### 预热Checkout(推荐) 此方法用于提前加载Checkout所需资源,使后续打开Checkout时首屏展示更快。 `prewarm`是挂载在`Subotiz`上的**静态方法**,无需创建SDK实例即可调用。预热在页面空闲时进行,不影响您页面的正常加载。 **建议在引入subotiz.js后尽早调用**,无需等待`initEmbeddedCheckout`,以预留充足的预热时间。 #### 方法调用示例 ```html theme={null} ``` #### 参数说明 Options (可选) object类型 | 属性 | 类型 | 必填 | 默认值 | 描述 | | ----------- | ------------------------ | -- | ---------- | ------------------------------------------------------------------------------------------ | | environment | 'SANDBOX' | 'PRODUCTION' | 否 | 'SANDBOX' | 当前环境设置,需与初始化Checkout时保持一致
'SANDBOX' - 沙盒环境(默认值)
'PRODUCTION' - 生产环境 | | checkoutUrl | string | 否 | | 自定义Checkout域名,提供时优先于`environment`。
**必须与后续实际使用的Checkout域名一致**,否则预热不生效 | | trigger | 'domready' | 'immediate' | 否 | 'domready' | 预热触发时机
'domready' - 页面DOM就绪后自动预热(默认值,推荐)
'immediate' - 调用后立即预热,适用于您希望自行控制预热时机的场景 | ### 初始化嵌入式Checkout 此方法用于初始化嵌入式Checkout支付组件,返回Checkout实例。 #### 方法调用示例 ```javascript theme={null} const checkout = await subotiz.initEmbeddedCheckout({ fetchSessionUrl: async() =>{ // 从服务端获取sessionURL示例 const response = await fetch('/api/session'); const data = await response.json(); return data.sessionUrl; }, environment: 'SANDBOX', // 'SANDBOX' | 'PRODUCTION' }); ``` #### 参数说明 Options (必传) object类型 | 属性 | 类型 | 必填 | 默认值 | 描述 | | --------------- | ------------------------ | -- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | fetchSessionId | `()=>Promise` | 否 | | 回调函数 `fetchClientSecret() => Promise` 获取 Checkout Session id。
`fetchSessionId`与`fetchSessionUrl`必须要提供⼀个,同时提供时仅调⽤`fetchSessionId` | | fetchSessionUrl | `()=>Promise` | 否 | | 回调函数 `fetchClientSecret() => Promise` 获取 Checkout Session URL。
`fetchSessionId`与`fetchSessionUrl`必须要提供⼀个,同时提供时仅调⽤`fetchSessionId` | | environment | 'SANDBOX' | 'PRODUCTION' | 否 | 'SANDBOX' | 当前环境设置
'SANDBOX' - 沙盒环境(默认值)
'PRODUCTION' - 生产环境 | | onComplete | ()=>void | 否 | | 支付完成时的回调函数仅在创建Checkout Session时将`redirect_on_completion` 设置为 `if_required` 时触发,即用户不接受自动重定向时触发该回调 | ### 挂载Checkout组件 需先创建容器DOM元素,再将Checkout组件挂载到该容器中。 #### 操作示例 ```html theme={null}
``` #### 参数说明 * selector **必传** string类型,容器元素的CSS选择器(如`#your_domElement`) ### 卸载Checkout组件 从DOM中卸载已挂载的Checkout组件,后续可通过`mount`重新挂载。 ```javascript theme={null} checkout.unmount(); ``` # 测试卡 Source: https://docs.subotiz.com/zh/resources/test-cards Subotiz 各支付渠道的测试卡数据,用于接入方在开发测试阶段模拟支付流程,所有交易均处于沙箱环境,不产生真实资金流转。 #### 使用说明: * **适用场景**:仅用于验证支付集成功能(如交易发起、状态回调、错误处理等),需搭配 Subotiz 沙箱环境使用。测试卡信息无法应用于生产环境; * **渠道分类逻辑**:测试卡按支付渠道划分,商家可根据自身设置的支付渠道选择对应测试卡,确保测试场景与实际接入场景一致; * **通用填写规范**:有效期需填写任意未来日期(如 12/34),CVC 按卡品牌要求填写(Visa/Mastercard 等填 3 位数,American Express 填 4 位数),其他表单字段可填写任意合规值; * **注意事项**:请勿使用真实银行卡信息进行测试,测试卡仅用于功能验证,不具备真实支付效力,确保集成测试符合支付合规要求。 ## PayPal | 使用场景 | 卡号示例 | CVC 要求 | 有效期要求 | | :---------------- | :--------------- | :------ | :----- | | 支付成功 | 5329879707824603 | 任意 3 位数 | 任意未来日期 | | 支付成功 | 371449635398431 | 任意 3 位数 | 任意未来日期 | | 支付成功 (打开3ds会支付失败) | 4111111111111111 | 任意 3 位数 | 任意未来日期 | | 支付成功 (打开3ds会支付失败) | 4005519200000004 | 任意 3 位数 | 任意未来日期 | | 支付失败 | 4868719460707704 | 任意 3 位数 | 任意未来日期 | | 支付失败 | 4147044347484424 | 任意 3 位数 | 任意未来日期 | ## Subotiz Payments | 使用场景 | 卡号示例 | CVC 要求 | 有效期要求 | | :---------------- | :--------------- | :------ | :----- | | Visa - 支付成功 | 4242424242424242 | 任意 3 位数 | 任意未来日期 | | Mastercard - 支付成功 | 5555555555554444 | 任意 3 位数 | 任意未来日期 | | 支付失败 | 4000000000000002 | 任意 3 位数 | 任意未来日期 | | 支付失败 | 4000000000009995 | 任意 3 位数 | 任意未来日期 | | 3ds 验证 - 支付成功 | 4000000000003220 | 任意 3 位数 | 任意未来日期 | | 3ds 验证 - 支付失败 | 4000008400001629 | 任意 3 位数 | 任意未来日期 | | 异步退款成功 | 4000000000007726 | 任意 3 位数 | 任意未来日期 | | 异步退款失败 | 4000000000005126 | 任意 3 位数 | 任意未来日期 | # 争议 Source: https://docs.subotiz.com/zh/webhook/dispute-2 ## 事件列表 | **事件名称** | **事件类型** | **触发时机** | **通知数据结构** | | -------- | ------------------- | ------------------------- | -------------------------------- | | 争议创建通知 | v2.disputes.created | 争议首次创建时 | [Dispute](/zh/webhook/dispute-2) | | 争议更新通知 | v2.disputes.updated | 争议关键字段(状态、原因、金额、截止时间等)变化时 | [Dispute](/zh/webhook/dispute-2) | ## 事件对象 | **属性** | **类型** | **描述** | **示例** | | --------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | | id | string | Subotiz 争议 ID | 583570323576728234 | | channel\_dispute\_id | string | 渠道争议 ID | dp\_1OqFkP2eZvKYlo2C | | merchant\_id | string | 商户 ID | 100010 | | order\_id | string | 交易单 ID | order\_1769076135405830680 | | payment\_channel | string | 支付渠道 | stripe | | payment\_method | string | 支付方式 | card | | dispute\_status | string | 争议状态:
`inquiry_needs_response` - 待商家回应(查询)
`inquiry_under_review` - 审核中(查询)
`case_closed` - 已关闭
`needs_response` - 待商家回应
`under_review` - 审核中
`won` - 争议胜诉
`lost` - 争议败诉
`open` - 尚未解决
`pending_customer_response` - 待客户回应
`needs_response_appealable` - 待商家回应(可申诉) | needs\_response | | dispute\_reason | string | 争议原因:
`unauthorized` - 客户未授权购买商品或服务
`product_not_received` - 客户未收到商品或服务
`product_unacceptable` - 客户报告商品或服务与描述不符
`credit_not_processed` - 未为客户处理退款或信贷
`duplicate` - 交易重复
`subscription_canceled` - 订阅已取消
`unrecognized` - 客户无法识别的交易
`incorrect_charge_amount` - 收费金额有误
`payment_by_other_methods` - 客户通过其他方式付款
`remittance_processing_error` - 汇款问题
`others` - 其他 | unauthorized | | order\_amount | string | 订单金额 | 100.00 | | order\_currency | string | 订单币种 | USD | | dispute\_amount | string | 争议金额 | 100.00 | | dispute\_currency | string | 争议币种 | USD | | dispute\_create\_time | string | 争议创建时间(RFC3339) | 2026-03-15T08:30:00Z | | dispute\_update\_time | string | 最后更新时间(RFC3339) | 2026-03-15T08:30:00Z | | dispute\_due\_time | string | 回应截止日(RFC3339) | 2026-03-22T08:30:00Z | ## 示例 ```json v2.disputes.created theme={null} { "id": "583570323576728234", "type": "v2.disputes.created", "created": "2026-03-15T08:30:00Z", "data": { "id": "583570323576728234", "channel_dispute_id": "dp_1OqFkP2eZvKYlo2C", "merchant_id": "100010", "order_id": "order_1769076135405830680", "payment_channel": "stripe", "payment_method": "card", "dispute_status": "needs_response", "dispute_reason": "unauthorized", "order_amount": "100.00", "order_currency": "USD", "dispute_amount": "100.00", "dispute_currency": "USD", "dispute_create_time": "2026-03-15T08:30:00Z", "dispute_update_time": "2026-03-15T08:30:00Z", "dispute_due_time": "2026-03-22T08:30:00Z" } } ``` ```json v2.disputes.updated theme={null} { "id": "583570323576728235", "type": "v2.disputes.updated", "created": "2026-03-18T10:15:00Z", "data": { "id": "583570323576728234", "channel_dispute_id": "dp_1OqFkP2eZvKYlo2C", "merchant_id": "100010", "order_id": "order_1769076135405830680", "payment_channel": "stripe", "payment_method": "card", "dispute_status": "under_review", "dispute_reason": "unauthorized", "order_amount": "100.00", "order_currency": "USD", "dispute_amount": "100.00", "dispute_currency": "USD", "dispute_create_time": "2026-03-15T08:30:00Z", "dispute_update_time": "2026-03-18T10:15:00Z", "dispute_due_time": "2026-03-22T08:30:00Z" } } ``` # 事件类型 Source: https://docs.subotiz.com/zh/webhook/event-types | **事件名称** | **事件类型** | **触发时机** | **通知数据结构** | 描述 | | --------- | -------------------------------------- | --------------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- | | 试用期即将到期通知 | subscription. trial\_period\_expiring | 试用期剩余时间小于 3 天时,提醒一次 | [Subscription](/zh/webhook/subscription-1) | 用户订阅试用期 3 天后到期 。
**使用场景:**
到期提醒:向用户推送到期提醒。 | | 首次订阅通知 | subscription.first | 订阅首次生效时 | [Subscription](/zh/webhook/subscription-1) | 订阅首次进入**试用期**或者**活跃**状态时通知,每个订阅只会发送一次。
**使用场景:**
订阅成功推送:发送首次订阅成功的消息(如推送、邮件)
权益发放:为用户解锁订阅对应的服务权限(如付费功能、资源额度) | | 终止订阅通知 | subscription.canceled | 订阅终止时 | [Subscription](/zh/webhook/subscription-1) | 订阅实际终止时通知。
**使用场景:**
终止服务提示:告知用户订阅已终止,明确服务停止时间
权限回收:回收用户付费权益 | | 订阅价格变更 | subscription.price\_changed | 订阅价格变更时 | [Subscription](/zh/webhook/subscription-1) | 订阅价格变更时,通知变更具体信息。 | | 账单支付成功 | invoice.paid | 一次性商品、首次订阅和订阅续订支付成功时通知 | [Invoice](/zh/webhook/invoice) | 一次性商品和订阅相关的支付成功时会发送该通知。用于同步账单状态、订阅管理。
**使用场景:**
账单状态同步:更新账单状态为"已完成";
订阅管理:续订账单中会包含订阅周期信息,如当前周期数、周期时间等 | | 账单支付失败 | invoice.payment\_failed | 一次性商品、首次订阅和订阅续订支付失败时通知 | [Invoice](/zh/webhook/invoice) | 一次性商品和订阅相关的支付失败时会发送该通知。不会每次重试支付失败都通知,只在最终支付失败时通知。
**使用场景:**
失败提醒与引导支付:告知用户支付失败,提供重新支付入口 | | 账单退款 | invoice.refunded | 当订阅产生的交易单退款成功时通知,用于获取订阅退款信息 | [Invoice](/zh/webhook/invoice) | 一次性商品和订阅相关的支付发生退款时会发送该事件。用于同步退款状态。 | | 交易单支付成功 | trades.succeeded | 支付成功时 | [Trade](/zh/webhook/trade-1) | 所有类型的支付成功时会发送该通知,适用于纯金额交易的闭环。 | | 交易单支付失败 | trades.payment\_failed | 支付失败时 | [Trade](/zh/webhook/trade-1) | 所有类型的支付失败时会发送该通知,适用于纯金额交易的闭环。 | | 退款成功 | refunds.succeeded | 退款成功时 | [Refund](/zh/webhook/refund-1) | 退款实际完成时通知。
**使用场景:**
退款通知与状态同步:告知用户退款金额,更新退款单状态为"已完成" | | 退款失败 | refunds.failed | 退款失败时 | [Refund](/zh/webhook/refund-1) | 退款实际失败时通知
**使用场景:**
状态同步:更新退款单状态为“失败"
重试与人工干预:触发自动重试机制,或通知客服人工排查,及时重新发起退款,避免用户投诉和资金纠纷。 | # 事件类型 Source: https://docs.subotiz.com/zh/webhook/event-types-1 | **事件名称** | **事件类型** | **触发时机** | **通知数据结构** | 描述 | | --------- | ----------------------------------------- | --------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | 试用期即将到期通知 | v2.subscription. trial\_period\_expiring | 试用期剩余时间小于 3 天时,提醒一次 | [Subscription](/zh/webhook/subscription-2) | 用户订阅试用期 3 天后到期 。
**使用场景:**
到期提醒:向用户推送到期提醒。 | | 首次订阅通知 | v2.subscription.first | 订阅首次生效时 | [Subscription](/zh/webhook/subscription-2) | 订阅首次进入**试用期**或者**活跃**状态时通知,每个订阅只会发送一次。
**使用场景:**
订阅成功推送:发送首次订阅成功的消息(如推送、邮件)
权益发放:为用户解锁订阅对应的服务权限(如付费功能、资源额度) | | 终止订阅通知 | v2.subscription.canceled | 订阅终止时 | [Subscription](/zh/webhook/subscription-2) | 订阅实际终止时通知。
**使用场景:**
终止服务提示:告知用户订阅已终止,明确服务停止时间
权限回收:回收用户付费权益 | | 订阅价格变更 | v2.subscription.price\_changed | 订阅价格变更时 | [Subscription](/zh/webhook/subscription-2) | 订阅价格变更时,通知变更具体信息。 | | 订阅暂停 | v2.subscription.paused | 订阅暂停时通知 | [Subscription](/zh/webhook/subscription-2) | 订阅暂停时通知,用于同步订阅状态。
**使用场景:**
暂停提醒:告知用户订阅已暂停,服务暂时停止
权限调整:暂停用户的订阅权益访问 | | 订阅重启 | v2.subscription.resumed | 订阅重启时通知 | [Subscription](/zh/webhook/subscription-2) | 订阅从暂停状态恢复时通知。
**使用场景:**
恢复通知:告知用户订阅已重新启用
权益恢复:重新开放用户的订阅权益和服务 | | 订阅逾期 | v2.subscription.past\_due | 订阅逾期时通知 | [Subscription](/zh/webhook/subscription-2) | 订阅支付逾期时通知,通常在自动续订扣款失败后进入该状态。
**使用场景:**
逾期提醒:提醒用户更新支付方式或补缴费用
宽限期管理:进入宽限期,限制部分功能但保留数据 | | 订阅未支付 | v2.subscription.unpaid | 订阅未支付时通知 | [Subscription](/zh/webhook/subscription-2) | 订阅因长期未支付而被标记为未支付状态时通知。
**使用场景:**
催款通知:最后一次催促用户完成支付
服务限制:暂停或限制用户的订阅服务权限 | | 撤回取消订阅 | v2.subscription.cancellation\_revoked | 撤回取消订阅时通知 | [Subscription](/zh/webhook/subscription-2) | 用户撤回之前的取消订阅请求时通知。
**使用场景:**
状态同步:更新订阅状态为正常,取消之前的终止计划
挽留成功提醒:告知用户订阅将继续,确认服务持续 | | 请求取消订阅 | v2.subscription.cancellation\_requested | 请求取消订阅时通知 | [Subscription](/zh/webhook/subscription-2) | 用户请求取消订阅时通知,但订阅尚未实际终止。
**使用场景:**
挽留机会:触发用户挽留流程,提供优惠或解决方案
状态标记:标记订阅为"待取消"状态,等待周期结束 | | 订阅固定期限变更 | v2.subscription.fixed\_term\_updated | 订阅的固定期限被修改时通知 | [Subscription](/zh/webhook/subscription-2) | 当订阅的固定期限设置发生变更时通知,包括修改期数、切换是否支持到期转续、转为持续订阅等操作。通知数据中包含 `previous_fixed_term_info`,记录变更前的固定期限信息。
**使用场景:**
状态同步:同步订阅的固定期限变更,更新本地记录
业务联动:根据固定期限变更调整用户权益或提醒策略 | | 账单支付成功 | v2.invoice.paid | 一次性商品、首次订阅和订阅续订支付成功时通知 | [Invoice](/zh/webhook/invoice-2) | 一次性商品和订阅相关的支付成功时会发送该通知。用于同步账单状态、订阅管理。
**使用场景:**
账单状态同步:更新账单状态为"已完成";
订阅管理:续订账单中会包含订阅周期信息,如当前周期数、周期时间等 | | 账单支付失败 | v2.invoice.payment\_failed | 一次性商品、首次订阅和订阅续订支付失败时通知 | [Invoice](/zh/webhook/invoice-2) | 一次性商品和订阅相关的支付失败时会发送该通知。不会每次重试支付失败都通知,只在最终支付失败时通知。
**使用场景:**
失败提醒与引导支付:告知用户支付失败,提供重新支付入口 | | 账单退款 | v2.invoice.refunded | 当订阅产生的交易单退款成功时通知,用于获取订阅退款信息 | [Invoice](/zh/webhook/invoice-2) | 一次性商品和订阅相关的支付发生退款时会发送该事件。用于同步退款状态。 | | 交易单支付成功 | v2.trades.succeeded | 支付成功时 | [Trade](/zh/webhook/trade-2) | 所有类型的支付成功时会发送该通知,适用于纯金额交易的闭环。 | | 交易单支付失败 | v2.trades.payment\_failed | 支付失败时 | [Trade](/zh/webhook/trade-2) | 所有类型的支付失败时会发送该通知,适用于纯金额交易的闭环。 | | 退款成功 | v2.refunds.succeeded | 退款成功时 | [Refund](/zh/webhook/refund-2) | 退款实际完成时通知。
**使用场景:**
退款通知与状态同步:告知用户退款金额,更新退款单状态为"已完成" | | 退款失败 | v2.refunds.failed | 退款失败时 | [Refund](/zh/webhook/refund-2) | 退款实际失败时通知
**使用场景:**
状态同步:更新退款单状态为“失败"
重试与人工干预:触发自动重试机制,或通知客服人工排查,及时重新发起退款,避免用户投诉和资金纠纷。 | | 争议创建通知 | v2.disputes.created | 争议首次创建时 | [Dispute](/zh/webhook/dispute-2) | 渠道首次回传争议数据时通知,每个 `channel_dispute_id` 仅发送一次。
**使用场景:**
争议入账:在商户系统中创建对应争议工单
资金提示:根据 `dispute_amount` 在结算视图中标记冻结金额 | | 争议更新通知 | v2.disputes.updated | 争议关键字段变化时 | [Dispute](/zh/webhook/dispute-2) | 已存在的争议在状态、原因、金额或截止时间等关键字段发生变化时通知。
**使用场景:**
状态同步:根据 `dispute_status` 更新本地争议状态
抗辩提醒:根据 `dispute_due_time` 推送商户证据提交提醒 | # 概述 Source: https://docs.subotiz.com/zh/webhook/introduction-2 在与 Subotiz 系统集成时,商户可通过配置 Webhook 通知端点,实时接收账户关联事件,以便后端系统触发对应的业务逻辑处理(如支付状态更新、订阅状态变更等)。 ## 端点校验 商户在管理后台配置 Webhook 端点时,Subotiz 会向该端点发送一个 `type` 为 `check_callback_url` 的简化事件,用于校验端点的可达性。接收方需确保对该事件返回的 HTTP 状态码 \< 500,否则端点配置将无法通过校验。 ## 通知原理 当 Subotiz 系统触发特定事件时,将向配置的 Webhook 通知端点发送 HTTPS POST 请求。请求包含以下关键要素: * **请求负载**:符合 JSON 格式规范的结构化事件对象,包含事件标识、类型及具体业务数据; * **请求头信息**:包含用于鉴权与请求标识的特定头部(如 X-Timestamp 时间戳、X-Signature 签名等); ## 请求组成 ### 请求头部 | **Header 名** | **示例值** | **说明** | | ------------ | ---------------------------------------------------------------- | ----------------- | | X-Timestamp | 1525872629832 | 参与签名计算的毫秒时间戳 | | Content-Type | application/json | | | X-Access-No | 100001 | 接入方唯一号`access_no` | | X-Signature | 54ea681fed566566c778a9aa1608589cfb34e235c4f326709d20cc00c132bb7b | 签名字符串. | ### 请求体结构 | **属性** | **类型** | **描述** | **示例** | | ------- | ------ | ------------------------- | -------------------- | | id | uint64 | 事件 id | 545440011265267736 | | type | string | 事件类型 | payment.success | | created | string | 创建时间 | 2025-07-01T10:25:25Z | | data | object | 具体事件的业务对象,事件类型不同会有不同的数据结构 | | | **属性** | **类型** | **描述** | **示例** | | ------- | ------ | ------------------------- | -------------------- | | id | string | 事件 id | 545440011265267736 | | type | string | 事件类型 | payment.success | | created | string | 创建时间 | 2025-07-01T10:25:25Z | | data | object | 具体事件的业务对象,事件类型不同会有不同的数据结构 | | ## 事件处理规范 ### 可靠性验证 接收事件前需通过以下步骤验证请求合法性: 1. **提取参数**:从请求头获取 X-Timestamp 时间戳(记为`timestamp`),并获取原始请求体内容(记为`body`); 2. **构造签名原串**:格式为`${timestamp}.${body}`; 3. **计算签名**:使用 Subotiz 分配的 `API Key` 作为密钥,通过 HMAC-SHA256 算法计算签名值; 示例代码: GO ```go theme={null} // 计算签名 func CalcSignature(timestamp int64, body []byte, secret string) string { mac := hmac.New(sha256.New, []byte(secret)) mac.Write([]byte(fmt.Sprintf("%d", timestamp))) mac.Write([]byte(".")) mac.Write(body) return hex.EncodeToString(mac.Sum(nil)) } ``` 4. **比对验证**:将计算得到的签名与请求头中的 X-Signature 值比对,一致则为合法请求。 ### 密钥轮换期间的处理 发起密钥轮换后,Subotiz 在**过渡期内会使用旧密钥**对 Webhook 请求进行签名;旧密钥过期后自动切换至新密钥。 **建议在过渡期内,接收端同时支持新旧两个密钥验签**,处理流程如下: 1. 先使用**旧密钥**计算签名,与 X-Signature 比对; 2. 若旧密钥验签失败,再使用**新密钥**重新验签; 3. 两者均失败时,视为非法请求拒绝处理。 这样可确保密钥切换过渡期间 Webhook 事件不丢失。 ## 处理要求 * **幂等性**:基于事件 id(唯一标识)实现重复事件的幂等处理,避免重复操作; * **事件过滤**:根据事件 type 字段识别关注的事件类型,非关注类型直接返回 200 状态码; * **顺序无关性**:系统不保证事件顺序,关键业务需通过 API 主动查询同步最新状态。 ## 响应与重试机制 * **成功响应**:事件处理完成后需返回 HTTP 200 状态码,标识事件处理成功; * **失败重试**:若响应状态码非 200 或超时,系统将在 48 小时内执行 16 次退避重试(起始间隔时间为 1 min,每次间隔时间翻倍,最大间隔 4 小时)。 # 发票 Source: https://docs.subotiz.com/zh/webhook/invoice ## 事件列表 | **事件名称** | **事件类型** | **触发时机** | **通知数据结构** | | :------- | :---------------------- | :-------------------------------- | :----------------------------- | | 账单支付成功 | invoice.paid | 当订阅产生的交易单支付成功才会通知,用于获取续订支付成功相关信息。 | [Invoice](/zh/webhook/invoice) | | 账单支付失败 | invoice.payment\_failed | 当订阅产生的交易单支付失败才会通知,用于获取续订支付失败相关信息。 | [Invoice](/zh/webhook/invoice) | | 账单退款 | invoice.refunded | 当订阅产生的交易单退款成功时通知,用于获取订阅退款信息 | [Invoice](/zh/webhook/invoice) | ## 事件对象 | **属性** | **类型** | **描述** | **示例** | | --------------------- | ------------------ | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | | id | uint64 | 账单唯一标识 | 529582021580696491 | | subscription\_id | uint64 | 所属订阅计划的 ID | 529582012596497323 | | customer\_id | string | Subotiz 平台顾客唯一标识 | 529582012424532946 | | sub\_merchant\_id | string | 商户ID | 123061 | | amount | string | 账单金额 | 0 | | currency | string | 币种 | USD | | status | string | 发票状态:
open:初始化
success:已支付
failed:支付失败
refunded:全额退款
partially\_refunded:部分退款 | success | | paid\_at | string | 支付时间 | 2025-07-01T08:49:53Z | | invoice\_type | string | 发票类型:
initial:首次支付
trial:试用期
renewal:续费
refund:退款 | trial | | created\_at | string | 创建时间 | 2025-07-01T08:49:50Z | | updated\_at | string | 更新时间 | 2025-07-01T08:49:50Z | | cycle\_index | Int | 订阅周期序号,当为试用期时,周期为0。 | 1 | | cycle\_start | string | 周期开始时间 | 2025-07-01T08:49:50Z | | cycle\_end | string | 周期结束时间 | 2025-07-01T08:49:50Z | | order\_id | string | 外部订单 ID | order\_123456 | | refund\_id | string | 退款id | 20250807542984743692553415 | | trade\_id | string | 交易单 id | 572677233903157186 | | original\_invoice\_id | string | invoice.refunded 事件中有值,关联退款的正向单 | 572677233903157182 | | metadata | map\[string]string | 发票上附带的元数据 | `{
"key": "value"
}` | | subscription\_data | SubscriptionData | 发票所属的订阅数据 | `{
"metadata": {
"key": "value"
}
}` | | discounts | Discounts | 发票上的折扣,包括此发票的所有折扣信息 | `{"current_period":[{"discount_id":"562218353725276866","discount_amount":"5.00","discount_code":"555"}]}` | ### SubscriptionData | **属性** | **类型** | **描述** | | | -------- | ------------------ | --------- | ---------------------------- | | metadata | map\[string]string | 订阅上附带的元数据 | `{
"key": "value"
}` | ### Discounts | 属性名 | 类型 | 描述 | | --------------- | ------------------------ | --------- | | current\_period | CurrentPeriodDiscount\[] | 当前时期的折扣详情 | ### CurrentPeriodDiscount | 属性名 | 类型 | 描述 | | ---------------- | ------ | -------- | | discount\_id | string | 折扣的唯一标识符 | | discount\_amount | string | 折扣金额 | | discount\_code | string | 使用的折扣代码 | ## 示例数据 ```json invoice.paid theme={null} { "id": 572677256258790436, "type": "invoice.paid", "created": "2025-10-28T06:54:56Z", "data": { "subscription_id": 572677251968024511, "order_id": "order_1761634475936438746", "sub_merchant_id": "2816433", "cycle_start": "2025-10-28T06:54:00Z", "status": "success", "invoice_type": "initial", "cycle_index": 1, "amount": "30", "updated_at": "2025-10-28T06:54:56Z", "trade_id": "572677233903157186", "id": 572677251968040895, "cycle_end": "2025-10-28T07:25:00Z", "customer_id": "547766341013094363", "currency": "USD", "paid_at": "2025-10-28T06:54:55Z", "created_at": "2025-10-28T06:54:56Z", "refund_id": "20250807542984743692553415" } } ``` ```json invoice.payment_failed theme={null} { "id": 572670998545971191, "type": "invoice.payment_failed", "created": "2025-10-28T06:30:04Z", "data": { "sub_merchant_id": "2816514", "subscription_id": 570837058398981116, "cycle_start": "2025-10-26T05:03:00Z", "status": "failed", "customer_id": "570836074111455077", "created_at": "2025-10-26T05:20:01Z", "currency": "USD", "paid_at": null, "invoice_type": "initial", "updated_at": "2025-10-28T06:30:04Z", "id": 571928511522097676, "cycle_index": 1, "cycle_end": "2025-11-26T05:03:00Z", "amount": "199", "order_id": "order_1761195526005115801", "trade_id": "571928589088117469" } } ``` ```json invoice.refunded theme={null} { "id": 583625562099034794, "type": "invoice.refunded", "created": "2025-11-27T11:59:37Z", "data": { "order_id": "order_1764230244388418776", "refund_id": "20251127583625544336174077", "original_invoice_id": "583564651824957126", "subscription_id": 583564651824940742, "cycle_start": "", "status": "refunded", "paid_at": null, "updated_at": "2025-11-27T11:59:36Z", "cycle_index": 0, "cycle_end": "", "customer_id": "537465921338359803", "amount": "2", "currency": "USD", "invoice_type": "refund", "id": 583602027389549049, "sub_merchant_id": "100010", "created_at": "2025-11-27T11:59:36Z" } } ``` # 发票 Source: https://docs.subotiz.com/zh/webhook/invoice-2 ## 事件列表 | **事件名称** | **事件类型** | **触发时机** | **通知数据结构** | | :------- | :------------------------- | :-------------------------------- | :----------------------------- | | 账单支付成功 | v2.invoice.paid | 当订阅产生的交易单支付成功才会通知,用于获取续订支付成功相关信息。 | [Invoice](/zh/webhook/invoice) | | 账单支付失败 | v2.invoice.payment\_failed | 当订阅产生的交易单支付失败才会通知,用于获取续订支付失败相关信息。 | [Invoice](/zh/webhook/invoice) | | 账单退款 | v2.invoice.refunded | 当订阅产生的交易单退款成功时通知,用于获取订阅退款信息 | [Invoice](/zh/webhook/invoice) | ## 事件对象 | **属性** | **类型** | **描述** | **示例** | | --------------------- | ------------------ | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | | id | string | 账单唯一标识 | 529582021580696491 | | subscription\_id | string | 所属订阅计划的 ID | 529582012596497323 | | customer\_id | string | Subotiz 平台顾客唯一标识 | 529582012424532946 | | sub\_merchant\_id | string | 商户ID | 123061 | | amount | string | 账单金额 | 0 | | currency | string | 币种 | USD | | status | string | 发票状态:
open:初始化
success:已支付
failed:支付失败
refunded:全额退款
partially\_refunded:部分退款 | success | | paid\_at | string | 支付时间 | 2025-07-01T08:49:53Z | | invoice\_type | string | 发票类型:
initial:首次支付
trial:试用期
renewal:续费
refund:退款 | trial | | created\_at | string | 创建时间 | 2025-07-01T08:49:50Z | | updated\_at | string | 更新时间 | 2025-07-01T08:49:50Z | | cycle\_index | string | 订阅周期序号,当为试用期时,周期为0。 | 1 | | cycle\_start | string | 周期开始时间 | 2025-07-01T08:49:50Z | | cycle\_end | string | 周期结束时间 | 2025-07-01T08:49:50Z | | order\_id | string | 外部订单 ID | order\_123456 | | refund\_id | string | 退款id | 20250807542984743692553415 | | trade\_id | string | 交易单 id | 572677233903157186 | | original\_invoice\_id | string | invoice.refunded 事件中有值,关联退款的正向单 | 572677233903157182 | | metadata | map\[string]string | 发票上附带的元数据 | `{
"key": "value"
}` | | subscription\_data | SubscriptionData | 发票所属的订阅数据 | `{
"metadata": {
"key": "value"
}
}` | | discounts | Discounts | 发票上的折扣,包括此发票的所有折扣信息 | `{"current_period":[{"discount_id":"562218353725276866","discount_amount":"5.00","discount_code":"555"}]}` | ### SubscriptionData | **属性** | **类型** | **描述** | | | -------- | ------------------ | --------- | ---------------------------- | | metadata | map\[string]string | 订阅上附带的元数据 | `{
"key": "value"
}` | ### Discounts | 属性名 | 类型 | 描述 | | --------------- | ------------------------ | --------- | | current\_period | CurrentPeriodDiscount\[] | 当前时期的折扣详情 | ### CurrentPeriodDiscount | 属性名 | 类型 | 描述 | | ---------------- | ------ | -------- | | discount\_id | string | 折扣的唯一标识符 | | discount\_amount | string | 折扣金额 | | discount\_code | string | 使用的折扣代码 | ## 示例数据 ```json v2.invoice.paid theme={null} { "id": "572677256258790436", "type": "v2.invoice.paid", "created": "2025-10-28T06:54:56Z", "data": { "subscription_id": "572677251968024511", "order_id": "order_1761634475936438746", "sub_merchant_id": "2816433", "cycle_start": "2025-10-28T06:54:00Z", "status": "success", "invoice_type": "initial", "cycle_index": "1", "amount": "30", "updated_at": "2025-10-28T06:54:56Z", "trade_id": "572677233903157186", "id": "572677251968040895", "cycle_end": "2025-10-28T07:25:00Z", "customer_id": "547766341013094363", "currency": "USD", "paid_at": "2025-10-28T06:54:55Z", "created_at": "2025-10-28T06:54:56Z", "refund_id": "20250807542984743692553415" } } ``` ```json v2.invoice.payment_failed theme={null} { "id": "572670998545971191", "type": "v2.invoice.payment_failed", "created": "2025-10-28T06:30:04Z", "data": { "sub_merchant_id": "2816514", "subscription_id": "570837058398981116", "cycle_start": "2025-10-26T05:03:00Z", "status": "failed", "customer_id": "570836074111455077", "created_at": "2025-10-26T05:20:01Z", "currency": "USD", "paid_at": null, "invoice_type": "initial", "updated_at": "2025-10-28T06:30:04Z", "id": "571928511522097676", "cycle_index": "1", "cycle_end": "2025-11-26T05:03:00Z", "amount": "199", "order_id": "order_1761195526005115801", "trade_id": "571928589088117469" } } ``` ```json v2.invoice.refunded theme={null} { "id": "583625562099034794", "type": "v2.invoice.refunded", "created": "2025-11-27T11:59:37Z", "data": { "order_id": "order_1764230244388418776", "refund_id": "20251127583625544336174077", "original_invoice_id": "583564651824957126", "subscription_id": "583564651824940742", "cycle_start": "", "status": "refunded", "paid_at": null, "updated_at": "2025-11-27T11:59:36Z", "cycle_index": "0", "cycle_end": "", "customer_id": "537465921338359803", "amount": "2", "currency": "USD", "invoice_type": "refund", "id": "583602027389549049", "sub_merchant_id": "100010", "created_at": "2025-11-27T11:59:36Z" } } ``` # 退款 Source: https://docs.subotiz.com/zh/webhook/refund-1 ## 事件列表 | **事件名称** | **事件类型** | **触发时机** | **通知数据结构** | | :------- | :---------------- | :------- | :----------------------------- | | 退款成功 | refunds.succeeded | 退款成功时 | [Refund](/zh/webhook/refund-1) | | 退款失败 | refunds.failed | 退款失败时 | [Refund](/zh/webhook/refund-1) | ## 事件对象 | **属性** | **类型** | **描述** | | --------------- | -------------------- | ------------------------------------------------------------ | | access\_no | string | 分配的接入方编号 | | merchant\_id | string | 接入方的商户号 | | refund\_id | string | 退款单 ID | | trade\_id | string | 交易单 ID | | currency | string | 金额对应的交易币种 | | reason | string | 退款原因 | | refund\_amount | string | 退款金额 | | refund\_status | string | 退款状态
pending: 处理中
failed:退款失败
succeeded: 退款成功 | | metadata | map\ | 透传的元数据,key 长度不超过 40 字节,value 长度不超过 500 字节,JSON编码后 ≤ 1024字节 | | failure\_reason | string | 失败原因 | | ref\_arn | string | 发卡行侧返回退款凭证 | | finished\_at | string | 退款完成时间 | ## 示例数据 ```json refunds.succeeded theme={null} { "id": 572683623191290916, "type": "refunds.succeeded", "created": "2025-10-28T07:20:15Z", "data": { "reason": "", "access_no": "77d52a21dc032b4", "merchant_id": "2816433", "refund_id": "20251028572683602265931714", "currency": "USD", "failure_reason": null, "ref_arn": "", "finished_at": "2025-10-28T07:20:15Z", "trade_id": "572679783406649282", "refund_amount": "15.57", "refund_status": "succeeded", "metadata": null } } ``` ```json refunds.failed theme={null} { "id": 550627286320154211, "type": "refunds.failed", "created": "2025-08-28T10:36:15Z", "data": { "access_no": "78f3c0d56803a11", "merchant_id": "2816411", "currency": "USD", "metadata": null, "failure_reason": { "code": "100999", "message": "insufficient account balance" }, "ref_arn": "", "refund_id": "20250828550582487160487110", "trade_id": "549527688117761146", "reason": "", "refund_amount": "39.00", "refund_status": "failed", "finished_at": null } } ``` # 退款 Source: https://docs.subotiz.com/zh/webhook/refund-2 ## 事件列表 | **事件名称** | **事件类型** | **触发时机** | **通知数据结构** | | :------- | :------------------- | :------- | :------------------------------ | | 退款成功 | v2.refunds.succeeded | 退款成功时 | [Refund](/zh/api/refund-object) | | 退款失败 | v2.refunds.failed | 退款失败时 | [Refund](/zh/api/refund-object) | ## 事件对象 | **属性** | **类型** | **描述** | | --------------- | -------------------- | ------------------------------------------------------------ | | access\_no | string | 分配的接入方编号 | | merchant\_id | string | 接入方的商户号 | | refund\_id | string | 退款单 ID | | trade\_id | string | 交易单 ID | | currency | string | 金额对应的交易币种 | | reason | string | 退款原因 | | refund\_amount | string | 退款金额 | | refund\_status | string | 退款状态
pending: 处理中
failed:退款失败
succeeded: 退款成功 | | metadata | map\ | 透传的元数据,key 长度不超过 40 字节,value 长度不超过 500 字节,JSON编码后 ≤ 1024字节 | | failure\_reason | string | 失败原因 | | ref\_arn | string | 发卡行侧返回退款凭证 | | finished\_at | string | 退款完成时间 | ## 示例数据 ```json v2.refunds.succeeded theme={null} { "id": "572683623191290916", "type": "v2.refunds.succeeded", "created": "2025-10-28T07:20:15Z", "data": { "reason": "", "access_no": "77d52a21dc032b4", "merchant_id": "2816433", "refund_id": "20251028572683602265931714", "currency": "USD", "failure_reason": null, "ref_arn": "", "finished_at": "2025-10-28T07:20:15Z", "trade_id": "572679783406649282", "refund_amount": "15.57", "refund_status": "succeeded", "metadata": null } } ``` ```json v2.refunds.failed theme={null} { "id": "550627286320154211", "type": "v2.refunds.failed", "created": "2025-08-28T10:36:15Z", "data": { "access_no": "78f3c0d56803a11", "merchant_id": "2816411", "currency": "USD", "metadata": null, "failure_reason": { "code": "100999", "message": "insufficient account balance" }, "ref_arn": "", "refund_id": "20250828550582487160487110", "trade_id": "549527688117761146", "reason": "", "refund_amount": "39.00", "refund_status": "failed", "finished_at": null } } ``` # 订阅 Source: https://docs.subotiz.com/zh/webhook/subscription-1 ## 事件列表 | **事件名称** | **事件类型** | **触发时机** | **通知数据结构** | | --------- | ------------------------------------ | -------------- | ------------------------------------------ | | 试用期即将到期通知 | subscription.trial\_period\_expiring | 试用期剩余时间小于 3 天时 | [Subscription](/zh/webhook/subscription-1) | | 首次订阅通知 | subscription.first | 订阅首次生效时 | [Subscription](/zh/webhook/subscription-1) | | 终止订阅通知 | subscription.canceled | 主动终止订阅时 | [Subscription](/zh/webhook/subscription-1) | | 订阅价格变更 | subscription.price\_changed | 订阅价格变更时 | [Subscription](/zh/webhook/subscription-1) | ## 事件对象 | **属性** | **类型** | **描述** | **示例** | | ---------------------- | ------------------ | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | id | uint64 | 订阅计划唯一标识 | 516816656060660549 | | customer\_id | string | Subotiz 平台顾客唯一标识 | 516816656060660549 | | sub\_merchant\_id | string | 商户唯一标识 | 123061 | | status | string | 订阅业务状态:init - 待生效trial - 试用期active - 生效中canceled - 已终止incomplete - 未完成 | init | | price\_id | uint64 | 商品定价的唯一标识 | 516816656060660549 | | total\_cycles | int | 总周期数,0表示无限期 | 0 | | current\_period\_start | string | 当前计费周期开始时间 | 2025-07-01T13:40:25Z | | current\_period\_end | string | 当前计费周期结束时间 | 2025-07-01T13:40:25Z | | next\_invoice\_date | string | 下一次收费日期 | 2025-07-01T13:40:25Z | | created\_at | string | 创建时间 | 2025-07-01T13:40:25Z | | updated\_at | string | 更新时间 | 2025-07-01T13:40:25Z | | order\_id | string | 接入方订单 ID | order\_123456 | | cycle\_index | int | 当前周期数 | 1 | | next\_price\_info | NextPriceInfo | 价格变更信息 | `{
"price_id": "516816656060660549",
"expected_effective_date": "2025-09-30T15:33:00Z",
"proration":"none"
}` | | cancel\_at | string | 订阅实际取消时间 | 2025-07-01T13:40:25Z | | cancel\_reason | string | 订阅取消原因 | Customer cancellation | | source\_trade\_id | string | 订阅的来源交易单 | 516816656060660549 | | metadata | map\[string]string | 订阅上附带的元数据 | `{
"key": "value"
}` | ### NextPriceInfo | **属性** | **类型** | **描述** | **示例** | | ------------------------- | ------ | ---------------------------------------------- | --------------------------------------------------------------------------- | | price\_id | string | 价格变更之后的定价 ID | 516816656060660549 | | expected\_effective\_date | string | 预计生效时间 | 2025-09-30T15:33:00Z | | proration | string | 结算类型
none: 无需结算分摊额
immediate:立即结算分摊额 | immediate | | change\_invoice\_id | string | 由订阅变更产生的 invoice 的 id | 516816656060660541 | | change\_refund\_ids | string | 由订阅变更产生的退款单id,可关联 invoice.refund\_id 字段 | `[
"20250807542984743692553411"
"20250807542984743692553415"
]` | ## Subscription 生命周期 ```mermaid theme={null} stateDiagram-v2 [*] --> Trial : 下单成功享受试用期 [*] --> Active : 下单不可享受试用期/无试用期 Trial --> Active : 先付费:试用期结束后扣款成功 Trial --> Active : 后付费:试用期结束后直接激活首期 Trial --> PastDue : 试用期结束首次扣款失败 Trial --> Canceled : 取消订阅 Active --> Paused : 暂停订阅 Active --> PastDue : 续订失败仍在重试 Active --> Canceled : 取消订阅 Paused --> Active : 重启订阅 Paused --> Canceled : 取消订阅 PastDue --> Active : 重试收款成功 PastDue --> Unpaid : 重试收款达到最大次数/宽限期到期 PastDue --> Canceled : 取消订阅/宽限期到期 Unpaid --> Canceled : 取消订阅 Unpaid --> Canceled : 到了宽限期/取消订阅 Unpaid --> Unpaid : 到了宽限期/标记为未支付 Unpaid --> Active : 宽限期内修改支付方式支付成功 Canceled --> [*] ``` ### 动作对应的事件 * **有试用期 & 首次订阅:** `subscription.first` 事件,且事件对象中的 `subscription.status = trial` * **首次订阅**: `subscription.first `事件,且事件对象中的 `subscription.status = active` * **终止订阅**:`subscription.canceled` 事件 * **试用期结束 & 支付成功:** `invoice.paid` 事件,且事件对象中的 `invoice.invoice_type = initial` * **续订支付成功**:`invoice.paid` 事件,且事件对象中的 `invoice.invoice_type = renewal` * **支付失败**:`invoice.payment_failed` 事件 ## 示例数据 ```json subscription.first theme={null} { "id": 583564652533787306, "type": "subscription.first", "created": "2025-11-27T07:57:35Z", "data": { "sub_merchant_id": "100010", "customer_id": "537465921338359803", "total_cycles": 0, "current_period_start": "2025-11-27T07:57:00Z", "next_invoice_date": "2025-11-27T13:08:00Z", "cancel_at": null, "created_at": "2025-11-27T07:57:35Z", "id": 583564651824940742, "next_price_info": null, "cancel_reason": "", "order_id": "order_1764230244388418776", "cycle_index": 1, "current_period_end": "2025-11-27T13:07:00Z", "price_id": 582401938335740273, "updated_at": "2025-11-27T07:57:35Z", "source_trade_id": "583564647529987790", "status": "active" } } ``` ```json subscription.canceled theme={null} { "id": 572682701203579940, "type": "subscription.canceled", "created": "2025-10-28T07:16:35Z", "data": { "price_id": 572349625697058751, "created_at": "2025-10-28T06:54:56Z", "updated_at": "2025-10-28T07:16:35Z", "next_price_info": null, "current_period_start": "2025-10-28T06:54:00Z", "current_period_end": "2025-10-28T07:25:00Z", "next_invoice_date": "2025-10-28T07:26:00Z", "cancel_at": "2025-10-28T07:16:00Z", "id": 572677251968024511, "total_cycles": 0, "cycle_index": 1, "cancel_reason": "cancel", "order_id": "order_1761634475936438746", "sub_merchant_id": "2816433", "status": "canceled", "customer_id": "547766341013094363", "source_trade_id": "572677233903157186" } } ``` ```json subscription.trial_period_expiring theme={null} { "id": 572670992330012613, "type": "subscription.trial_period_expiring", "created": "2025-10-28T06:30:01Z", "data": { "id": 572664015193371988, "customer_id": "567609424412263252", "price_id": 563378244649234223, "current_period_start": "2025-10-28T06:02:00Z", "updated_at": "2025-10-28T06:02:20Z", "total_cycles": 0, "current_period_end": "2025-10-31T06:02:00Z", "cancel_at": null, "created_at": "2025-10-28T06:02:20Z", "source_trade_id": "572663537512178624", "sub_merchant_id": "1216433", "status": "trial", "next_invoice_date": "2025-10-31T06:03:00Z", "cancel_reason": "", "cycle_index": 0, "order_id": "order_1761631220208894185" } } ``` ```json subscription.price_changed theme={null} { "id": 583570323576728234, "type": "subscription.price_changed", "created": "2025-11-27T08:20:07Z", "data": { "id": 583564651824940742, "price_id": 582401938335740273, "cycle_index": 1, "current_period_end": "2025-11-27T13:07:00Z", "next_invoice_date": "2025-11-27T13:08:00Z", "cancel_at": null, "total_cycles": 0, "cancel_reason": "", "created_at": "2025-11-27T07:57:35Z", "source_trade_id": "583564647529987790", "sub_merchant_id": "100010", "status": "active", "customer_id": "537465921338359803", "current_period_start": "2025-11-27T07:57:00Z", "next_price_info": { "price_id": 582402035266105713, "expected_effective_date": "2025-11-27T08:20:00Z", "proration": "immediate", "change_invoice_id": "583570320951084742", "change_refund_ids": null }, "updated_at": "2025-11-27T07:57:35Z", "order_id": "order_1764230244388418776" } } ``` # 订阅 Source: https://docs.subotiz.com/zh/webhook/subscription-2 ## 事件列表 | **事件名称** | **事件类型** | **触发时机** | **通知数据结构** | | -------- | --------------------------------------- | -------------- | ------------------------------------------ | | 试用期即将到期 | v2.subscription.trial\_period\_expiring | 试用期剩余时间小于 3 天时 | [Subscription](/zh/webhook/subscription-2) | | 首次订阅 | v2.subscription.first | 订阅首次生效时 | [Subscription](/zh/webhook/subscription-2) | | 终止订阅 | v2.subscription.canceled | 主动终止订阅时 | [Subscription](/zh/webhook/subscription-2) | | 订阅价格变更 | v2.subscription.price\_changed | 订阅价格变更时 | [Subscription](/zh/webhook/subscription-2) | | 订阅暂停 | v2.subscription.paused | 订阅暂停时通知 | [Subscription](/zh/webhook/subscription-2) | | 订阅重启 | v2.subscription.resumed | 订阅重启时通知 | [Subscription](/zh/webhook/subscription-2) | | 订阅逾期 | v2.subscription.past\_due | 订阅逾期时通知 | [Subscription](/zh/webhook/subscription-2) | | 订阅未支付 | v2.subscription.unpaid | 订阅未支付时通知 | [Subscription](/zh/webhook/subscription-2) | | 撤回取消订阅 | v2.subscription.cancellation\_revoked | 撤回取消订阅时通知 | [Subscription](/zh/webhook/subscription-2) | | 请求取消订阅 | v2.subscription.cancellation\_requested | 请求取消订阅时通知 | [Subscription](/zh/webhook/subscription-2) | | 固定期限变更 | v2.subscription.fixed\_term\_updated | 订阅固定期限变更时通知 | [Subscription](/zh/webhook/subscription-2) | | 撤回价格变更 | v2.subscription.price\_change\_revoked | 撤回订阅价格变更时通知 | [Subscription](/zh/webhook/subscription-2) | ## 事件对象 | **属性** | **类型** | **描述** | **示例** | | --------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | id | string | 订阅计划唯一标识 | 516816656060660549 | | customer\_id | string | Subotiz 平台顾客唯一标识 | 516816656060660549 | | sub\_merchant\_id | string | 商户唯一标识 | 123061 | | status | string | 订阅业务状态:init - 待生效trial - 试用期active - 生效中canceled - 已终止incomplete - 未完成 | init | | price\_id | string | 商品定价的唯一标识 | 516816656060660549 | | total\_cycles | string | 总周期数,0表示无限期 | 0 | | current\_period\_start | string | 当前计费周期开始时间 | 2025-07-01T13:40:25Z | | current\_period\_end | string | 当前计费周期结束时间 | 2025-07-01T13:40:25Z | | next\_invoice\_date | string | 下一次收费日期。非固定周期扣费(如按用量阈值扣费)时,返回的是描述性文字而非时间戳。 | 2025-07-01T13:40:25Z | | created\_at | string | 创建时间 | 2025-07-01T13:40:25Z | | updated\_at | string | 更新时间 | 2025-07-01T13:40:25Z | | order\_id | string | 接入方订单 ID | order\_123456 | | cycle\_index | string | 当前周期数 | 1 | | next\_price\_info | NextPriceInfo | 价格变更信息 | `{
"price_id": "516816656060660549",
"expected_effective_date": "2025-09-30T15:33:00Z",
"proration":"none"
}` | | cancel\_at | string | 订阅实际取消时间 | 2025-07-01T13:40:25Z | | cancel\_reason | string | 订阅取消原因 | Customer cancellation | | source\_trade\_id | string | 订阅的来源交易单 | 516816656060660549 | | metadata | map\[string]string | 订阅上附带的元数据 | `{
"key": "value"
}` | | paused\_at | string | 订阅暂停的时间 | 2025-07-01T13:40:25Z | | initiate\_cancel\_at | string | 发起取消订阅的时间 | 2025-07-01T13:40:25Z | | expected\_cancel\_at | string | 预期取消订阅的时间 | 2025-07-01T13:40:25Z | | price\_version\_id | string | 商品定价版本唯一标识 | 585661231470226668 | | first\_source\_channel | string | 首次创建结账会话的来源渠道 | | | last\_source\_channel | string | 最近一次访问结账会话的来源渠道 | | | is\_renewable | bool | 固定期限到期后是否自动转为长期订阅 | false | | end\_at | string | 订阅结束时间。空字符串表示长期订阅(无结束时间) | | | current\_period\_num | string | 当前期数 | 1 | | previous\_fixed\_term\_info | object | 变更前的固定期限信息。仅在 `v2.subscription.fixed_term_updated` 事件中存在。包含子字段:`previous_fixed_term` (string)、`previous_is_renewable` (bool)、`previous_end_at` (string) | `null` | ### NextPriceInfo | **属性** | **类型** | **描述** | **示例** | | ------------------------- | ------ | -------------------------------------------------------------- | --------------------------------------------------------------------------- | | price\_id | string | 价格变更之后的定价 ID | 516816656060660549 | | effective\_type | string | 价格变更的生效时机
immediate:立即生效
end\_of\_period:当前计费周期结束时生效 | immediate | | expected\_effective\_date | string | 预计生效时间 | 2025-09-30T15:33:00Z | | proration | string | 结算类型
none: 无需结算分摊额
immediate:立即结算分摊额 | immediate | | change\_invoice\_id | string | 由订阅变更产生的 invoice 的 id | 516816656060660541 | | change\_refund\_ids | string | 由订阅变更产生的退款单id,可关联 invoice.refund\_id 字段 | `[
"20250807542984743692553411"
"20250807542984743692553415"
]` | ## Subscription 生命周期 ```mermaid theme={null} stateDiagram-v2 [*] --> Trial : 下单成功享受试用期 [*] --> Active : 下单不可享受试用期/无试用期 Trial --> Active : 先付费:试用期结束后扣款成功 Trial --> Active : 后付费:试用期结束后直接激活首期 Trial --> PastDue : 试用期结束首次扣款失败 Trial --> Canceled : 取消订阅 Active --> Paused : 暂停订阅 Active --> PastDue : 续订失败仍在重试 Active --> Canceled : 取消订阅 Paused --> Active : 重启订阅 Paused --> Canceled : 取消订阅 PastDue --> Active : 重试收款成功 PastDue --> Unpaid : 重试收款达到最大次数/宽限期到期 PastDue --> Canceled : 取消订阅/宽限期到期 Unpaid --> Canceled : 取消订阅 Unpaid --> Canceled : 到了宽限期/取消订阅 Unpaid --> Unpaid : 到了宽限期/标记为未支付 Unpaid --> Active : 宽限期内修改支付方式支付成功 Canceled --> [*] ``` ### 动作对应的事件 * **有试用期 & 首次订阅:** `v2.subscription.first` 事件,且事件对象中的 `subscription.status = trial` * **首次订阅**: `v2.subscription.first `事件,且事件对象中的 `subscription.status = active` * **终止订阅**:`v2.subscription.canceled` 事件 * **试用期结束 & 支付成功:** `v2.invoice.paid` 事件,且事件对象中的 `invoice.invoice_type = initial` * **续订支付成功**:`v2.invoice.paid` 事件,且事件对象中的 `invoice.invoice_type = renewal` * **支付失败**:`v2.invoice.payment_failed` 事件 ## 示例数据 ```json v2.subscription.first theme={null} { "id": "583564652533787306", "type": "v2.subscription.first", "created": "2025-11-27T07:57:35Z", "data": { "sub_merchant_id": "100010", "customer_id": "537465921338359803", "total_cycles": "0", "current_period_start": "2025-11-27T07:57:00Z", "next_invoice_date": "2025-11-27T13:08:00Z", "cancel_at": null, "created_at": "2025-11-27T07:57:35Z", "id": "583564651824940742", "next_price_info": null, "cancel_reason": "", "order_id": "order_1764230244388418776", "cycle_index": "1", "current_period_end": "2025-11-27T13:07:00Z", "price_id": "582401938335740273", "updated_at": "2025-11-27T07:57:35Z", "source_trade_id": "583564647529987790", "status": "active" } } ``` ```json v2.subscription.canceled theme={null} { "id": "572682701203579940", "type": "v2.subscription.canceled", "created": "2025-10-28T07:16:35Z", "data": { "price_id": "572349625697058751", "created_at": "2025-10-28T06:54:56Z", "updated_at": "2025-10-28T07:16:35Z", "next_price_info": null, "current_period_start": "2025-10-28T06:54:00Z", "current_period_end": "2025-10-28T07:25:00Z", "next_invoice_date": "2025-10-28T07:26:00Z", "cancel_at": "2025-10-28T07:16:00Z", "id": "572677251968024511", "total_cycles": "0", "cycle_index": "1", "cancel_reason": "cancel", "order_id": "order_1761634475936438746", "sub_merchant_id": "2816433", "status": "canceled", "customer_id": "547766341013094363", "source_trade_id": "572677233903157186" } } ``` ```json v2.subscription.trial_period_expiring theme={null} { "id": "572670992330012613", "type": "v2.subscription.trial_period_expiring", "created": "2025-10-28T06:30:01Z", "data": { "id": "572664015193371988", "customer_id": "567609424412263252", "price_id": "563378244649234223", "current_period_start": "2025-10-28T06:02:00Z", "updated_at": "2025-10-28T06:02:20Z", "total_cycles": "0", "current_period_end": "2025-10-31T06:02:00Z", "cancel_at": null, "created_at": "2025-10-28T06:02:20Z", "source_trade_id": "572663537512178624", "sub_merchant_id": "1216433", "status": "trial", "next_invoice_date": "2025-10-31T06:03:00Z", "cancel_reason": "", "cycle_index": "0", "order_id": "order_1761631220208894185" } } ``` ```json v2.subscription.price_changed theme={null} { "id": "654282672553592775", "type": "v2.subscription.price_changed", "created": "2026-07-10T11:23:00Z", "data": { "status": "active", "end_at": "", "previous_fixed_term_info": null, "current_period_start": "2026-06-10T11:23:00Z", "order_id": "test_order_00111", "next_price_info": { "proration": "none", "change_invoice_id": "", "change_refund_ids": null, "usage_invoice_id": "", "price_id": "608934085099784585", "price_version_id": "608934085099784585", "effective_type": "end_of_period", "expected_effective_date": "Charged when usage-based fees reach $20.00" }, "initiate_cancel_at": "", "customer_id": "539729972764360694", "price_version_id": "629136800761259429", "cancel_reason": "", "is_renewable": true, "created_at": "2026-06-10T11:23:32Z", "source_trade_id": "654281916278652917", "first_source_channel": "", "cycle_index": "0", "next_invoice_date": "Charged when usage-based fees reach $20.00", "updated_at": "2026-06-10T11:23:32Z", "expected_cancel_at": "", "price_id": "608933940362740418", "current_period_end": "2026-06-10T11:23:00Z", "last_source_channel": "", "id": "654282114438533136", "total_cycles": "2", "sub_merchant_id": "364861", "cancel_at": null, "paused_at": "", "current_period_num": "1" } } ``` ```json v2.subscription.paused theme={null} { "id": "603927306368453965", "type": "v2.subscription.paused", "created": "2026-01-22T12:31:30Z", "data": { "price_version_id": "585661231470226668", "cycle_index": "1", "next_price_info": null, "first_source_channel": "", "paused_at": "2026-01-22T12:31:00Z", "total_cycles": "0", "updated_at": "2026-01-22T12:31:30Z", "source_trade_id": "603889788398876633", "initiate_cancel_at": "", "expected_cancel_at": "", "id": "603889808367951518", "price_id": "585661231470226668", "current_period_start": "2026-01-22T10:02:00Z", "current_period_end": "-", "cancel_reason": "", "last_source_channel": "", "metadata": null, "sub_merchant_id": "2816433", "status": "paused", "customer_id": "541822454956310498", "next_invoice_date": "-", "cancel_at": null, "created_at": "2026-01-22T10:02:30Z", "order_id": "order_1769076135405830680" } } ``` ```json v2.subscription.resumed theme={null} { "id": "603928258563542349", "type": "v2.subscription.resumed", "created": "2026-01-22T12:35:17Z", "data": { "cancel_at": null, "price_id": "585661231470226668", "price_version_id": "585661231470226668", "total_cycles": "0", "next_invoice_date": "Charged when usage-based fees reach $20.00", "created_at": "2026-01-22T10:02:30Z", "source_trade_id": "603889788398876633", "next_price_info": null, "last_source_channel": "", "id": "603889808367951518", "cycle_index": "1", "current_period_start": "2026-01-22T10:02:00Z", "paused_at": "", "initiate_cancel_at": "", "customer_id": "541822454956310498", "current_period_end": "2026-01-22T10:10:02Z", "metadata": null, "updated_at": "2026-01-22T12:35:17Z", "order_id": "order_1769076135405830680", "first_source_channel": "", "expected_cancel_at": "", "sub_merchant_id": "2816433", "status": "active", "cancel_reason": "" } } ``` ```json v2.subscription.past_due theme={null} { "id": "604229309149746453", "type": "v2.subscription.past_due", "created": "2026-01-23T07:50:55Z", "data": { "customer_id": "541822454956310498", "total_cycles": "0", "created_at": "2026-01-23T07:44:32Z", "initiate_cancel_at": "", "first_source_channel": "", "last_source_channel": "", "current_period_start": "2026-01-23T07:44:00Z", "next_invoice_date": "Charged when usage-based fees reach $20.00", "cancel_at": null, "cancel_reason": "", "source_trade_id": "604217431497390041", "metadata": null, "expected_cancel_at": "", "price_id": "585661231470226668", "order_id": "order_1769154252871463378", "paused_at": "", "updated_at": "2026-01-23T07:50:55Z", "next_price_info": null, "id": "604217479710908319", "sub_merchant_id": "2816433", "status": "past_due", "price_version_id": "585661231470226668", "cycle_index": "1", "current_period_end": "2026-01-23T07:50:01Z" } } ``` ```json v2.subscription.unpaid theme={null} { "id": "604230206634333461", "type": "v2.subscription.unpaid", "created": "2026-01-23T08:30:08Z", "data": { "expected_cancel_at": "", "sub_merchant_id": "2816433", "price_id": "600585046541216169", "cycle_index": "1", "cancel_reason": "", "first_source_channel": "", "source_trade_id": "603856934524690415", "customer_id": "541822454956310498", "total_cycles": "0", "cancel_at": null, "created_at": "2026-01-22T07:52:13Z", "order_id": "order_1769068305139700301", "price_version_id": "600585046541216169", "next_invoice_date": "2026-01-22T08:16:00Z", "next_price_info": null, "metadata": null, "paused_at": "", "last_source_channel": "", "initiate_cancel_at": "", "id": "603857024144389364", "status": "unpaid", "current_period_start": "2026-01-22T07:52:00Z", "current_period_end": "2026-01-22T09:02:00Z", "updated_at": "2026-01-23T08:30:08Z" } } ``` ```json v2.subscription.cancellation_revoked theme={null} { "id": "603909739125935437", "type": "v2.subscription.cancellation_revoked", "created": "2026-01-22T11:21:41Z", "data": { "current_period_end": "2026-01-22T12:30:00Z", "next_invoice_date": "2026-01-22T12:31:00Z", "cancel_reason": "", "updated_at": "2026-01-22T11:21:41Z", "order_id": "order_1769080829192130135", "paused_at": "", "total_cycles": "0", "current_period_start": "2026-01-22T11:20:00Z", "sub_merchant_id": "2816433", "expected_cancel_at": "", "customer_id": "541822454956310498", "price_id": "594101578214976042", "cycle_index": "1", "cancel_at": null, "source_trade_id": "603909473999796185", "next_price_info": null, "id": "603909515594702494", "status": "active", "metadata": null, "first_source_channel": "", "last_source_channel": "", "initiate_cancel_at": "", "price_version_id": "599077413057465741", "created_at": "2026-01-22T11:20:48Z" } } ``` ```json v2.subscription.cancellation_requested theme={null} { "id": "605206977064209227", "type": "v2.subscription.cancellation_requested", "created": "2026-01-26T01:16:27Z", "data": { "paused_at": "", "expected_cancel_at": "2026-01-26T01:16:00Z", "sub_merchant_id": "2816433", "total_cycles": "0", "current_period_start": "2026-01-22T13:05:00Z", "source_trade_id": "603889788398876633", "first_source_channel": "", "last_source_channel": "", "price_id": "597247070985830078", "current_period_end": "2026-01-26T01:16:27Z", "cancel_at": "2026-01-26T01:16:00Z", "updated_at": "2026-01-26T01:16:27Z", "order_id": "order_1769076135405830680", "id": "603889808367951518", "next_invoice_date": "Charged when usage-based fees reach $30.00", "created_at": "2026-01-22T10:02:30Z", "initiate_cancel_at": "2026-01-26T01:16:00Z", "next_price_info": null, "metadata": null, "status": "canceled", "customer_id": "541822454956310498", "price_version_id": "597247070985830078", "cycle_index": "1", "cancel_reason": "" } } ``` # 交易单 Source: https://docs.subotiz.com/zh/webhook/trade-1 ## 事件列表 | **事件名称** | **事件类型** | **触发时机** | **通知数据结构** | | :------- | :--------------------- | :------- | :--------------------------- | | 交易单支付成功 | trades.succeeded | 支付成功时 | [Trade](/zh/webhook/trade-1) | | 交易单支付失败 | trades.payment\_failed | 支付失败时 | [Trade](/zh/webhook/trade-1) | ## 事件对象 | **属性** | **类型** | **描述** | | ----------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | trade\_id | string | 交易单id | | access\_no | string | 分配的接入方编号 | | merchant\_id | string | 接入方的商户号 | | amount | string | 支付金额,截取两位小数 | | currency | string | 金额对应的交易币 | | customer\_id | string | 顾客ID | | paid\_at | string | 交易单付款成功时间. | | metadata | map\[string]string | 一组可附加到对象上的键值对,允许您以结构化格式存储附加信息。 | | last\_payment\_error | PaymentError | 最后一次支付错误信息,如果该字段有值,则表示**支付失败**。 | | next\_action | NextAction | 下一步操作动作 | | order\_id | string | 接入方订单号 | | last\_trans\_id | string | 订单流水ID。 | | payment\_mode | string | 支付业务模式:
`subscription`:首次订阅支付,需要收集顾客支付信息,传入 payment\_method\_data 字段,支付成功时会返回 payment\_token 用于后续订阅续费
`recurring_payment`:订阅续订支付,需要传入 payment\_token 完成支付,无需收集用户支付信息 | | payment\_token | string | 支付token,用于订阅续订扣款。 | | payment\_method | string | 支付方式 | | payment\_channel | string | 支付渠道 | | return\_url | string | 在类似 3DS 跳转支付场景时,支付渠道受理成功后重定向的页面 | | trade\_status | string | 支付单状态:
`requires_payment_method`:初始状态
`payment_failed`:支付失败
`processing`:支付处理中
`succeeded`:支付成功
`closed`: 已关闭 | | txn\_time | string | 交易发起时间,客户端发起接口的时间 | | created\_at | string | 交易单创建时间 | | refund\_status | string | 退款状态:
no\_refund:无退款
partially\_refunded:部分退款
refunded:退款完成 | | total\_refunded\_amount | string | 退款金额,截取两位小数 | | session\_id | string | 来源结账会话的 ID | | invoice\_id | string | 发票 id | | discounts | Discounts | 应用于交易的折扣,包括此交易的所有折扣信息 | ##### PaymentError | **属性** | **类型** | **描述** | | :------ | :----- | :----- | | code | string | 交易错误码 | | message | string | 交易错误信息 | ##### NextAction | **属性** | **类型** | **描述** | | -------- | ------------------ | ---------------------------------- | | type | string | 客户端下一步需要操作的类型:
`redirect`:重定向 | | redirect | NextActionRedirect | 重定向信息 | ##### NextActionRedirect | **属性** | **类型** | **描述** | | :----- | :----- | :------ | | url | string | 重定向 URL | ### Discounts | 属性名 | 类型 | 描述 | | --------------- | ------------------------ | --------- | | current\_period | CurrentPeriodDiscount\[] | 当前时期的折扣详情 | ### CurrentPeriodDiscount | 属性名 | 类型 | 描述 | | ---------------- | ------ | -------- | | discount\_id | string | 折扣的唯一标识符 | | discount\_amount | string | 折扣金额 | | discount\_code | string | 使用的折扣代码 | ## 交易单生命周期 ```mermaid theme={null} stateDiagram-v2 direction TB state "requires_payment_method" as RPM state "processing" as PROC state "payment_failed" as FAIL state "succeeded" as SUCC state "closed" as CLOSED RPM --> PROC: 支付审核中 RPM --> SUCC: 支付成功 RPM --> FAIL: 支付失败 PROC --> SUCC: 渠道webhook通知成功 PROC --> FAIL: 渠道webhook通知失败 FAIL --> PROC: 支付审核中 FAIL --> SUCC: 重新发起支付并支付成功 FAIL --> CLOSED: 续订失败关闭 RPM --> CLOSED: 交易单超时关闭 ``` ### 交易单状态对应的处理 * **requires\_payment\_method**:交易单初始状态,顾客尚未完成付款(可能尚未发起或正在支付中),或订阅续订扣费已发起但尚未返回结果。 * **payment\_failed**:支付失败,Subotiz 向支付渠道提交支付信息之后被渠道拒绝,例如余额不足、卡验证失败或风控拦截。 * **processing**:支付处理中,Subotiz 向支付渠道提交支付信息之后,支付渠道返回处理中,需要轮询该状态的交易单,直至处于 payment\_failed(支付失败)或者 succeeded(支付成功)。 * **succeeded**:支付成功,处于当前状态无需额外处理。 * **closed**:已关闭,订阅续订失败(多次重试后仍失败)或超过7天无支付结果时,状态流转至已关闭。 ## 示例数据 ```json trades.succeeded theme={null} { "id": 593722493181634535, "type": "trades.succeeded", "created": "2025-12-25T08:41:13Z", "data": { "return_url": "https://checkout.dev.subotiz.com/checkout/593722303875911656/return", "discounts": null, "metadata": null, "last_payment_error": null, "payment_token": "pCD1TbQzAOjo", "payment_method": "credit_card", "currency": "USD", "order_id": "test_order_00111", "last_trans_id": "20251225593722452886957894", "invoice_id": "", "trade_status": "succeeded", "txn_time": "2025-12-25T08:40:36Z", "trade_id": "593722338718003014", "customer_id": "537465921338359803", "capture_method": "auto", "payment_mode": "subscription", "payment_channel": "shoplazzapayment", "refund_status": "no_refund", "total_refunded_amount": "0.00", "session_id": "593722303875911656", "access_no": "200010", "merchant_id": "100010", "amount": "50.00", "paid_at": "2025-12-25T08:41:13Z" } } ``` ```json trades.payment_failed theme={null} { "id": 593722365515409383, "type": "trades.payment_failed", "created": "2025-12-25T08:40:42Z", "data": { "access_no": "200010", "metadata": null, "last_trans_id": "", "paid_at": null, "session_id": "593722303875911656", "refund_status": "no_refund", "total_refunded_amount": "0.00", "customer_id": "537465921338359803", "last_payment_error": { "code": "100999", "message": "其他错误" }, "order_id": "test_order_00111", "payment_token": "", "txn_time": "2025-12-25T08:40:36Z", "trade_status": "requires_payment_method", "trade_id": "593722338718003014", "amount": "50.00", "capture_method": "auto", "payment_channel": "shoplazzapayment", "return_url": "https://checkout.dev.subotiz.com/checkout/593722303875911656/return", "discounts": null, "merchant_id": "100010", "currency": "USD", "payment_mode": "subscription", "payment_method": "credit_card", "invoice_id": "" } } ``` # 交易单 Source: https://docs.subotiz.com/zh/webhook/trade-2 ## 事件列表 | **事件名称** | **事件类型** | **触发时机** | **通知数据结构** | | :------- | :------------------------ | :------- | :---------------------------- | | 交易单已创建 | v2.trades.created | 交易单创建时 | [Trade](/zh/api/trade-object) | | 交易单支付失败 | v2.trades.payment\_failed | 支付失败时 | [Trade](/zh/api/trade-object) | | 交易单支付成功 | v2.trades.succeeded | 支付成功时 | [Trade](/zh/api/trade-object) | ## 事件对象 | **属性** | **类型** | **描述** | | ----------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | trade\_id | string | 交易单id | | access\_no | string | 分配的接入方编号 | | merchant\_id | string | 接入方的商户号 | | amount | string | 支付金额,截取两位小数 | | currency | string | 金额对应的交易币 | | customer\_id | string | 顾客ID | | paid\_at | string | 交易单付款成功时间. | | metadata | map\[string]string | 一组可附加到对象上的键值对,允许您以结构化格式存储附加信息。 | | last\_payment\_error | PaymentError | 最后一次支付错误信息,如果该字段有值,则表示**支付失败**。 | | next\_action | NextAction | 下一步操作动作 | | order\_id | string | 接入方订单号 | | last\_trans\_id | string | 订单流水ID。 | | payment\_mode | string | 支付业务模式:
`subscription`:首次订阅支付,需要收集顾客支付信息,传入 payment\_method\_data 字段,支付成功时会返回 payment\_token 用于后续订阅续费
`recurring_payment`:订阅续订支付,需要传入 payment\_token 完成支付,无需收集用户支付信息 | | payment\_token | string | 支付token,用于订阅续订扣款。 | | payment\_method | string | 支付方式 | | payment\_channel | string | 支付渠道 | | return\_url | string | 在类似 3DS 跳转支付场景时,支付渠道受理成功后重定向的页面 | | trade\_status | string | 支付单状态:
`requires_payment_method`:初始状态
`payment_failed`:支付失败
`processing`:支付处理中
`succeeded`:支付成功
`closed`: 已关闭 | | txn\_time | string | 交易发起时间,客户端发起接口的时间 | | created\_at | string | 交易单创建时间 | | refund\_status | string | 退款状态:
no\_refund:无退款
partially\_refunded:部分退款
refunded:退款完成 | | total\_refunded\_amount | string | 退款金额,截取两位小数 | | session\_id | string | 来源结账会话的 ID | | invoice\_id | string | 发票 id | | discounts | Discounts | 应用于交易的折扣,包括此交易的所有折扣信息 | ##### PaymentError | **属性** | **类型** | **描述** | | :------ | :----- | :----- | | code | string | 交易错误码 | | message | string | 交易错误信息 | ##### NextAction | **属性** | **类型** | **描述** | | -------- | ------------------ | ---------------------------------- | | type | string | 客户端下一步需要操作的类型:
`redirect`:重定向 | | redirect | NextActionRedirect | 重定向信息 | ##### NextActionRedirect | **属性** | **类型** | **描述** | | :----- | :----- | :------ | | url | string | 重定向 URL | ### Discounts | 属性名 | 类型 | 描述 | | --------------- | ------------------------ | --------- | | current\_period | CurrentPeriodDiscount\[] | 当前时期的折扣详情 | ### CurrentPeriodDiscount | 属性名 | 类型 | 描述 | | ---------------- | ------ | -------- | | discount\_id | string | 折扣的唯一标识符 | | discount\_amount | string | 折扣金额 | | discount\_code | string | 使用的折扣代码 | ## 交易单生命周期 ```mermaid theme={null} stateDiagram-v2 direction TB state "requires_payment_method" as RPM state "processing" as PROC state "payment_failed" as FAIL state "succeeded" as SUCC state "closed" as CLOSED RPM --> PROC: 支付审核中 RPM --> SUCC: 支付成功 RPM --> FAIL: 支付失败 PROC --> SUCC: 渠道webhook通知成功 PROC --> FAIL: 渠道webhook通知失败 FAIL --> PROC: 支付审核中 FAIL --> SUCC: 重新发起支付并支付成功 FAIL --> CLOSED: 续订失败关闭 RPM --> CLOSED: 交易单超时关闭 ``` ### 交易单状态对应的处理 * **requires\_payment\_method**:交易单初始状态,顾客尚未完成付款(可能尚未发起或正在支付中),或订阅续订扣费已发起但尚未返回结果。 * **payment\_failed**:支付失败,Subotiz 向支付渠道提交支付信息之后被渠道拒绝,例如余额不足、卡验证失败或风控拦截。 * **processing**:支付处理中,Subotiz 向支付渠道提交支付信息之后,支付渠道返回处理中,需要轮询该状态的交易单,直至处于 payment\_failed(支付失败)或者 succeeded(支付成功)。 * **succeeded**:支付成功,处于当前状态无需额外处理。 * **closed**:已关闭,订阅续订失败(多次重试后仍失败)或超过7天无支付结果时,状态流转至已关闭。 ## 示例数据 ```json v2.trades.created theme={null} { "id": "572677246926464036", "type": "v2.trades.created", "created": "2025-10-28T06:54:55Z", "data": { "metadata": {}, "return_url": "https://checkout.sandbox.subotiz.com/checkout/572677164911046667/return", "txn_time": "2025-10-28T06:54:52Z", "access_no": "77d52a21dc032b4", "amount": "30.00", "capture_method": "auto", "last_payment_error": null, "last_trans_id": "", "paid_at": null, "payment_token": "", "refund_status": "no_refund", "trade_id": "572677233903157186", "currency": "USD", "payment_method": "credit_card", "payment_channel": "shoplazzapayment", "total_refunded_amount": "0.00", "session_id": "572677164911046667", "merchant_id": "2816433", "customer_id": "547766341013094363", "order_id": "order_1761634475936438746", "payment_mode": "subscription", "trade_status": "requires_payment_method", "invoice_id": "" } } ``` ```json v2.trades.payment_failed theme={null} { "id": "593722365515409383", "type": "v2.trades.payment_failed", "created": "2025-12-25T08:40:42Z", "data": { "access_no": "200010", "metadata": null, "last_trans_id": "", "paid_at": null, "session_id": "593722303875911656", "refund_status": "no_refund", "total_refunded_amount": "0.00", "customer_id": "537465921338359803", "last_payment_error": { "code": "100999", "message": "其他错误" }, "order_id": "test_order_00111", "payment_token": "", "txn_time": "2025-12-25T08:40:36Z", "trade_status": "requires_payment_method", "trade_id": "593722338718003014", "amount": "50.00", "capture_method": "auto", "payment_channel": "shoplazzapayment", "return_url": "https://checkout.dev.subotiz.com/checkout/593722303875911656/return", "discounts": null, "merchant_id": "100010", "currency": "USD", "payment_mode": "subscription", "payment_method": "credit_card", "invoice_id": "" } } ``` ```json v2.trades.succeeded theme={null} { "id": "572677246926464036", "type": "v2.trades.succeeded", "created": "2025-10-28T06:54:55Z", "data": { "metadata": {}, "return_url": "https://checkout.sandbox.subotiz.com/checkout/572677164911046667/return", "txn_time": "2025-10-28T06:54:52Z", "access_no": "77d52a21dc032b4", "amount": "30.00", "capture_method": "auto", "last_payment_error": null, "last_trans_id": "20251028572677234091900866", "paid_at": "2025-10-28T06:54:55Z", "payment_token": "pB_KO6Q***YU", "refund_status": "no_refund", "trade_id": "572677233903157186", "currency": "USD", "payment_method": "credit_card", "payment_channel": "shoplazzapayment", "total_refunded_amount": "0.00", "session_id": "572677164911046667", "merchant_id": "2816433", "customer_id": "547766341013094363", "order_id": "order_1761634475936438746", "payment_mode": "subscription", "trade_status": "succeeded", "invoice_id" : "547766341013094363" } } ``` # AI 助手 Source: https://docs.subotiz.com/zh/faq/ai-assistant AI 助手支持三项核心功能: * **店铺设置** —— 注册后自动引导入驻流程 * **邮件模板编辑** —— 在编辑器内通过自然语言修改模板 * **数据分析** —— 通过对话查询店铺数据 所有功能均可在后台任意页面通过顶部导航栏图标进入,无需在不同模块之间切换。 不支持。AI 助手仅限访问当前登录的 Subotiz 店铺数据,不支持跨账户或跨店铺查询。这一限制适用于所有功能,包括入驻引导、邮件编辑和数据分析。如您管理多个店铺,需切换账户后分别进入各店铺的 AI 助手操作。 撤销功能仅适用于邮件模板编辑场景。在邮件模板编辑器中,可通过面板中的撤销选项回退最近一次 AI 修改,但该功能仅支持撤销最近一步操作——提交新指令后,上一次的撤销选项将被替换。编辑器快捷键撤销适用于 AI 修改与手动修改的共享历史记录。数据分析和店铺设置不涉及对系统的直接修改,因此不适用撤销功能。 入驻流程支持跳过部分或全部问题。跳过后,系统会自动为未填写的字段补充默认值,生成的入驻方案将基于默认设置而非您的实际业务信息。建议在点击生成入驻指南前,在信息摘要卡片中核对并修改相关字段。任务清单中的各项任务也可单独跳过,不影响整体流程推进。 不需要。入驻进度会自动保存。重新进入 Subotiz 后台后,AI 助手会从上次完成的步骤继续引导,已完成的任务不会重置。您也可以随时打开 AI 助手面板继续完成剩余任务。 可以。信息收集完成后,系统会以摘要卡片形式展示结果,您可以在点击生成入驻指南之前直接编辑卡片中的字段,也可以通过发送对话消息修改,例如将经营地区改为美国。方案仅在点击生成后才正式生成,因此在此之前随时可以调整。 Email AI 助手支持通过自然语言完成多种修改: * 更新颜色、字体和视觉样式 * 调整间距、对齐方式和布局 * 重写主题、正文及行动号召按钮文案 * 修改按钮大小、颜色和文字 * 调整 Logo 位置与大小 * 编辑页头和页尾结构 * 突出显示价格、试用期等关键信息 所有修改仅作用于当前打开的模板。 建议每次只提交一个修改指令以获得更稳定的结果。在同一条消息中混合多个请求可能导致修改不完整或结果不一致。如需多项修改,建议逐步拆分提交,每次确认结果后再继续下一步。助手会在当前会话中保留上下文,后续指令将基于已有修改继续执行。 AI 助手结果与报表不一致,最常见原因有三: 1. **默认时间范围** —— 若未指定时间,助手默认使用最近 30 天数据,可能与报表使用的时间段不同。 2. **数据同步延迟** —— 最新数据可能尚未完全同步,尤其是查询今天或最近 1 小时时。 3. **店铺上下文差异** —— 助手自动使用当前店铺的时区与结算币种。若报表模块配置了不同设置,结果可能存在差异。 建议明确指定时间范围,并确认报表使用的时区与币种与当前店铺一致。 若未指定时间范围,AI 助手在一般查询中默认使用最近30天数据。对于对比类问题,默认逻辑为最近7天与前7天对比,反映短期趋势。助手还会自动使用当前店铺的时区与结算币种。为避免结果偏差,建议在提问时明确说明时间段,例如上周、本月或具体日期区间。 常见原因有两种: 1. **行数限制** —— 每次查询最多返回 1000 行数据,查询范围过大时可能出现结果不完整。建议缩小时间范围或增加维度筛选(如国家、商品)。 2. **数据范围限制** —— 助手仅支持 Subotiz 系统内数据,外部文件、第三方平台、行业基准及竞争对手数据均不在支持范围内。 如结果不完整,请优先缩小查询范围或补充筛选条件重新查询。 不支持。数据分析助手仅用于历史数据分析,不提供未来趋势预测、收入预估或业绩预测功能,也不支持行业基准对比或竞争对手分析。如需业务规划或预测,请使用专业预测工具或外部数据分析平台,结合 Subotiz 数据进行综合分析。 不支持。数据分析助手仅返回聚合数据,不提供单笔交易记录、客户个人信息、支付卡号或 CVV 等敏感数据。这是系统设计的数据保护机制。如需查看单笔交易明细,请直接使用 Subotiz 报表模块。 大多数情况下可以切换。系统会根据数据结构自动选择最合适的图表类型:趋势数据默认折线图,对比数据默认柱状图,结构数据默认饼图。在支持范围内,可使用图表类型选择器切换展示方式,但并非所有数据类型都支持切换,部分结果可能仅以表格形式展示。在窄屏模式下查看图表时,建议切换至宽屏模式以获得更完整的显示效果。 当今日数据显示异常时,建议检查以下三点: 1. **时间范围** —— 若未指定时间,助手默认使用最近 30 天,需明确指定今天才能获取当日数据。 2. **数据同步延迟** —— 最新数据可能尚未完全同步,尤其是短期查询(如今天或最近 1 小时)受影响最大,可尝试扩大至最近 2–3 天进行趋势验证。 3. **交叉核对** —— 将结果与报表模块同期数据进行对比,判断是否存在差异。 Email AI 助手仅在邮件模板编辑器内可用,无法从主 AI 助手面板进入。进入路径: 1. 前往 Subotiz 后台的**电子邮件**。 2. 选择**交易邮件**或**营销邮件**。 3. 点击任意邮件模板右侧的**预览**按钮进入编辑器。 4. 点击顶部工具栏中的 **AI 助手**图标打开对话面板。 Email AI 助手仅在打开模板时可用。 不会。Email AI 助手的修改仅作用于当前打开的模板。如果您有多个邮件模板,每个模板需单独打开并分别编辑。在一个模板中的修改不会影响其他模板。 不是。邮件编辑器中的键盘快捷键撤销适用于包含 AI 生成修改和手动编辑的共享操作历史记录。按下撤销会回退最近一步操作,无论是 AI 还是手动完成的。这与 AI 助手面板中的撤销选项不同,面板撤销仅针对最近一次 AI 生成的修改。如果只想撤销最后一次 AI 修改而不影响手动编辑,请使用助手面板中的撤销选项。 AI 入驻流程在回答设置问题时支持三种输入方式: * **自由文本输入** * **选择系统提供的预设选项** * **上传图片** 商家无需逐一手动输入,可以选择预填选项或在适用时上传相关图片。跳过的问题会由系统自动补充默认值。 可以。入驻指南任务清单中的各项任务可以单独跳过,不影响其他任务的推进。整体进度会根据已完成的任务更新。跳过任务不会将其从列表中移除,可以随时返回完成。入驻流程设计灵活,商家可根据实际情况按需完成各项设置。 可以。AI 助手面板可以随时通过 Subotiz 后台顶部导航栏重新打开。即使已完成入驻任务,仍可随时重新进入 AI 助手查看剩余任务或已完成任务。系统会自动保存进度,重新打开面板时会显示当前的任务完成状态。 AI 助手支持对四种数据类型进行自然语言查询:**交易、客户、订阅和发票**。支持多种查询条件: * **ID 或关键词** —— 如具体交易 ID 或包含某字段的客户邮箱 * **时间范围** —— 如上周、最近 7 天、本月 * **状态** —— 如未激活订阅、已退款交易 * **金额范围** —— 如超过 100 美元的交易 也支持模糊查询,如大额交易、新客户、最近退款,AI 会返回结果并展示实际采用的筛选条件,方便进一步调整查询范围。 可以。AI 助手支持在同一会话内持续追问,并自动继承当前查询条件,无需重复输入完整条件,系统会基于已有条件持续更新结果。例如,先查询最近7天的失败交易,再追问查看其中退款金额超过100美元的记录,再查询某笔交易对应的客户信息。通过连续追问,可以逐步缩小范围,更快定位目标数据。 可以。AI 助手支持跨业务对象的关联数据查询,无需分别进入不同菜单查看。支持关联的数据类型包括交易、客户、订阅和发票。在同一对话中可以查看某客户关联的订阅与付款记录、查询退款交易对应的客户与账单信息、查看订阅相关的历史支付状态。通过关联查询,可在同一对话窗口内获取更完整的信息,减少在多个模块之间反复切换。 可以。当查询结果较多时,点击查看全部结果进入对应列表页面查看完整数据。AI 助手会自动同步对话中的筛选条件,无需再次手动配置。在列表页可以继续查看完整结果、调整筛选条件或导出数据。AI 查询与后台列表操作无缝衔接,减少重复筛选操作。 AI 助手数据查询有两个主要限制: * **受权限控制** —— 查询结果遵循当前账号权限,仅展示该账号可访问的数据。 * **会话上下文有限** —— 单次会话最多保留 50 轮上下文记录。超过 50 轮后,早期对话上下文可能不再保留,复杂的多步骤查询可能需要重新开始。 # 客户 Source: https://docs.subotiz.com/zh/faq/customers Subotiz 会根据结账时购物车内容自动分配客户类型: * **会员** —— 购物车中包含至少一个订阅商品时创建。 * **游客** —— 购物车仅包含一次性商品时创建。 这一区别非常重要,因为订阅相关的账单、合同 ID 和续费记录会关联至会员类型的资料。如果游客后续使用相同标识(通常为邮箱)购买订阅商品,系统会自动将其资料升级为会员类型,并保留原有客户 ID。 Subotiz 使用基于优先级的匹配逻辑来判断是复用已有资料还是创建新资料。系统按以下顺序检查标识: 1. **客户 ID** —— 若找到有效匹配,直接使用该资料,结账时联系字段变为只读。 2. **外部客户 ID** —— 若客户 ID 未匹配,检查外部客户 ID。 3. **邮箱** —— 若前两者均未匹配,检查邮箱地址。 只有在提供外部客户 ID 或邮箱且未匹配到现有资料时,系统才会新建客户资料。若仅提供客户 ID 但未找到匹配记录,系统不会创建新资料。 外部客户 ID 是商家可选填的标识字段,用于从外部系统(如 CRM 或 ERP)同步客户资料时保持数据一致性。它是第二优先级的匹配标识——在未提供客户 ID 时,系统会先检查外部客户 ID,再检查邮箱。它也是唯一可以在客户没有邮箱时替代邮箱作为唯一标识的字段。外部客户 ID 在同一 Subotiz 账户内必须唯一。 不会,只要使用相同的标识(如邮箱)。当游客后续使用相同标识购买订阅商品时,Subotiz 会自动将现有游客资料升级为会员资料,而不会创建新资料。升级过程中: * 原客户 ID 保持不变。 * 客户类型更新为会员。 * 如有新的有效数据(如姓名、地址),系统会自动补充缺失字段。 这避免了重复资料的产生,并将所有购买历史集中保存在同一资料下。 客户导入支持两种文件格式:.xlsx 和 .csv。其他格式无法导入。文件大小不得超过 10MB。此外,模板中的表头名称和顺序不可修改——表头被修改的文件无法被系统正确处理。所有字段需按规定格式填写。若有记录验证失败,系统会跳过或标记,并可下载错误明细文件查看具体失败原因,修正后重新导入。 取决于导入时是否启用覆盖选项: * **启用覆盖** —— 当导入记录的邮箱或外部客户 ID 与已有客户匹配时,系统会用导入数据更新现有资料。模板中为空的字段不会覆盖原有数据,只有非空字段才会更新。 * **不启用覆盖** —— 任何与现有客户匹配的导入记录会被跳过,不做任何修改。 无论覆盖选项如何设置,没有匹配记录的新客户始终会被创建。 不会。关闭导入弹窗不会中断或取消导入任务,系统会在后台继续处理文件。导入完成后,系统会通过消息中心发送通知,包含导入成功、失败和跳过的记录数量,并支持下载错误明细文件。如需稍后查看结果,可前往消息中心或通知区域查看导入汇总。 不可以。若客户仍有未结束的有效订阅,系统不允许删除,并会提示先取消相关订阅。取消所有有效订阅后才可以确认删除。删除后客户资料将永久移除,无法恢复,所有关联数据将不可再访问。 自定义数据是客户资料中一个独立模块,用于保存商家自定义的扩展字段,供内部参考或外部系统映射使用,例如内部标识、业务标签或集成密钥。每个客户资料最多支持添加 40 个自定义字段(键值对)。自定义数据仅用于信息记录,不参与客户识别或资料匹配,不显示在发票上,也不影响任何计费逻辑。联系信息(如姓名、邮箱、地址)则用于账单生成、发票开具和结账页面预填充。自定义数据纯属内部业务使用。 客户列表的搜索仅支持邮箱、客户 ID 和外部客户 ID。但如果只有发票 ID 或交易单 ID,最有效的方式是先在发票或交易单模块中搜索对应记录,然后从发票或订单详情页点击跳转至关联客户资料。如果知道客户邮箱,也可以直接在客户列表中搜索。 可以。同一客户资料可以关联多个订阅合同 ID,支持客户同时订阅多个商品或定价方案的场景。每个订阅合同 ID 代表一份独立的订阅关系。所有订阅记录可在客户详情页的订阅模块中查看,包括各合同的商品名称、计费周期、创建时间和订阅合同 ID。点击任意订阅合同 ID 可进入完整的订阅详情页。 客户 ID 由系统自动生成,不可修改。其他字段(如姓名、地址、邮箱订阅状态)可以在客户详情页的基础信息模块中点击编辑进行更新。邮箱在 Subotiz 中为可选字段,若填写,必须在账户内保持唯一。在结账过程中使用已有客户 ID 时,联系信息字段(包括姓名和邮箱)会变为只读,系统会自动从现有资料预填数据。如需在结账之外更新客户信息,请直接在客户详情页使用编辑功能。 客户资料中的邮箱订阅字段表示客户是否同意接收营销或服务相关邮件。该字段在结账流程中通过客户与营销邮件订阅复选框的互动获取,或通过 API 同步从外部系统导入客户数据时捕获。商家可以在后台使用该字段按通信偏好筛选客户——例如在发送营销活动前筛选已授权的客户。该字段也可以在客户详情页中查看和更新。 在结账创建客户资料时,Subotiz 会自动从结账表单、支付方式或 API 请求中收集以下信息: * **邮箱** —— 从结账表单收集或通过 API 传入。 * **姓名** —— 从支付方式获取,例如信用卡持卡人姓名或 PayPal 账户姓名。 * **电话** —— 可选,从结账表单或 API 获取。 * **地址** —— 可选,从支付方式或 API 获取。 * **自定义数据(Metadata)** —— 可选,通过 API 传入。 系统只要收到至少一个有效标识就会自动收集可获取的信息,无需商家手动填写。 默认情况下,导入模板使用邮箱作为客户的唯一标识。如果客户没有邮箱,可以使用外部客户 ID 作为替代标识。使用外部客户 ID 作为标识时,邮箱字段可以留空。邮箱和外部客户 ID 在所有客户中都必须唯一——不同记录之间的重复值会导致导入失败。两者不能同时用于同一条记录的标识,系统会根据可用性优先使用其中一个。 导入完成后,Subotiz 会显示导入结果汇总,包含成功导入、导入失败和跳过记录的数量。如有失败记录,点击失败记录按钮下载错误明细文件。该文件会指明无法导入的具体记录及每条记录的失败原因。查看并修正文件中的问题后,仅重新导入已修正的记录即可。如果在任务完成前关闭了导入弹窗,任务完成后可在消息通知或消息中心查看结果并下载失败记录文件。 在 Subotiz 后台的客户模块中,使用类型筛选器按客户类型分类查看: * **会员** —— 查看至少有一个订阅商品的客户资料。 * **游客** —— 查看只有一次性购买的客户资料。 还可以将类型筛选与邮箱订阅筛选组合使用,进一步缩小范围——例如,查找已授权营销邮件的订阅客户。这些筛选条件有助于快速识别不同客户群体,用于运营或沟通目的。 可以。自定义数据可以随时在客户详情页添加或更新。点击自定义数据模块中的编辑,然后选择添加自定义数据即可添加键值对。每个客户资料最多支持40个自定义数据字段。已有的自定义数据也可以随时更新。自定义数据仅供参考,不用于客户识别、资料匹配或任何计费逻辑,纯属内部业务使用,如存储业务标签、内部 ID 或外部系统映射信息。 # 数据 Source: https://docs.subotiz.com/zh/faq/data 争议风险指数显示的是 Subotiz Payments 当月的争议率,计算方式为:当月争议订单数 ÷ 当月成功订单数 × 100%。 指数分三个等级: * **正常** —— 绿色,≤ 0.8% * **关注** —— 黄色,0.8%–1.0% * **风险** —— 红色,≥ 1.0% 重要提示:该指数不会随时间范围或支付供应商筛选的切换而变化,始终仅反映 Subotiz Payments 当月数据。 争议风险指数对零订单情况的处理规则如下: * 若当月无成功订单且无争议,指数显示正常(绿色)。 * 若当月无成功订单但存在争议,指数显示风险(红色)。 这意味着在没有成功订单的情况下,哪怕只有一笔争议也会直接触发风险状态。 争议数据看板显示的争议金额,是所选时间范围内涉及争议的订单金额总和。所有金额统一折算为美元(USD)进行汇总展示,仅供统计参考,不反映实际结算货币或本地化金额。该看板目前不支持切换显示货币。 争议率突然大幅上升通常说明近期订单存在异常。准确解读需结合以下三点: 1. **持续时间** —— 单次波动更可能是个别异常,持续上升趋势则通常反映系统性问题,需要更全面排查。 2. **笔数与金额** —— 争议笔数增加但金额较低,多为小额争议;若金额同步明显上升,则可能涉及高价值订单风险。 3. **原因分布** —— 查看争议原因分布图,判断是否由某类特定原因驱动上升。 可结合支付供应商筛选,判断是否集中在某一渠道。 争议数据看板下方的两个环形图分别用于不同分析维度: * **争议原因分布图(左下)** —— 展示争议发生的原因,按争议类别(如未授权交易、未收到商品、商品与描述不符等)拆分全部争议的占比、笔数及金额。用于识别高频问题类型,针对性优化流程。 * **争议状态分布图(右下)** —— 展示争议目前处于哪个处理阶段,如争议败诉、胜诉、审核中等。用于评估整体案件结构与处理进度。 审核中占比偏高意味着存在大量未结案争议需要重点跟进。 当某一支付供应商的争议率明显偏高时,建议按以下步骤排查: 1. 在争议数据看板中使用支付供应商筛选,单独查看该供应商的数据及趋势变化。 2. 查看该供应商对应的争议原因分布,判断是否集中在某类特定原因。 3. 检查该渠道的交易质量与风控设置。 4. 若争议率已达关注或风险等级,优先排查当月争议原因,并考虑调整该渠道的配置或运营策略。 不可以。争议数据看板仅用于聚合数据的趋势与分布分析,展示争议率、争议笔数、争议金额、趋势变化、原因分布及状态分布等汇总指标。不包含单笔争议详情、客户信息或具体交易记录。如需查看或处理单笔争议,请前往 Subotiz 后台的争议订单页面。 这两个指标衡量的是支付路径中的不同阶段: * **结算客户数** —— 统计在所选时间范围内进入结账页面的去重客户数量,同一客户多次进入结账仅计为1人。 * **支付客户数** —— 统计在同一时间范围内成功完成至少一次支付的去重客户数量,同一客户多次支付也仅计为1人。 两者之间的差值反映了进入结账但未完成支付的客户数量。 交易概览中的销售金额代表所选时间范围内成功支付订单的总金额,按支付成功时间统计,仅反映已完成的支付,不扣除退款。退款作为独立指标单独展示——退款金额字段显示同一时间范围内成功处理的退款总额,按退款完成时间统计。如需计算净收入,需手动将退款金额从销售金额中减去。图表中仅显示货币符号与金额,表格中则显示币种代码、符号与金额(如:USD \$1,000.00)。 结账转化漏斗追踪客户在支付路径中经过的四个阶段:开始结账、提交支付、完成支付操作、支付成功。每位客户在所选时间范围内仅计数一次,以确保转化数据准确。 支持四种转化率指标: * **结账转化率** —— 支付成功人数 ÷ 开始结账人数 * **发起支付率** —— 提交支付人数 ÷ 开始结账人数 * **支付完成率** —— 完成支付操作人数 ÷ 提交支付人数 * **付款成功率** —— 支付成功人数 ÷ 完成支付操作人数 漏斗数据每15分钟更新一次,基于店铺时区。如需查看最新数据,请手动刷新页面。 如果同一笔交易在订阅续订重试过程中多次失败,支付失败原因区域仅展示该交易的最后一次失败原因。这意味着失败数量和占比反映的是每笔交易的最终失败结果,而非每次重试的记录。这种处理方式避免了重试次数对失败数量的虚增,确保数据反映实际的最终结果。 这两种统计维度控制订阅指标的计算方式: * **客户维度** —— 以去重客户为统计主体,每位客户无论持有多少订阅均只计为1人,适合分析用户规模、客户结构和人均收入。 * **订阅合同维度** —— 以每份订阅合同为统计单位,持有多份订阅的客户会被多次计入,适合分析方案采用情况、合同数量和多订阅行为。 同一客户持有3份订阅时,客户维度计为1,订阅合同维度计为3。 订阅概览中的 MRR(月度经常性收入)代表当前时间点所有有效订阅折算后的月度经常性收入。计算方式是将每份订阅的当前计费周期价格折算为月度等值金额,无论方案按月、按季度还是按年计费。例如,年费方案价格为 \$120/年,则贡献 \$10 MRR。MRR 反映的是当前有效订阅的即时快照,并非未来收入预测或预估,会根据查看时的有效订阅状态实时更新。 订阅概览中的全部时间选项显示自店铺启用订阅功能以来所有订阅的数据,不按日期筛选。适合用于长期趋势分析和整体业务健康评估。自定义时间段将分析限定在特定时间区间内创建的订阅,适合短期效果评估,例如衡量活动或价格调整的影响。选择自定义时间段时,系统仅统计该时间段内创建的订阅,但其续订和生命周期活动会持续追踪至当前日期。 这两个指标从不同角度衡量授权表现: * **支付成功率** —— 计算方式为:成功支付订单数 ÷ 交易订单总数,包含所有失败类型,反映整体端到端支付转化情况。 * **净支付成功率** —— 从分母中剔除客户因素导致的失败:成功支付订单数 ÷(交易订单总数 − 因客户因素失败的订单数),用于隔离供应商侧或系统侧的授权问题,排除余额不足、卡片拒付等用户行为导致的失败。 评估支付渠道稳定性时使用净支付成功率,评估整体结账转化时使用支付成功率。 是的,这是预期行为。页面顶部的支付方式汇总卡片显示各支付方式的交易总金额及占比,这些卡片是固定的,仅在更改所选时间范围时才会更新。切换支付供应商、更改指标维度(如净支付成功率或交易订单数量)或调整支付方式勾选均不会影响汇总卡片。页面下方图表区域则会根据所选供应商、指标和支付方式实时更新。 支付供应商错误归因占比报表提供一个切换开关,用于包含或排除客户因素失败。包含客户因素时,图表展示全部失败原因的分布。排除客户因素时,图表仅显示供应商侧或系统侧的授权问题,剔除余额不足、卡片过期、拒付等用户行为导致的失败。排查供应商问题的步骤:将开关切换为排除客户因素,同时按特定支付供应商筛选。此视图中占比较高的失败原因说明存在渠道或系统侧授权问题,需联系支付供应商进一步排查。 启用对比视图后,每个指标的百分比变化计算方式为:(当前周期数值 − 对比周期数值)÷ 对比周期数值 × 100,结果保留两位小数。增长显示为绿色文字加上升箭头,下降显示为红色文字加下降箭头,无变化显示为灰色文字加一字线。 可选择三种对比方式: * 昨天 * 上一个同期周期(如本周与上周对比) * 去年同期 在交易概览中,客户的国家/地区由其发起结账时的 IP 地址决定。这反映的是客户开始结账时所在的地点,而非账单地址或收货地址。订单来源国家/地区图表最多展示订单量排名前8的国家,其余国家统一归为其他。 数据更新频率取决于所选时间范围。选择今天时,交易指标全天按分钟级别持续更新。选择其他时间范围(如昨天、过去7天、过去30天)时,数据基于已完成的聚合周期,按计划更新,而非持续实时更新。所有时间范围下如需查看最新数据,均需手动刷新页面,页面不会自动刷新。 两个指标都衡量订阅取消情况,但关注的生命周期阶段不同: * **订阅总流失率** —— 计算方式为取消订阅数除以订阅总数,统计所有取消情况,不限时间节点。 * **首次续订前流失率** —— 专门衡量在首次续订发票生成前就已取消的订阅占比,帮助识别在初始期或试用期内、续订尝试发生之前就流失的客户,这与续订开始后的取消是不同的流失信号。 订阅概览中的 LTV(生命周期平均价值)代表每份订阅在其生命周期内产生的平均总收入,包含初始订阅金额与所有续订成功金额。对于已结束的订阅,LTV 覆盖从创建到取消或到期的完整周期。对于仍处于有效状态的订阅,LTV 统计至当前观察时间点,反映截至目前的实际收入,而非预测值。随着有效订阅持续续订成功,LTV 数值会持续增长。 订阅续订与流失图表按续订轮次分析订阅的续订表现,覆盖所选时间范围内创建的订阅。图表包含三组数据: * 进入各续订轮次的订阅数量 * 该轮次续订成功数 * 以折线展示的续订成功率 选择12次续订适用于月付订阅产品或较短计费周期,大多数生命周期活动在第一年内发生。选择24次续订适用于长期订阅产品或留存周期较长的场景,行为规律需要更多时间才能显现。 订阅概览中的 ARPU(每用户平均收入)计算方式为:(订阅总收入 − 订阅总退款)÷ 去重订阅客户数。与不扣除退款的收入指标不同,ARPU 使用扣除退款后的净收入进行计算。客户数量基于所选时间范围内按客户 ID 去重的唯一客户数。因此 ARPU 反映的是每位客户的净收入,而非毛收入。 报表模块中的支付供应商和支付方式列表根据以下两个条件动态生成: * 商家已配置且处于激活状态的支付供应商或支付方式 * 该供应商或支付方式在所选时间范围内是否存在交易数据 如果某个供应商或支付方式在所选时间段内没有交易数据,则不会出现在下拉菜单中。如需查看缺失的供应商,可尝试扩大时间范围至该供应商曾有交易的时间段。 订阅概览中的试用转正率衡量的是:在所选时间范围内进入试用期的订阅中,试用结束后成功转为付费方案的比例。计算方式为:试用后成功转为付费的订阅数 ÷ 所选时间范围内进入试用期的订阅总数。成功转正意味着订阅从试用期顺利进入付费计费周期——客户在试用结束后的首个完整计费周期被成功扣款。在试用期间取消订阅或试用结束后未能完成支付的情况,不计入转正。 订阅概览中的生命周期平均时长衡量所选时间范围内创建的订阅,从生效日期到最终失效的平均实际服务时长,包含试用期和正式付费周期。对于提前取消的订阅,时长计算至服务到期日期,而非取消申请的日期——即取消后的剩余服务期仍计入时长。这反映的是客户实际享有服务的时间,而非仅统计计费活动。 在交易概览的商品筛选中同时选择多个商品时,系统会对所有选中商品的数据进行合并统计。客户数、订单数、销售金额和转化趋势等指标,会基于所有选中商品汇总计算,作为一个统一结果展示,而非按商品分别显示。其他筛选条件(如时间范围、支付方式、国家/地区和交易类型)会同时生效,与商品筛选共同作用于数据范围。如需对比单个商品的表现,建议每次只选择一个商品进行筛选。 交易概览图表的横轴粒度会根据所选时间范围自动调整: * **选择3天及以内的时间范围时** —— 图表以小时为粒度展示,同日数据格式为 HH:mm,跨日数据格式为 MM-DD HH:mm。 * **选择超过3天但在同一年内的时间范围时** —— 图表切换为按日展示,格式为 MM-DD。 * **跨年时间范围** —— 则使用 YYYY-MM-DD 格式。 系统会根据所选时间范围自动匹配最合适的显示粒度,无需手动设置。 # 折扣 Source: https://docs.subotiz.com/zh/faq/discounts Subotiz 支持两种折扣类型: * **百分比折扣** —— 按设定比例减少商品或订阅价格,例如享受10%优惠 * **固定金额折扣** —— 按指定金额直接减免订单总额,例如减免\$20。固定金额折扣以店铺结算货币为准,单个折扣活动不支持多币种设置。 两种类型均可应用于一次性购买和周期性订阅,具体取决于活动配置。 非周期性折扣仅作用于单笔订单,不延续至后续账单周期,适用于一次性促销或单次购买激励。周期性折扣可跨多个账单周期持续生效,具体周期数由创建活动时的配置决定,例如前三期或所有周期。这一区别对于订阅商品尤为重要,因为折扣可能会在多个计费周期内持续生效。 Subotiz 折扣码需满足以下要求: * 仅支持大写字母和数字,不支持小写字母和特殊字符。 * 长度限制为2至20个字符。 * 同一活动内每个折扣码必须唯一。 * 折扣码可以手动输入或自动生成。 建议使用简短、易识别的代码,例如 WELCOME10,方便客户使用。 可以。创建折扣活动时,系统默认折扣适用于全部商品。如需限定范围,开启商品选择开关并从商品目录中勾选指定商品即可。这样可以针对特定商品或定价方案开展精准促销,而不影响其他商品。创建后,适用范围会显示在活动详情页,并支持编辑,修改仅影响后续新订单,不影响已完成的账单。 可以。创建折扣活动时,可以设置最低消费金额作为折扣生效的前提条件。如果订单金额未达到最低消费门槛,结账时将不应用折扣。该功能适用于鼓励客户增加消费或防止折扣被用于低价值订单。条件满足时,折扣金额会在结账页面清晰显示;条件不满足时,系统不会应用折扣。 不会。折扣活动的修改仅影响后续新订单,不会影响已完成的账单或支付记录。已经使用折扣完成支付的订单不会因活动配置的变更而受到影响。这与 Subotiz 商品和定价修改的一贯规则一致,修改只对后续交易生效,历史记录保持不变。 Subotiz 折扣活动有四种状态,每种状态下的可用操作不同: * **草稿** —— 已保存但尚未发布,可执行发布或删除。 * **未开始** —— 已发布并设定了未来启动时间,只能转为草稿。 * **进行中** —— 活动正在运行,只能提前结束。 * **已结束** —— 活动已完成或被提前结束,可执行重新启用或删除。 了解这些状态有助于商家管理活动生命周期,避免误操作正在进行中的活动。 消耗进度字段显示折扣活动的当前使用情况,格式为已使用次数与总次数——例如 3/10 或 3/不限。该字段会实时自动更新。重要的是,当订单发生退款或取消时,消耗进度会相应调整——已使用次数减少,剩余次数增加。这确保了即使有订单被撤销,消耗数据仍然保持准确。 不会。折扣在试用期内(无论免费或付费试用)不会生效。但系统会保留折扣,待试用期结束后从首个付费周期开始自动应用。例如,订阅含7天免费试用,之后每月收费\$30,若配置了10%折扣,首个付费周期的实际扣款为\$27。在结账页面,试用期内折扣金额显示为\$0,但系统已记录折扣处于待生效状态,将在首个付费周期自动应用。 若折扣活动配置了N个账单周期,系统从试用期结束后的首个付费周期开始连续应用折扣,直至达到设定周期数。例如,\$50月付订阅享受10%折扣持续3个周期:第1、2、3期各扣\$45,第4期起恢复正常价格\$50。若订阅包含试用期,试用期不计入账单周期数——3个折扣周期从试用结束后的首个付费周期开始计算。 可以。已结束的折扣活动可以在活动列表或详情页中重新启用。在已结束的活动右侧点击更多操作,选择重新启用即可。重新启用后,活动恢复为进行中状态,折扣码可以在结账时继续使用。这对于重新发起成功的促销活动非常有用,无需从头创建新活动。注意:只有已结束的活动支持重新启用操作,进行中的活动只能提前结束,草稿活动只能发布。 固定金额折扣以店铺结算货币为准,单个折扣活动不支持多币种设置。这意味着如果您的店铺结算货币为美元,设置\$20固定折扣,则无论客户使用何种货币支付,均按美元\$20计算减免金额。如需针对不同货币提供折扣,需要分别创建独立的折扣活动。百分比折扣不受此限制,因为它按比例计算,与货币无关。 可以。创建折扣活动时,开始时间字段可以留空(发布后立即生效),也可以设定未来的具体启动日期。设定未来开始时间后,活动发布后状态将显示为未开始,并在设定日期自动启用。这对于配合营销节点、季节性促销或新品发布非常实用。结束时间为可选项,可用于控制活动的截止时间。 会。创建折扣活动时填写的折扣名称会显示在客户发票上,因此这不仅是内部管理标签,客户也能看到。命名折扣活动时,建议使用对客户有意义的清晰名称,例如夏季特惠八折或新客专属优惠,避免使用内部代码或不明缩写,以免客户在查看发票时产生困惑。 # 电子邮件 Source: https://docs.subotiz.com/zh/faq/emails Subotiz 会自动发送两类交易邮件。 订阅类: * **试用开始** —— 试用已激活 * **试用到期** —— 到期前3天提醒 * **订阅激活** —— 周期性订阅已激活 * **订阅续订** —— 续订前3天提醒 * **取消订阅** —— 取消确认 * **订阅到期前3天** —— 到期前3天提醒 * **订阅已到期** —— 到期后鼓励重新订阅 * **订阅更新** —— 订阅信息变更通知 * **订阅暂停** —— 暂停时发送通知 * **订阅重启** —— 恢复时发送通知 * **固定期限到期提醒** —— 固定期限结束前3天提醒客户 * **固定期限更新** —— 固定期限配置更新时通知客户 订单类: * **付款成功** —— 一次性或周期性收款成功后发送 * **付款失败** —— 自动收款失败时通知客户 * **退款成功** —— 发生退款时通知客户 可在 电子邮件 > 交易邮件 中单独启用或停用每类邮件。 可以。在 Subotiz 后台进入 电子邮件 > 交易邮件,每种邮件旁边都有独立的开关,可以单独开启或关闭,控制哪些通知发送给客户。例如,关闭订阅续订提醒,客户在续订前3天就不会收到提醒邮件,但不会影响其他类型的邮件发送。注意:停用某些交易邮件可能会影响相关订阅功能。例如,停用固定期限订阅到期提醒后,客户将无法收到订阅到期提醒,且即使已启用转为持续订阅功能,客户也不会收到包含转为持续订阅按钮的邮件,因此无法通过邮件一键转换订阅。 每种交易邮件都支持在发送前预览。进入 电子邮件 > 交易邮件,找到需要查看的邮件类型,点击预览邮件。预览页面会显示邮件的完整内容与排版。可以切换桌面端视图和移动端视图,查看邮件在不同设备上的展示效果。还可以使用发送测试邮件功能,将邮件发送至指定地址进行审阅,确保内容准确并符合品牌形象。 Subotiz 提供三种预设的营销邮件旅程: * **放弃订单挽留** —— 当客户进入结账页但未完成支付时触发,系统发送提醒邮件引导客户返回完成购买 * **结束试用召回** —— 当客户在试用期内主动取消订阅时触发,在试用结束后发送邮件引导其升级为付费订阅 * **订阅到期召回** —— 当客户关闭自动续费且订阅到期后触发,系统发送召回邮件推动客户重新订阅或恢复服务 三种旅程均只向在结账页授权接收营销邮件且行为符合触发条件的客户发送。 不会。营销邮件仅在同时满足两个条件时才会发送: 1. 客户必须已授权接收营销邮件——需要在结账页勾选营销邮件订阅选项。 2. 客户行为必须符合对应旅程的触发条件,例如放弃结账、试用期取消或到期未续费。 如果客户未勾选营销邮件订阅,无论其行为如何,都不会收到任何营销旅程邮件。营销邮件订阅勾选项的展示方式可在营销邮件模块的结账页订阅设置中配置。 折扣码在三种营销旅程中并非全部支持。结束试用召回和订阅到期召回两种旅程支持折扣激励,配置后当客户通过邮件中的链接返回结账页时,系统会自动应用对应折扣。放弃订单挽留邮件不支持折扣码。支持折扣的旅程,其折扣设置在对应邮件的创建页面内完成。这样商家可以针对召回和激活场景提供精准激励,而不影响所有结账会话。 不会。如果客户在营销邮件旅程进行过程中完成了新的订单或重新激活了订阅,该旅程中剩余的未发送邮件将自动停止。这避免了客户在已完成目标行为后仍收到无关的后续邮件。一旦系统检测到符合条件的行为,旅程立即停止——例如,放弃订单挽留旅程在客户完成结账后停止,订阅到期召回旅程在客户重新激活订阅后停止。 不可以。Subotiz 的营销邮件一旦创建就无法删除。但可以通过启用开关将其关闭,关闭后该邮件不会再发送给后续符合条件的客户。已关闭的邮件仍保留在系统中,可随时重新启用。如果某封邮件不再需要,最佳做法是保持关闭状态。每个旅程最多支持3封邮件,如需用不同内容替换,需要直接编辑现有邮件而非删除后重建。 不是。放弃订单挽留邮件仅支持托管式结账(Hosted Checkout)集成方式。如果您的店铺使用其他结账集成方式,放弃订单旅程将不可用。另外两种营销旅程——结束试用召回和订阅到期召回——没有此限制,与结账集成方式无关。如需使用放弃订单挽留邮件,请确认店铺已配置为托管式结账。 未配置自定义发件域名时,邮件可能显示为您的地址 via [subotizemail.com](http://subotizemail.com)——例如 [support@yourstore.com](mailto:support@yourstore.com) via [subotizemail.com](http://subotizemail.com),这会降低客户信任感和品牌专业度。配置验证后的自定义发件域名后,邮件仅显示品牌化发件地址,例如 [support@yourstore.com](mailto:support@yourstore.com),呈现专业可信的品牌形象。此外,已验证域名可提升邮件送达率——经过认证的发件方式可降低邮件被过滤为垃圾邮件的风险。如未配置自定义域名或发件邮箱,系统会使用店铺注册联系邮箱作为默认发件人。 强烈建议使用子域名(如 [mail.yourstore.com](http://mail.yourstore.com))而非主域名([yourstore.com](http://yourstore.com)),原因有两点: 1. 保护主域名信誉——交易类和营销类邮件有时可能产生垃圾邮件投诉、退信或被列入黑名单。使用独立子域名可有效隔离风险,避免影响主域名声誉。 2. 提升送达率——子域名支持独立配置 SPF、DKIM 和 DMARC 认证,帮助系统邮件更容易通过身份验证并进入收件箱。 域名验证失败通常有以下几个常见原因: * **DNS 传播延迟** —— 添加 DNS 记录后,通常需要等待30分钟至48小时才能全网生效,请在此期间后再尝试验证。 * **记录值填写错误** —— 请完全按照 Subotiz 提供的内容复制 TXT 和 CNAME 记录——不要添加空格、修改内容或包含 https\://。 * **SPF 记录重复** —— 同一域名只能有一条 SPF 类型的 TXT 记录。若已有 SPF 记录,需将 Subotiz 提供的 SPF 段合并到现有记录中,而不是新增一条。 * **子域名不匹配** —— DNS 中的主机名必须与在 Subotiz 填写的子域名一致——例如,发件域名为 [mail.shopdemo.com](http://mail.shopdemo.com),则 DNS 主机名应填 mail,而非完整域名或根域 @。 如需重试: 1. 进入 电子邮件 > 发件域名设置。 2. 找到状态为未验证或验证失败的域名。 3. 点击操作栏中的编辑。 4. 核对 DNS 记录是否正确。 5. 点击重新验证。 默认情况下无法收到。通过 Subotiz 创建的发件邮箱仅用于发送,无法接收来信。客户回复系统邮件后,回复不会直接到达您的 Subotiz 后台。如需接收客户回复,需要在域名注册商处配置邮件转发规则,将发件地址指向一个受监控的收件箱。这对于面向客户的发件地址(如 support@ 或 billing@)尤为重要。这是发件域名功能的一个限制——所有邮件发送正常,但收件功能需要在域名注册商处单独配置。 不是所有邮件。自定义发件域名适用于交易邮件(如订单通知、订阅更新、支付提醒)和营销邮件(如放弃订单挽留、试用召回、订阅到期召回)。但部分系统级别通知,例如密码重置邮件,仍会使用平台默认域名发送,不受自定义发件域名配置影响。 # 资金 Source: https://docs.subotiz.com/zh/faq/finance Subotiz 将账户资金分为三类: * **可用余额** —— 已完成结算、可用于提现的资金,结算完成后由待结算余额转入,受退款、手续费、保证金释放及调账影响。 * **待结算余额** —— 客户已付款但仍处于结算周期内(如 T+7)的资金,不计入可用余额,直至结算周期完成。 * **保证金** —— 按风控规则预留、预留期间不可用的资金。分两种:流动保证金(按每笔交易比例预留,周期结束后自动释放)和固定保证金(按固定金额预留,适用于长期风控要求的账户)。 客户付款在 Subotiz 中经过四个步骤: 1. 客户完成支付后资金立即进入待结算余额。 2. 系统自动扣除手续费并计算保证金。 3. 结算周期结束后(如 T+7),净金额转入可用余额。 4. 退款、拒付或调账会根据发生时间从待结算或可用余额中扣减。 净金额计算:净金额 = 交易金额 − 手续费 − 保证金。 余额页面显示12种交易类型: * **批量结算入账** —— 多笔交易合并一次结算 * **保证金留存** —— 按规则预留资金 * **保证金释放** —— 预留期结束后释放 * **提现** —— 转账至商户银行账户 * **提现手续费扣除** —— 提现费用 * **提现结汇手续费** —— 提现货币换算费用 * **资金返还** —— 退回给客户的资金 * **余额扣款** —— 账户余额扣减 * **资金充值** —— 客户支付成功入账 * **调账** —— 平台余额调整 * **活跃账户费扣除** —— 平台服务费 * **负余额充值** —— 抵扣负余额的扣款 按以下顺序逐步排查: 1. **确认结算周期** —— 检查交易是否仍在结算周期内,尚未转入可用余额。 2. **核查保证金** —— 进入 资金 > 余额 > 保证金 > 查看,确认是否有保证金占用资金。 3. **核对手续费** —— 在余额页面打开交易详情确认扣费。 4. **排查退款或拒付** —— 会根据发生时间从待结算或可用余额扣减。 5. **对比对账报表** —— 使用 资金 > 余额 > 查看对账报表核对周期汇总。 使用余额页面的交易类型和时间筛选定位相关记录。 资金显示在待结算余额是因为仍处于结算周期内(如 T+7)。资金只有在结算周期结束后才会转入可用余额。如需核查,进入 资金 > 余额,点击 待结算余额 > 查看。页面顶部显示配置的结算周期,列表展示每笔未结算交易的交易时间、原始金额、手续费和净金额。结合交易时间和结算周期判断预计到账时间。若交易仍在周期内,无需操作,周期结束后自动转入。 两者都是按风控规则预留的资金,但运作方式不同: * **流动保证金** —— 按每笔交易金额的一定比例预留,达到设定持有周期后自动释放,预留金额随交易量变化。 * **固定保证金** —— 按账户要求冻结固定金额,通常用于风险管理或合规目的,冻结金额不随单笔交易变化,在账户条件满足前持续冻结。 如需查看,进入 资金 > 余额 > 保证金 > 查看,切换流动保证金和固定保证金标签。 进入 资金 > 余额 查看交易记录列表。找到需要核查的交易,点击该行右侧的查看图标,打开交易详情页面。详情页显示完整资金构成: * **收款** —— 客户支付金额 * **退款** —— 如有 * **调整** * **手续费** —— 扣除的费用 * **保证金** —— 按规则预留的资金 * **保证金释放** —— 已释放并重新计入结算的保证金 下方结算明细列表展示每条记录的交易时间、类型、原始金额、手续费、保证金和净金额。注意查看图标仅在支持的交易类型中显示。 进入 资金 > 余额,点击右上角 查看对账报表。选择时间范围后报表自动更新。提供两种下载方式: * **下载明细** —— 提供逐笔交易记录,用于详细核对——适合追溯单笔交易、核对手续费或确认保证金金额。 * **下载报表** —— 提供汇总数据,用于财务统计与分析——适合周期汇总、财务报告和统计分析。 报表还展示所选时间范围的期初余额、按交易类型分组的资金变动明细和期末余额。 净结算金额计算公式为:净金额 = 交易金额 − 手续费 − 保证金。例如,客户支付 100 美元,扣除 3 美元手续费并预留 5 美元保证金,进入结算流程的净金额为 92 美元,在结算周期结束后转入可用余额。手续费根据支付方式和配置费率自动扣除,保证金按账户保证金规则预留。 当账户扣款超过可用资金时会出现负余额。常见原因: * **退款超额** —— 退款金额超过当前待结算或可用余额。 * **拒付资金回退** —— 争议导致资金被扣,可能产生额外拒付费用。 * **费用扣减** —— 手续费或调账导致余额低于零。 出现负余额时,Subotiz 会自动进行负余额扣款抵扣,在余额页面显示为负余额充值交易类型。使用交易类型筛选找出导致余额下降的具体交易,并结合对账报表进行核对。 差异属正常现象,原因有以下几点: * **数据范围** —— 余额页面显示实时余额,对账报表按周期统计,仅覆盖所选时间范围内的已完成数据。 * **结算状态** —— 待结算资金不计入可用余额,在报表中的处理方式可能不同。 * **保证金影响** —— 仍在预留期内的保证金不计入可用余额。 * **费用差异** —— 货币换算或手续费时间可能影响显示金额。 如需准确对账,使用对账报表匹配核查周期,若汇总不一致则通过下载明细逐笔排查。 流动保证金在配置的持有周期结束后会自动释放,无需商家进行任何操作。系统会自动处理释放并将资金转回余额或结算流程。如需查看当前状态和释放时间,进入 资金 > 余额 > 保证金 > 查看,选择流动保证金标签。每笔交易记录会显示保证金金额和当前状态。释放后,资金会在余额页面以保证金释放交易类型显示。 在对账报表中,期初余额是所选时间范围开始时的账户可用余额,期末余额是所选时间范围结束时的账户可用余额。结合中间的本期对账明细,这三部分共同构成完整的周期账务视图:起点、按交易类型分组的所有资金变动,以及终点。这一结构方便商家验证:期初余额 + 所有收入 − 所有支出 = 期末余额,便于与银行账单或账务记录进行核对。 可以。待结算页面支持导出交易数据: 1. 进入 资金 > 余额,点击 待结算余额 > 查看,打开未结算交易列表。 2. 在列表中勾选需要导出的记录。 3. 点击页面右上角的导出按钮生成数据文件。 4. 处理完成后下载文件,用于对账或分析。 当需要向财务团队提供未结算交易的详细记录时,此功能非常实用。 Subotiz 提现有三种状态: * **待划款** —— 提现已触发,系统已生成提现记录并完成可用余额扣减,等待后续处理。 * **划款中** —— 提现已进入当日处理流程,状态将在划款日内更新。 * **已划款** —— 平台已完成该笔提现的打款处理,平台侧流程结束。 注意:提现状态不包含「已到账」或「失败」等最终到账确认状态,平台无法实时获取银行侧到账结果。如需确认最终到账情况,请以银行流水为准。 不会。Subotiz 提现状态仅反映平台侧的处理进度,不包含最终银行到账确认。状态中不含「已到账」或「失败」,因为平台无法实时获取银行侧的到账结果。已划款状态表示平台已完成打款处理,不代表资金已到达银行账户。如需确认最终到账情况,请直接查看银行流水。Subotiz 提现详情页面仅用于记录核对,不作为银行到账凭证或结算证明。 不需要。提现记录由系统自动生成,商家无需手动发起。在当前规则下,提现记录通常在以下情况触发:平台可用余额达到或超过 USD 500,或到达系统约定的定时处理节点(如每周一 9:00,UTC+8)。如遇商户主体所在国家或地区的法定节假日或非工作日,处理节点可能根据实际情况调整或顺延。若商家在未满足自动提现条件的情况下主动向客服申请提现,系统将按规则收取固定提现手续费,相关费用会体现在提现记录中。 当提现进入系统约定的定时处理流程时,状态从待划款变为划款中。在当前规则下,这通常发生在每周一 9:00(UTC+8)的定时处理节点。处于待划款状态时,提现记录已创建且对应金额已从可用余额扣减,但转账尚未发起。到达处理节点后状态更新为划款中,并在划款日内进一步更新。如遇法定节假日或非工作日,处理时间可能调整或顺延。 如需导出提现记录,在 Subotiz 后台进入 资金 > 提现,在提现页面点击导出按钮。系统会下载包含该笔提现所有交易记录的 CSV 文件。导出文件通常包含多个工作表: * **余额明细表** —— 展示提现相关交易及其对账户余额的影响。 * **提现明细表** —— 展示该笔提现包含的交易记录、手续费及对应的余额变动情况。 这些文件可帮助核对提现计算方式、验证结算准确性,并辅助财务对账与数据核对。 会。如果在未满足自动提现条件的情况下(例如可用余额未达到 USD 500 或尚未到达定时处理节点)主动向客服申请提现,系统将按规则收取固定提现手续费。相关费用会体现在对应的提现记录中。在正常自动提现条件下,如有适用手续费也会显示在提现记录中。建议商家在提现列表中查看提现手续费字段,确认每笔提现实际收取的费用。 Subotiz 提现详情页面显示: * 提现金额 * 发起时间 * 完成时间(如已划款) * 提现 ID * 当前状态 * 相关备注信息(如有) 该页面仅用于查看平台侧的处理记录,不作为银行到账凭证或结算证明——它确认的是平台已完成打款处理,而非资金已到达银行账户。如需确认实际到账情况,请直接查看银行流水。 可以。提现页面支持使用三个筛选条件: * **提现 ID** —— 输入指定提现 ID,用于查找单笔提现记录。 * **提现状态** —— 按处理状态筛选记录——待划款、划款中或已划款。 * **日期范围** —— 按提现发起时间筛选指定时间段内的记录。 多个筛选条件可以组合使用,进一步缩小范围。这些筛选功能适用于查看历史提现数据和进行对账核对。进入 资金 > 提现,使用页面顶部的筛选工具操作即可。 Subotiz 不直接执行币种转换。所有交易以商户在 Subotiz 后台设定的主要结算币种进行结算。当客户使用其他币种付款时,由支付供应商(如 PayPal 或 Airwallex)在结算阶段完成币种转换,根据结算时的汇率将金额转换为商户的主要结算币种后返回给 Subotiz。Subotiz 以主要结算币种记录并展示换算后的金额。因此,余额、提现和发票等页面显示的金额均为主要结算币种,无需商家手动换算或操作。 结算币种在账户注册时选择。一旦账户下已创建交易,结算币种将无法更改。这是因为现有的账单记录、发票和提现计算均与最初选择的币种绑定。如果需要以不同的结算币种运营,需要创建一个新商店并选择所需的币种设置。如需进一步协助,请通过 [merchant-service@subotiz.com](mailto:merchant-service@subotiz.com) 联系 Subotiz 支持团队。 退款对结算余额的影响取决于退款处理的时间与结算周期的关系: * **如果退款在结算前完成** —— 退款金额从当前待结算余额中扣除,下一笔结算的可用金额相应减少。 * **如果退款在结算后完成** —— 退款金额在下一笔结算中进行调整,从下一笔可用余额中扣减,而不是从已结算金额中扣回。 无论哪种情况,退款都会自动反映在 Subotiz 后台的余额和提现记录中,无需手动调整。 # 发票 Source: https://docs.subotiz.com/zh/faq/invoices Subotiz 为每张发票分配一个发票类型,用于标识产生扣费的账单场景。可用类型包括: * **一次性支付** —— 客户完成一次性商品购买时生成。 * **免费试用** —— 在需要支付方式的免费试用流程中生成,如试用激活或支付方式收集。 * **订阅创建** —— 订阅首次创建并完成首次扣款时生成。 * **订阅续订** —— 订阅在计费周期开始时自动续订时生成。 * **订阅变更扣款** —— 订阅升级、降级或修改并产生额外费用时生成。 * **订阅激活** —— 订阅激活并产生计费扣款时生成。 发票类型仅用于业务识别,不影响支付状态或结算结果。 Subotiz 共显示七种发票状态: * **成功** —— 支付已成功完成。 * **失败** —— 支付尝试未成功。 * **待支付** —— 发票已生成但支付尚未完成。 * **支付处理中** —— 支付正在处理中,等待确认。 * **重试中** —— 订阅续订支付失败,当前处于自动重试周期内,状态会根据重试结果自动更新。 * **已退款** —— 发票全额已退款。 * **部分退款** —— 发票金额的一部分已退款。 发票状态反映当前的支付或退款状态,与反映账单场景的发票类型是不同的字段。 在 Subotiz 后台的发票模块中,可以通过多种方式搜索和筛选发票: * 通过搜索栏按客户邮箱或发票 ID 搜索。 * 按状态筛选,查看特定支付或退款状态的发票,如成功、失败、重试中或已退款。 * 按发票类型筛选,查看特定账单场景的发票,如订阅续订或一次性支付。 * 按时间范围筛选,将结果缩小到特定时间段。 多个筛选条件可以组合使用。点击任意发票行可进入完整的发票详情页,查看完整账单和支付信息。 不是所有发票都可以。生成正式发票文件仅适用于以下三种状态的发票:成功、全部退款、部分退款。状态为失败或仍处于处理中的发票(如待支付、支付处理中、重试中)不支持生成发票文件。 如需生成发票: 1. 进入 Subotiz 后台的发票模块。 2. 打开符合条件的发票。 3. 点击右上角的生成发票按钮。 系统会自动生成 PDF 文件并下载至本地。 不会。在生成发票时对收票人信息(姓名、邮箱和账单地址)所做的修改,仅作用于当次生成的发票文件,不会修改客户资料或任何历史账单记录。这些字段默认基于发票记录和客户资料预填充,但您所做的任何修改仅限于当次生成的 PDF 文件。这样商家可以根据账务或税务需求灵活调整发票信息,而不影响客户数据。 可以。同一张发票记录可以多次生成 PDF 文件,不限次数。每次生成时都可以更新或调整收票人信息。重复生成发票文件不会对支付结果、退款状态或订阅关系产生任何影响,纯属文件生成操作。请注意,历史已生成的发票文件不会自动更新,每份文件反映的是生成时的信息。 生成的发票 PDF 包含以下信息: * 发票编号 * 支付方式与支付时间 * 货币代码 * 发票主体信息(Merchant of Record 模式下显示开票主体,非 MOR 模式可能不显示) * 收票人信息(姓名、邮箱和账单地址) * 项目明细(单价、数量、折扣和金额) * 小计与总金额 * 退款信息(如适用) 对于部分或全额退款的发票,退款明细和调整后的最终金额会反映在文件中。发票主体信息来源于企业资料,保持企业信息最新可确保发票准确、规范。 当订阅续订支付失败时,Subotiz 会激活智能重试(Smart Retry)机制,发票状态会设置为重试中而非失败。这个状态表示首次支付失败,但系统当前仍在自动重试周期内,会根据智能重试计划再次尝试扣款。发票状态会根据重试结果自动更新:如果某次重试成功,状态变更为成功;如果所有重试均失败,状态更新为失败。在重试中状态期间,商家无需进行任何操作。 不可以。退款无法直接从发票页面发起。Subotiz 中的所有退款都通过对应的交易单进行处理。 如需发起退款: 1. 前往交易单模块。 2. 找到对应的订单。 3. 从那里发起退款操作。 退款完成后,发票状态会自动更新以反映退款结果——全额退款后变为全部退款,部分退款后变为部分退款。退款失败时发票状态保持不变。发票页面仅用于查看账单记录和生成发票文件。 不是,零金额发票不是系统错误。Subotiz 在某些特定场景下可能会生成金额为 \$0 的发票。主要有两种情况: 1. 在订阅续订场景下首次生成 \$0 发票时:系统仍可能发起支付流程,用于完成或验证支付方式绑定。支付网关确认成功后(即使金额为 \$0),发票状态会更新为成功。 2. 对于一次性购买或已绑定支付方式的场景,无需进行支付方式验证时:系统直接生成发票并标记为成功,不会触发支付流程,也不会生成对应的支付记录。 零金额发票是正常的账单行为,用于准确记录该计费事件。 # 商品 Source: https://docs.subotiz.com/zh/faq/products 在 Subotiz 中,商品和定价方案各自承担不同职责。商品用于定义销售内容——例如 SaaS 服务、数字内容或会员订阅——包含商品名称、类型、图片和描述等信息,本身不包含价格信息。定价方案用于设置客户购买该商品的具体收费金额与计费周期。每个定价方案必须绑定一个商品,一个商品可以配置多个定价方案。例如,商品「团队版」可以对应「团队版·月付 \$30」和「团队版·年付 \$300」两个定价方案。 不会。如果商品已被订单、发票或订阅引用,修改后系统会创建新的商品版本(product\_version\_id),而不会修改现有数据。历史订单、发票和订阅保存了原始商品信息快照,会继续引用原有版本。已存在的订阅将按照原商品版本继续续费。只有修改后新创建的订单、结账或订阅才会使用更新后的商品版本。创建新商品版本时,系统会同步生成新的定价版本以确保一致性。 Subotiz 中商品有三种状态: * **已激活** —— 商品已启用,可被定价方案引用、用于生成付款链接并参与结账流程。 * **未激活** —— 商品已创建但尚未启用,不可参与结账或生成付款链接,但仍可继续编辑并随时激活。 * **已归档** —— 软删除状态,商品从列表中移除,但历史记录仍可查询。商品归档时,其关联的定价方案将一并归档。已归档商品无法恢复。 Subotiz 支持九种商品类型: * SaaS 订阅 * 软件(包括 AI 工具) * 在线视频内容 * 信息服务 * 电子书 * 数字图形或模板 * 电子游戏 * 区块链数字商品 * 其他数字商品 对于通过互联网提供、无需本地安装的订阅制软件服务,应选择 SaaS 订阅。SaaS 定义为云端托管、多租户结构、按月或按年周期计费,由服务商负责维护与安全的订阅式软件。商品类型用于后台分类与报表统计,正确选择有助于确保计费逻辑与财务报表的一致性。 SaaS 订阅和软件都与软件产品相关,但代表截然不同的交付方式和计费模式。SaaS 订阅是通过云端托管、多租户结构在线提供的订阅制软件,无需本地安装,通常按月或按年周期计费,服务商负责维护、更新和安全。软件指可下载或授权安装在用户设备上的软件,通常为一次性购买或永久授权,可附加维护或升级服务。核心区别在于交付方式:云端订阅访问(SaaS)vs 本地安装授权(软件)。 在 Subotiz 中创建商品时,必填字段和可选字段如下: * **必填字段:** * 商品名称(显示在结账页面和收据中) * 商品类型(用于后台分类与筛选) * **可选字段:** * 商品图片(JPG、PNG 或 WEBP 格式,不超过 2MB) * 商品描述(简要说明商品内容) * 权益标签(最多20个定量或定性权益) 商品 ID 由系统自动生成,无需手动输入。权益标签仅在结账页面或发票中展示,不影响实际计费逻辑或使用限制。 保存新商品时有两种选项: * **创建并激活** —— 会立即启用商品,使其可用于定价配置、结账流程和发票生成。 * **保存** —— 将商品以未激活状态保存,仅用于后台管理。未激活商品不会出现在定价配置中,不可用于新订单结账,但可以继续编辑并随时激活。 如果暂时还不需要开放结账,选择保存,待需要时再激活即可。 Subotiz 中的商品权益标签是添加到商品上的描述性内容,用于向客户说明购买后获得的服务内容。权益标签仅在结账页面或发票中展示,仅供参考。 支持两种类型: * **定量权益** —— 用于有明确数量或次数限制的服务,如课程数量、下载次数或使用额度 * **定性权益** —— 用于仅描述服务内容、不涉及具体数量的权益,如会员访问权限、社区论坛权限或专属服务 每个商品最多支持添加20个权益标签。重要提示:权益标签不影响计费逻辑、使用限制或任何系统层面的控制,仅用于信息展示。 停用商品时,该商品下所有关联的定价方案将一并停用。商品变为未激活状态,定价方案无法再用于新的结账流程或订单,也无法生成新的付款链接。但历史订单保持不变,已存在的订阅仍按原条款继续续费。如果之后需要重新使用该商品,可以重新激活,其定价方案也需要相应重新激活。 不可以。商品删除后无法恢复,会从商品列表中永久移除。但引用该商品的历史订单记录会被保留,仍可查询——删除操作仅将商品从活跃商品管理界面移除。删除前请确认该商品不再需要,并已查看所有相关业务记录。如果只是不想用于新交易而非永久移除,建议选择停用或归档。 不会。定价方案的修改仅影响后续新交易,不影响已有订单或有效订阅。例如将月费从 \$30 调整为 \$40 后,现有订阅用户仍按 \$30 续费,修改后新创建的订阅则按 \$40 计费。这一机制确保现有客户不会因价格调整受到意外影响,同时允许商家立即为新客户应用新价格。 可以。当定价方案被停用或归档后,已在该方案下的订阅用户不受影响,可以继续使用并正常续费。下架定价方案只意味着新用户无法在结账时选择该方案。这一机制确保现有客户的业务连续性,同时允许商家逐步停止向新用户提供旧定价选项。 Subotiz 定价方案支持两种收费方式: * **周期性订阅** —— 适用于持续收费的订阅服务,如 SaaS 月费或年费,支持试用期(免费或付费)、前期自定义定价以及自动续费。 * **单次付费** —— 适用于一次性收费场景,如服务开通费或终身授权,仅收取一次费用,不产生周期性续费或订阅。 同一商品可以同时配置周期性订阅和单次付费两种定价方案。 会。归档定价方案会阻止其被用于新的订单、订阅或结账,但不影响已存在的有效订阅。已在该方案下的订阅将继续按照原定价配置续费。历史订单和发票同样保持不变。归档后的方案不再显示于列表页面,也无法通过搜索查找,但所有关联的历史数据仍可查询。 两种试用类型都会推迟首次正式订阅扣费,但区别在于试用期本身是否收费: * **免费试用** —— 试用期间不收费,试用结束后系统自动按标准订阅价格开始计费。例如,5月1日开始7天免费试用,首次扣费日期为5月8日。 * **付费试用** —— 在试用期间按设定的试用价格收费,试用结束后自动切换为标准周期性计费。例如,7天试用收取\$5,之后按月标准价格扣费。 两种试用类型均支持设置每位客户仅可享受一次试用,避免重复使用。 固定定价订阅方案中的前期定价允许为早期计费周期设置最多三条自定义价格规则,按顺序依次应用后恢复标准价格。每条规则需要设置周期区间(如第1–2期),区间必须连续且不可重叠。前期定价结束后,系统自动按标准价格继续计费,无需手动操作。例如:第1–2期 \$50,第3–4期 \$75,第5期起恢复标准价格 \$100。 Subotiz 周期性订阅定价方案支持四种计费周期: * 每周(7天) * 每月(31天) * 每季(93天) * 每年(365天) 系统会按所选周期自动扣费。对于套餐定价方案,还可选择客户发起支付选项,关闭自动续费,由客户手动发起每次支付。 套餐定价方案是一种基于每个计费周期内预设数量或捆绑内容进行计费的周期性订阅模式,而非仅基于固定价格。适用于每个周期包含固定使用量的商品,如课程包(每月10节课)、下载次数包或积分套餐。固定定价方案更适合价格稳定且无数量差异的商品。核心区别在于:套餐定价需要定义每周期的包含数量,而固定定价仅定义每周期的收费金额,不涉及使用量。 两种模式都用于按单价计费,但区别在于发票的生成时机: * **按周期出账** —— 在固定计费周期(周/月/季/年)内累计使用量,周期结束时系统根据总使用量自动生成发票,无需设置阈值。 * **按阈值出账(Threshold billing)** —— 费用持续累计,不依赖固定周期结束,当累计费用达到设定阈值(如 \$50)时自动生成发票,出账后重新开始新的累计周期,需要设置阈值。 按周期出账适合需要规律性出账的场景,按阈值出账适合使用量较大、希望比完整计费周期更频繁出账的场景。 两种模式都是按不同用量区间设定单价的阶梯定价模型,但计费方式不同: * **批量计价** —— 账单周期内的所有用量按总用量所属区间的统一单价计算。例如客户使用450 GB,落入第2档(101–500 GB,\$0.15/GB),所有450 GB均按 \$0.15 计费,总计 \$67.50。 * **分段计价** —— 用量按各区间分别计费。同样示例:前100 GB按 \$0.20 = \$20.00,后350 GB按 \$0.15 = \$52.50,总计 \$72.50。 批量计价更简单,达到高档位后通常费用更低。分段计价更精细,按实际用量分段递减计价。 两种状态都会使定价方案无法用于新订单,但在可见性和可恢复性上有所不同: * **未激活** —— 定价方案无法用于新的结账或发票流程,但仍显示在定价列表中,可通过搜索查找,并可随时重新激活。已有订单和订阅不受影响。 * **已归档** —— 定价方案从默认列表中永久移除,无法通过搜索查找,不可用于新订单或结账。但历史订单、订阅和相关数据仍可查询。归档通过定价管理界面的删除操作触发。 如果以后可能重新使用,选择未激活;如果永久停用,选择归档。 无法生成支付链接通常有两个原因: 1. 定价方案必须处于已激活状态——分享商品功能仅在定价方案已激活时可用,未激活或已归档的方案无法使用分享功能。 2. 必须完成 Webhook 配置才能生成支付链接——如果不存在已激活的 Webhook,系统将提示无法生成支付链接。 解决方法:激活定价方案,并参照 Webhooks|为支付链接快速配置 完成 Webhook 设置。 可以。Subotiz 中一个商品可以同时支持多种不同收费方式的定价方案。例如,可以在同一商品下配置周付订阅、月付订阅和终身一次性付费三种方案。每个定价方案独立运行——客户在每次结账时选择其中一个方案,订单、发票和订阅基于所选方案生成。这样无需为不同计费方式重复创建商品。注意:单次付费方案不涉及试用期和计费周期,这两个字段不会显示。 用量计费方案(单价制或阶梯价格)在结账页面不会显示固定应付金额,这是系统的预期行为。由于费用基于实际使用量计算,在计费周期结束或达到计费阈值前无法确定最终金额,因此结账时无法展示固定收费。结账页面会展示计费方式(基于用量计费)、计费周期(如适用)以及单价信息(如每次费用或每单位价格)。建议在定价方案描述中清晰说明计费规则,帮助客户在订阅前了解收费方式。 客户发起支付是套餐定价方案中的一个选项,启用后会关闭自动续费。在普通周期性订阅中,系统会在每个计费周期结束时自动扣款,无需客户操作。选择客户发起支付后,系统不会自动续费,需要客户手动发起每次支付才能继续订阅。该选项适用于希望客户主动确认每个计费周期而非被动自动扣费的场景。注意:该选项仅适用于套餐定价方案,固定定价方案和用量计费方案不支持此选项。 已有的有效订阅将继续使用原始价格,不受修改影响。当一个已产生交易或订阅的定价方案被修改时,系统会自动创建新的价格版本(price\_version\_id)以保护历史数据。已有订阅继续按照原价格版本计费,修改后新创建的订单和订阅才会使用新版本价格。如需确认某笔订单或订阅使用的具体定价,可进入其详情页查看当时生效的计费配置。 商品管理页面支持搜索与筛选功能,帮助快速定位商品。可通过关键词搜索商品名称或商品 ID;也可按商品类型(如 SaaS、软件、电子书、信息服务等)或状态(已激活或未激活)进行筛选。多个筛选条件可以组合使用,进一步缩小范围。商品列表中会显示商品名称、商品 ID、商品类型、状态及创建时间。 Subotiz 中的商品 ID 由系统自动生成,不支持手动设置或修改。商品 ID 用于系统内部识别,会显示在商品列表和详情页中。如需使用自定义编号,可在商品名称或描述字段中注明。商品 ID 同时支持作为搜索参数,可在商品管理页面通过 ID 快速定位对应商品。 进入 商品 > 商品定价,点击目标定价方案名称进入详情页,可查看该方案的完整配置及关联商品信息。如该方案已产生订单或订阅,停用操作不会影响现有订阅——已有订阅会继续按原条款执行。停用仅会阻止该方案被用于新的结账或订单。如需判断是否仍有活跃订阅,可结合订阅模块筛选对应定价方案进行确认。 价格表是一种展示与分发工具,将多个定价方案整合到同一页面,通过单一链接或 iframe 嵌入代码进行分享。与单个定价方案支付链接只展示一种计费选项不同,价格表支持客户在同一页面对比多个方案(如周付、月付、一次性购买),选择后直接完成结账。价格表不会修改原有定价方案的配置,仅作为基于现有已激活定价方案的展示与分发层。 价格表仅支持添加状态为已激活的定价方案。 在定价类型方面,目前仅支持以下两种: * 一次性付费方案 * 周期性订阅中的固定定价方案 套餐定价和基于用量的定价(单价制和阶梯价格)暂不支持在价格表中展示或使用,无法添加至价格表。 创建价格表前需要确认两项设置已完成: 1. 需要至少一个已激活状态的定价方案——价格表只能添加已激活的定价方案。 2. 必须完成 Webhook 配置。价格表依赖 Webhook 接收支付结果通知,未完成配置时将无法创建价格表。进入 开发者 > Webhooks,创建 Webhook 并填写有效的 Endpoint URL。 完成配置并启用后即可使用价格表功能。 有限制。每种计费周期(如每周、每月、每年)在同一价格表中最多支持添加4个定价方案。该限制按计费周期类型分别计算,而非整个价格表的总数。例如,同一价格表中可以有最多4个月付方案和最多4个年付方案。此限制旨在保持页面展示简洁,避免每个周期选项过多影响客户决策。 归档和删除价格表在影响范围和可恢复性上有所不同: * **归档** —— 价格表停止用于结账,但仍保留在后台,可随时重新启用。关联的分享链接和嵌入代码同时失效,但列表本身被保留。 * **删除** —— 价格表被永久移除,所有关联的结账链接和嵌入代码立即失效,且无法恢复,操作不可撤销。 如果以后可能重新使用,选择归档;确认永久停用才选择删除。 有效。编辑价格表内容(如修改名称、标题、描述或展示样式)不会使已分享的结账链接或嵌入代码失效。修改保存后立即生效,现有链接会自动展示更新后的内容。链接仅在价格表被归档或删除后才会失效。如需调整价格表中的定价方案或展示设置,可直接在详情页修改,已分享的链接会自动反映最新配置。 价格表保存并启用后,Subotiz 会自动生成结账链接和 iframe 嵌入代码两种分发方式。如需将价格表嵌入网站,进入价格表详情页,复制 iframe 嵌入代码,将其粘贴至网站页面或第三方落地页的 HTML 中即可。价格表会以内嵌形式展示在页面中,客户可直接在页面内对比方案并完成结账,无需跳转。同一嵌入代码持续有效,直至价格表被归档或删除。 可以。在创建或编辑价格表时,Subotiz 提供桌面端与移动端两种布局的预览功能。可以在分享链接或发布嵌入代码之前,确认按钮颜色、字体及整体布局在不同设备上的展示效果是否统一、专业。预览功能在价格表配置页面的展示设置完成后即可使用。 价格表名称和标题用途不同,面向的受众也不同。价格表名称是内部管理标签,仅显示在 Subotiz 后台的价格表列表中,方便商家自己识别和管理,客户不会看到。标题是面向客户的展示内容,显示在价格表页面上,例如选择适合您的订阅方案,客户打开分享链接或查看嵌入页面时看到的就是这个标题。创建价格表时,名称用于内部管理,标题用于向客户清晰传达方案信息。 支持。Subotiz 支持混合定价,允许商家在同一个订阅方案中组合不同的定价结构。例如,一个方案可以包含每个计费周期收取的固定基础费用,以及根据实际使用量收取的可变用量费用。这对于有固定底价加变动用量费用的 SaaS 产品非常实用。混合定价可以在后台 商品 > 商品定价 中创建或编辑定价方案时进行配置。 # Subotiz Accounts Source: https://docs.subotiz.com/zh/faq/subotiz-accounts 外汇兑换是 Subotiz Accounts 提供的实时多币种兑换功能,支持商户使用账户余额将一种货币兑换为另一种货币,无需通过第三方平台或线下银行办理。系统根据实时汇率计算预计兑换金额,确认交易后立即完成兑换。兑换后的资金可用于全球付款、人民币结汇及其他资金管理场景。 常见场景: * 将美元换欧元支付欧洲供应商货款 * 将美元换英镑支付英国广告费 * 将外币换离岸人民币用于结汇 * 根据业务需求调整不同币种资金配置 Subotiz Accounts 目前支持以下9种主流币种之间的实时兑换: * **USD** —— 美元 * **EUR** —— 欧元 * **GBP** —— 英镑 * **HKD** —— 港币 * **CNH** —— 离岸人民币 * **SGD** —— 新加坡元 * **CAD** —— 加拿大元 * **AUD** —— 澳大利亚元 * **JPY** —— 日元 9种币种均可相互兑换,共72种两两兑换组合。实际支持的币种及兑换组合以后台页面显示结果为准。 外汇兑换不额外收取手续费。页面在提交前显示的兑换汇率即为本次交易的实际成交汇率,商户可在确认前查看兑换成本。页面汇率参照主流银行实时报价,秒级刷新,完全透明可查。 单笔最低兑换金额为等值 0.01 美元。当前无单笔最高兑换金额限制。如单笔兑换金额超过等值 100 万美元,建议提前联系客户经理,以便平台提前安排处理,确保流动性。 1. 前往 资金 > Subotiz Accounts,点击外汇兑换。 2. 选择卖出币种和买入币种,页面同步显示对应可用余额。 3. 输入兑换金额,系统按实时汇率自动计算预计兑换金额。 4. 查看汇率、预计兑换金额和汇率倒计时,确认后点击提交。 5. 在确认页核对锁定汇率、卖出金额和买入金额,输入6位交易密码后点击确认。 完成后对应币种余额立即更新,资金可立即使用。注意:首次使用前需先完成交易密码设置。 发起兑换后,系统自动锁定当前汇率45秒,供商户在确认前查看明细和输入交易密码。在锁定窗口内,汇率是保证的——兑换将按锁定汇率成交。如45秒内未完成确认,系统自动刷新汇率,需重新查看更新后的预计金额再确认。交易确认后不可撤销或修改。 兑换成功后资金瞬时到账,交易确认后对应币种余额立即更新,无需等待。兑换后的资金可立即用于后续外汇兑换、全球付款、人民币结汇及其他资金管理操作。 不支持。Subotiz Accounts 的外汇兑换目前仅支持按实时市场汇率即时成交,暂不支持挂单、预约兑换、远期交易合约或其他延时交易模式。 前往 资金 > Subotiz Accounts > 外汇兑换,点击换汇交易页签查看所有历史兑换记录。 每条记录显示: * 订单号 * 创建时间 * 当前状态 * 卖出金额及币种 * 汇率 * 买入金额及币种 * 操作入口 可按订单号、卖出/买入币种、交易状态及时间范围筛选。点击详情可查看完整信息,包括锁定汇率、创建时间和处理时间。 外汇兑换记录有三种状态: * **处理中** —— 兑换申请已提交,正常情况下即时完成;如渠道出现异常,交易可能暂时显示为处理中,请等待系统完成处理。 * **成功** —— 兑换已完成,卖出币种余额已扣减,买入币种余额已增加,资金可立即使用。 * **失败** —— 本次兑换未完成,系统不会扣减对应币种余额,商户可重新发起兑换。 如无法提交兑换申请,请检查以下情况: * 卖出币种可用余额是否充足——余额不足时无法提交 * 页面汇率是否已过期——45秒锁定到期后汇率自动刷新,需重新确认金额 * 是否已完成交易密码设置——首次使用前必须先完成设置 * 资金是否处于待处理或待提交材料状态——此类状态的资金暂不可用于外汇兑换 每笔外汇兑换在确认页需要输入6位交易密码进行二次验证。首次使用外汇兑换前必须先完成交易密码设置。如果忘记了交易密码,前往 资金 > Subotiz Accounts > 设置 > 全局设置 重新设置交易密码。重置完成后即可重新发起兑换。 不可以。兑换一旦确认提交,无法撤销或修改。请在确认页仔细核对锁定汇率、卖出金额和买入金额后再提交。45秒的汇率锁定窗口为商户提供了足够的核对时间。如兑换提交后失败,系统不会扣减对应币种余额,商户可重新发起兑换。 # Subotiz Payments Source: https://docs.subotiz.com/zh/faq/subotiz-payments Subotiz Payments 是 Subotiz 体系内的自有支付产品,专为数字内容、虚拟商品和订阅型业务商户设计。与需要单独集成的第三方支付供应商不同,Subotiz Payments 直接内置于 Subotiz 后台,商户可在同一平台内管理支付、订阅、结算和合规。支持主流国际信用卡网络(Visa、Mastercard、American Express、JCB)、Apple Pay、Google Pay、BNPL 及多种本地化支付方式。内嵌 AI 智能引擎,用于智能路由、失败重试、风险识别和客户生命周期自动化。商户直接在 Subotiz 后台申请,通常 4 个工作日内获得审核结果。 在 Subotiz 后台直接提交 Subotiz Payments 开通申请后,在资料完整的情况下,通常可在 4 个工作日内获得审核结果。审核通过后,系统会自动激活支付能力。商户可在 设置 > 支付方式 中启用支付方式,并在同一后台集中管理交易、结算与对账信息。拒付和争议处理也在平台内完成,无需多系统切换。 Subotiz 沙盒是一个独立的测试环境,允许商户在不影响真实业务、不产生实际交易的情况下完成账号注册、支付配置和完整收款流程测试。设置步骤: 1. 访问 [https://admin.sandbox.subotiz.com/](https://admin.sandbox.subotiz.com/) 完成账号注册。 2. 注册后进入 **设置 > 支付供应商 > 发现更多**,找到 Subotiz Payments 点击**立即申请**——系统立即激活测试支付渠道。 3. 进入 **设置 > 支付方式**,启用所需支付方式(如 Card 或 Apple Pay),点击**保存**。 沙盒流程与正式环境保持一致,适合正式上线前完整验证。请勿在沙盒中使用真实银行卡信息。 不是。在沙盒环境中,订阅计费周期会进行加速处理,方便快速验证订阅生命周期事件,无需等待真实时间间隔。加速后的周期为: * **日订阅** —— 约 10 分钟完成一个周期 * **周订阅** —— 约 70 分钟完成一个周期 * **月订阅** —— 约 310 分钟完成一个周期 这样商户可以快速测试续费、到期和订阅状态变化等流程。注意沙盒中的开通状态仅用于测试,不影响正式环境。 Subotiz Payments 收取以下费用: * **标准处理费** * 支付汇率转换费 —— 客户付款转换为商家结算币种时收取 2% * 转账汇率手续费 —— 结算资金转账至商家银行账户时如涉及币种转换收取 1% * **提现费用** * 自动提现(余额达到 USD 500 或以上,每周一处理)—— 美国本地转账免费,国际转账每笔 USD 20 * 手动提现(余额低于 USD 500)—— 每次收取 USD 5 * **活跃账户费** —— 当月有交易记录时收取 USD 5/月 * **争议费用** —— 争议/欺诈比例 ≤1% 时每笔 USD 15,高于 1% 时每笔 USD 20 * **账户级费用** —— 开户费 USD 500;账户变更(如变更主体或结算币种)每次 USD 500 支付汇率转换费(2%)在客户付款币种需要转换为商家结算币种时收取。避免此费用的方法是确保客户支付币种与结算币种一致——两种币种相同时,收款环节不会产生汇率转换费。同样,转账汇率手续费(1%)仅在将结算资金转账至银行账户时涉及币种转换时收取。选择与主要销售市场一致的结算币种,可以减少不必要的汇率转换成本并提升结算效率。 Subotiz Payments 的最低结算周期为 T+2。在此时间线下,成功交易的资金通常在付款日后两个工作日可进入结算阶段,不含周末和法定节假日。例如,周一完成的付款,周二和周三计为两个结算工作日,周三结束时资金进入可用余额。周五的付款(T+2)将跳过周末,下周二进入可用余额。您账户实际适用的结算周期取决于业务类型、交易表现、争议比例和账户风险等因素。当前结算周期可在 资金 > 余额 > 待结算余额 中查看。 Subotiz Payments 中的保证金是指已成功收款但暂时未进入可用余额的部分资金,用于覆盖退款、争议、拒付或其他交易后的资金调整。重要提示:保证金不是费用,这些金额将在既定周期结束后按政策自动释放至商家的可用余额。分两种类型: * **循环保证金** —— 按每笔交易金额的一定比例暂时扣留,达到固定天数后滚动释放 * **固定保证金** —— 为降低整体风险设定的固定金额,不与交易比例挂钩,随账户表现改善后可调整或释放 循环保证金按每笔交易单独计算。每笔交易结算时按固定比例扣留一部分资金,达到预定持有周期后,这些资金会以滚动方式自动释放归还。例如,设置为 10% 循环保证金、保留 30 天:3 月 1 日收到一笔 USD 200 的交易,扣留 USD 20 作为保证金。30 天后即 3 月 31 日,这 USD 20 自动释放并进入可用余额。这一机制在每个周期内形成稳定、可预测的扣留与释放节奏。所有保证金记录都在 Subotiz 后台余额模块中完整呈现,包含保证金类型、金额、交易时间及每周期的扣留或释放金额。 申请前需准备以下材料: * **企业资料** —— 官方网站链接、业务模式与产品描述、企业资质或注册证明文件。 * **董事资料** —— 公司董事或主要管理人员信息及对应身份证明文件。 * **受益人信息** —— 有限公司需填写直接或间接持股 25% 及以上的人员(无符合人员则填写实际控制人);合伙企业需填写所有合伙人资料。 * **提现账户** —— 绑定已有账户需提供近 6 个月银行对账单(显示账户名称、账号、日期、银行信息),或申请 Global Account 所需相关文件。 * **授信评估材料** —— 体现业务规模、收费模式和产品定价的页面链接或文件。 提前准备完整资料可显著缩短审核时间。 会。网站是 Subotiz Payments 审核流程中的必要部分。申请时需确认网站检查清单,验证以下内容: * 官网可正常访问 * 产品或服务描述清晰准确 * 已提供完整的政策页面(如退款政策、隐私政策) * 页面内容与实际业务一致 如果网站内容不完整、与业务模式不一致或页面无法访问,申请可能被退回要求补充材料或被暂停审核。在提交申请前完善网站内容,可降低审核延迟的风险。 可以。如果没有海外银行账户,可以在 Subotiz Payments 申请流程中申请 Global Account。在设置提现账户步骤中,选择申请 Global Account 而非绑定已有账户。需要选择默认提现币种,并确保提现账户所属地区与公司注册地一致。注意:公司注册地为中国大陆、中国香港以外的主体,需额外上传董事任命书及股权架构图。所有文件需清晰完整,信息与前述企业及受益人信息保持一致。 活跃账户费为每月 USD 5,在当月账户有交易记录时收取。如果某月没有发生任何交易,则不收取该费用。这是 Subotiz Payments 的标准运营费用之一,会在余额页面的交易记录中以活跃账户费扣除的交易类型显示。 如果争议或欺诈比例(以评估周期内的争议单量或争议金额为依据)超过 1%,每笔争议的费用会从 USD 15 提高至 USD 20。争议比例以评估周期内的交易笔数或金额为依据进行统计。将争议比例控制在 1% 以下有助于维持较低的争议费用并降低账户风险。较高的争议比例也可能影响结算周期和保证金条款。 多个因素会影响 Subotiz Payments 账户的结算周期: * 业务类型和行业风险等级 * 销售稳定度和历史交易表现 * 争议和拒付比例 * 合规审核或账户更新 * 支付渠道的资金路由差异 随着账户表现改善——例如争议比例降低、交易历史稳定、合规审核通过——结算周期可能相应调整。当前适用的结算周期始终可在 Subotiz 后台的 资金 > 余额 > 待结算余额 中查看。 保证金政策——包括类型(循环或固定)、比例和持有周期——基于以下因素综合评估: * 业务类型和行业风险等级 * 交易结构和销售规模 * 退款和争议比例 * 行业风险等级 * 账户历史和活跃周期 * 合规和运营状态 保证金条款不是永久固定的。随着账户表现改善——例如争议比例降低、交易历史稳定、合规审核通过——保证金比例或周期可能随之调整或降低。所有保证金记录都在 Subotiz 后台余额模块中完整呈现。 提交初始申请时,需要填写以下企业基础信息: * 企业名称 * 网站链接 * 国家或地区 * 联系人姓名 * 客服邮箱 * 联系电话 填写前需确认网站检查清单,网站须包含: * 清晰的产品或服务描述 * 客户支持联系方式 * 隐私政策 * 服务条款 * 退款政策 * 取消政策 * 支持的支付方式 * 网站安全信息 网站内容不完整、信息不一致或无法访问,可能导致审核延迟或被退回。 Global Account 目前支持以下国家或地区的企业主体申请: * 中国大陆 * 中国香港 * 美国 * 英国 * 法国 * 德国 * 奥地利 * 丹麦 符合条件时,提现账户页面会显示申请 Global Account 选项;未显示则表示当前主体暂不支持申请,需选择绑定已有账户。实际支持范围可能根据产品能力调整,请以系统页面显示为准。 Subotiz Payments 采用两阶段审核流程: * **第一阶段审核通过后** —— 可以开始收款,账户获得初始收款额度,但结算和提现功能尚不可用。 * **第二阶段审核通过后** —— 结算、提现及相关账户功能开放,收款额度限制解除,完整账户功能根据审核结果启用。 第一阶段通过后,通常需要补充资料完成第二阶段审核。各阶段可用功能以后台页面实际显示为准。 前往 设置 > 支付供应商 > Subotiz Payments 查看当前审核进度及操作入口。页面显示当前申请状态、审核结果及资料补充要求。如页面显示修改资料、完善资料或其他待处理提示,请根据页面说明完成操作后重新提交审核。审核结果及后续要求也会通过系统消息同步通知。 第一阶段审核通过后,可能需要补充资料完成第二阶段审核。所需材料因企业主体类型和审核要求而有所不同。常见补充材料包括: * 企业注册信息及注册文件 * 企业负责人信息 * 董事信息(如适用) * 受益人信息含身份证明文件和地址证明(如适用) * 业务信息(产品或服务介绍、目标销售市场、行业类型、预计月交易规模、退款政策链接、隐私政策链接、服务条款链接) 系统显示完善资料时,按页面提示提交所需文件并重新提交审核。 申请未通过时,系统会显示具体驳回原因。请根据页面提示修改相关信息或文件后重新提交审核。对于提现账户问题,也可重新选择其他提现方式(申请 Global Account 或绑定已有账户)。常见被驳回原因包括: * 网站内容与实际业务不一致 * 文件不清晰或不完整 * 提现账户开户主体与企业主体不一致 * 政策页面无法访问 提现账户需满足以下要求: * 账户所属区域须与企业主体所在地一致。 * 独资企业或个人持股比例达 100% 的有限公司,可使用企业代表人的个人账户提现;其他类型企业须使用公司账户提现。 * 绑定已有账户时,需上传近半年内的银行对账单,需清晰显示账户持有人姓名、账户号码、账单日期、银行名称及银行标识。 * 如账户为新开立、无法提供 6 个月对账单,可上传银行后台截图(显示账户名称、银行账号和银行平台标识)作为替代材料,最终以审核结果为准。 # 订阅 Source: https://docs.subotiz.com/zh/faq/subscriptions 订阅合同是 Subotiz 中记录客户与定价方案之间订阅关系的核心记录,在客户订阅后由系统自动生成。每份合同包含: * 订阅 ID * 定价名称 * 客户信息(如邮箱) * 订阅开始时间 * 合同状态(如生效中、试用期、已取消、未完成) * 计费周期(每周、每月、每季度或每年) * 定价类型(固定定价、套餐定价或按使用量计费) 合同还会关联展示所有相关计费周期、订阅变更及退款记录。系统会为所有订阅类型的定价方案生成订阅合同,包括周期性订阅、含试用期订阅、固定期限订阅及用量计费订阅。 Subotiz 订阅合同共有七种状态: * **试用期** —— 订阅处于试用阶段,尚未进入正常计费周期,可能为免费或付费试用。 * **生效中** —— 订阅正在运行,按计费规则生成账单。 * **未完成** —— 客户已发起订阅或结账流程,但未完成支付或确认,合同未进入生效状态。 * **逾期** —— 账单到期后仍未支付,需要跟进处理。 * **未支付** —— 某计费周期已生成发票但尚未完成付款。 * **暂停** —— 订阅已被临时暂停,系统不会生成新账单,直至重新启用。 * **已取消** —— 订阅已终止,不再生成后续账单。 如需排查扣费异常: 1. 进入 Subotiz 后台的 **订阅 > 订阅合同**。 2. 在搜索栏选择客户邮箱或发票 ID 作为搜索字段,快速定位该订阅。 3. 进入订阅合同详情页后,查看**历史账单**模块,该模块会展示每个计费周期的交易单 ID、发票 ID、金额及支付时间。 4. 对于包含试用期或阶梯定价的订阅,需特别关注**价格**列——该列会显示试用期信息和分阶段定价(如第 1–3 期一个价格,第 4 期起另一价格)。 5. 可直接点击发票 ID 或交易单 ID 跳转查看完整关联记录。 可以。Subotiz 支持在不中断订阅的情况下修改订阅方案,包括升级、降级或切换到新的定价方案。在订阅合同详情页的**更多操作**菜单中选择**修改订阅**即可操作。您可以: * 选择新的商品和定价方案 * 设置生效时间(立即生效或本周期结束后生效) * 配置分摊方式(如适用) 系统会自动更新订阅合同、记录变更时间和操作人,并根据规则生成相应发票或退款记录。订阅修改支持固定定价、套餐定价和用量计费三种定价类型。 修改订阅时有两种生效方式: * **立即生效** —— 立即切换至新定价方案。根据订阅状态、定价类型和分摊设置,系统可能收取新方案费用、退还当前方案剩余价值、同时发生退款与收款,或不涉及任何金额结算。具体金额处理结果会在提交前的确认弹窗中显示。 * **本周期结束后生效** —— 继续按原定价执行当前计费周期,新定价从下个周期开始生效,通常不会在本次修改时产生金额结算。对于客户发起支付的套餐定价,新定价将在下一次客户发起支付时生效。 在试用期间提交订阅修改时,账单处理方式取决于当前是付费试用还是免费试用: * **付费试用期间修改** —— 系统可能退还试用期剩余金额,并按新定价重新计算费用。 * **免费试用期间修改** —— 系统可能直接收取新方案费用,或立即进入新的试用期。 具体金额处理方式会在提交前的确认弹窗中显示,可在确认前查看本次修改的处理结果。 取消订阅时,根据订阅状态和账单阶段可能提供以下三种退款选项: * 不退款 * 退还最近账单全额 * 按未使用天数比例退款 选择按未使用天数退款时,系统会自动计算退款金额,计算公式为:(当前周期已支付金额 ÷ 计费周期总天数)× 未使用天数。例如,\$31 的月付方案覆盖 7 月 1 日至 7 月 31 日,若在 7 月 10 日取消,剩余 21 天未使用,退款金额为 \$31 ÷ 31 × 21 = \$21。可用退款选项可能因订阅阶段而有所不同,退款执行可能受支付渠道规则与结算周期限制。 不会。取消订阅不会删除任何历史记录。取消后系统会停止生成后续续订账单,但会完整保留所有历史记录,包括账单、发票、交易单和退款记录。取消前已生成但未支付的发票,将继续按系统配置的扣款重试或催收策略处理。订阅合同状态更新为已取消,并记录预期取消时间、发起取消时间、实际取消时间、取消操作人及取消原因等信息。 不会。在 Subotiz 中,发起退款不会自动暂停或取消订阅合同。即使账单已退款,订阅仍会保持当前状态并继续按计费周期运行,系统仍会按既定规则生成后续账单。这一机制适用于商家希望向客户提供补偿或调整费用,但仍希望继续维持订阅关系的场景。每笔退款都会与对应发票和订阅合同关联,可在后台查看完整记录。支持全额和部分退款。 会。当周期性订阅付款失败时,Subotiz 会自动启动 Smart Retry(智能重试)机制。在大多数情况下,系统会在首次失败后最多进行 4 次自动重试。具体重试时间会根据多个因素动态调整: * 支付失败原因 * 客户所在时区 * 工作日调整 * 部分地区的发薪周期优化 任何一次重试成功后,订阅将继续按原计费周期正常运行。自动重试对所有周期性订阅默认启用,无需额外配置。商家也可以为特定定价方案配置自定义重试策略。 当订阅扣款失败时,系统会对失败类型进行分类并采用不同的重试策略: * **软拒绝** —— 通常为临时性问题,例如网络异常、银行系统暂时不可用或账户余额不足。软拒绝情况下,系统会继续按照 Smart Retry 策略进行多次自动重试。 * **硬拒绝** —— 通常为较明确的拒绝原因,例如卡片失效、账户关闭或银行明确拒绝交易。硬拒绝情况下,系统通常只会额外尝试一次重试。 如果后续重试返回不同的错误类型,系统会根据最新错误重新判断重试策略。 可以通过订阅合同详情页的更多操作菜单中的暂停订阅选项临时暂停订阅。暂停后,订阅不会生成新的账单,状态变更为暂停。如需恢复,在同一更多操作菜单中选择重启订阅,订阅将恢复正常计费流程。暂停订阅适用于客户需要暂时中止服务但不希望永久取消订阅的场景。 可以在订阅合同详情页的更多操作菜单中选择分享更新付款方式链接,为客户生成专属的支付方式更新链接。在弹窗中可以复制链接并发送给客户,也可以直接在弹窗中通过邮件发送。客户通过该链接即可更新其订阅绑定的支付方式。如果链接不再需要使用,可在同一弹窗中将其禁用。该功能适用于有效订阅。 选择立即生效时,有两种分摊方式可选: * **立即结算分摊额** —— 系统根据当前计费周期的剩余时间计算新旧方案的差额,并自动生成发票(需补收差额)或退款记录(退还差额)。 * **无需结算分摊额** —— 新方案立即生效,但本次修改不进行差额计算与结算。根据订阅状态,系统可能不涉及金额变动,或直接收取新方案费用而不按剩余周期调整。 两种选项的具体金额处理结果都会在提交前的确认弹窗中显示,可在确认前查看。 取消订阅时有两种时间选项: * **立即取消** —— 订阅合同立即终止,系统从当时起停止生成新账单,通常由管理员在后台执行。 * **当前周期结束时取消** —— 订阅保持有效,客户继续使用服务直至当前计费周期结束,周期结束后不再生成续订账单。该方式常用于客户取消但仍希望享用已付费周期内服务的场景。 取消选项仅在订阅处于有效生命周期内时可用,若订阅已取消或合同已结束,则不会显示该选项。 如果所有自动重试均失败,系统会根据订阅与账单配置继续处理。可能的结果包括: * 等待客户更新支付方式 * 进入账单催收流程 * 根据订阅规则终止订阅 具体处理方式取决于订阅配置和系统策略,没有统一固定的结果。商家可以为特定定价方案配置自定义重试策略和催收规则,以控制多次失败后的处理方式。未配置自定义规则的订阅将按系统默认的重试与催收规则执行。 Subotiz 支持两种订阅模式: * **持续订阅** —— 默认的自动续费模式,订阅按设定的计费周期持续扣费,直到商家或客户主动取消,没有预设结束时间。 * **固定期限订阅** —— 适用于具有明确服务期限的场景,系统根据设定的续订期数自动计算订阅期限,在最后一期结束后自动停止续费,无需客户手动取消。在适用配置下支持转为持续订阅。 固定期限在订阅合同层级配置,而非商品或定价层级,这意味着购买同一定价方案的不同客户可以拥有不同的固定期限设置。 固定期限订阅在达到设定的计费期数后会自动结束,无需手动取消。系统在最后一期结束后停止生成续订账单,合同状态自动更新。这与持续订阅不同,持续订阅会一直续费直到主动取消。如果固定期限订阅在期限结束前已被手动取消,取消规则优先于固定期限自动结束逻辑。「当前周期结束时取消」与固定期限自动到期是相互独立的机制。 固定期限在订阅合同层级设置和调整,而非定价方案层级。如需设置或调整,打开订阅合同详情页,点击 **更多操作 > 修改固定期限**,或点击固定期限字段旁的编辑入口。在弹窗中可以: * 启用或关闭固定期限 * 设置固定期限期数(期数必须大于当前已完成期数) * 配置是否支持转为持续订阅 如启用转为持续订阅,系统会在固定期限结束前 3 天,通过固定期限订阅到期提醒邮件向客户发送提醒,邮件中包含转为持续订阅按钮,客户可一键将固定期限订阅转换为持续订阅,无需重新创建订阅。注意:转为持续订阅功能需同时在 电子邮件 > 交易邮件 中启用固定期限订阅到期提醒邮件才会生效;如未启用该邮件,客户不会收到包含转换按钮的提醒邮件。提交后,系统会更新订阅信息并重新计算对应到期时间,现有商品、定价方案和计费周期不受影响。 不计入。对于固定期限订阅,试用期不占用固定期限的计费期数。固定期限会在试用结束并进入正式订阅计费后才开始计算。例如,若固定期限订阅设置为 12 期并包含 7 天免费试用,12 期的计数从首个正式付费周期开始,而非试用开始时间。 支持。固定期限订阅同样支持修改订阅,包括升级、降级或切换到新的定价方案。修改订阅后,系统会根据新的定价方案更新合同信息,并按所选生效方式处理相关账单。现有的固定期限配置在修改后保持不变。如需同时调整固定期限,需通过 修改固定期限 功能单独处理——修改订阅不会自动变更固定期限设置。 不会自动收到,需要同时满足两个条件: 1. 在订阅合同中启用转为持续订阅(通过 **更多操作 > 修改固定期限**)。 2. 在 **电子邮件 > 交易邮件** 中启用固定期限订阅到期提醒邮件。 两者同时启用时,系统会在固定期限结束前 3 天自动向客户发送到期提醒邮件,邮件中包含转为持续订阅按钮,客户可一键转换,无需重新创建订阅。如果固定期限订阅到期提醒邮件未启用,即使合同中已开启转为持续订阅,客户也不会收到提醒邮件和转换按钮,无法通过邮件完成一键转换。 # 交易 Source: https://docs.subotiz.com/zh/faq/transaction 交易单是 Subotiz 中核心的账单记录,用于追踪每一笔支付行为。以下场景系统会自动生成交易单: * 订阅开通 * 订阅续费 * 一次性购买 * 试用绑定支付方式(含0元授权) * 用量计费 * 支付方式验证(如0元扣款) * 通过 OpenAPI 发起的支付请求 每笔交易单均与发票、退款单和争议订单相互关联,是所有账单活动的唯一数据来源。 交易单页面通过下拉选择器支持12种搜索类型:交易单ID、外部订单ID、订阅ID、发票ID、客户邮箱、客户姓名、客户ID、商品名称、商品ID、定价名称、定价ID 以及支付卡号后四位。在搜索框左侧下拉菜单中选择搜索类型,再输入对应关键词查询。每次仅支持一种搜索类型。 交易单详情页分为五个模块:(1) 订单信息——商品图片、定价名称、定价标签(如订阅、基于用量等)以及当前订单总额。(2) 时间轴——按时间顺序记录关键事件,如提交支付、支付成功等。(3) 支付信息——支付渠道交易单ID、支付币种、支付供应商、支付方式及卡号后四位(可查看卡品牌、发卡国家、卡片类型)。(4) 附加信息——关联客户、发票账单ID、订阅合同ID及订单类型。(5) 客户追踪——客户IP地址、解析国家/地区及访问设备类型。 仅状态为 已支付 或 部分退款 的交易单可发起退款,这两种状态下详情页右上角才会显示退款按钮。待支付、支付渠道审核中、支付失败及已关闭状态不支持退款。已关闭的交易单在任何情况下均不支持退款。退款必须通过 Subotiz 后台发起,每次退款会生成独立退款单供追踪使用。 可以。只要累计退款金额不超过可退款余额,可对同一笔交易单多次发起部分退款。每次部分退款完成后,交易单状态更新为部分退款,退款按钮仍会显示,可继续发起退款直至可退款余额耗尽。每次退款均会生成独立退款单用于追踪与审计。 提交退款后,系统自动生成退款单,退款单号即时显示在交易单详情页右侧的退款信息模块中,无需刷新页面。也可前往 交易 > 退款单 追踪退款处理进度。退款完成后,交易单状态将更新为部分退款或全额退款。建议定期查看状态为退款中或失败的退款单,及时处理未完成的退款。 交易单在以下两种情况下会自动关闭:订阅续费多次失败后,或订单创建后超过7天未收到支付结果。已关闭的交易单不支持再次支付,也无法重新开启。如客户需要继续付款,需引导其重新订阅或创建新订单。如需核实已关闭订单的原始支付结果,可使用外部订单ID在支付渠道后台进行查询。 订阅续费支付失败时,交易单状态显示为支付失败。建议按以下步骤处理:(1) 通知客户重新发起支付,或建议更换有效的支付方式。(2) 在交易单详情页查看最新重试状态——系统会对续费订单自动重试。(3) 如经多次重试后订单状态变为已关闭,需引导客户重新订阅或创建新订单。(4) 若同一支付方式多次失败,可检查渠道设置或建议客户更新支付方式。 可以。导出弹窗提供两种选项:所有订单(导出全部交易单记录)和筛选出的订单(仅导出当前筛选条件下的结果,如按订单状态、支付方式、订单类型或时间范围筛选后的记录)。在点击导出前,先在交易单页面设置好所需筛选条件,再选择「筛选出的订单」即可。确认后系统在后台处理,完成后会通过消息中心发送通知并提供下载链接。 不会。关闭导出弹窗不会中断或取消导出任务,系统会在后台继续处理。导出完成后,消息中心会发送通知并提供下载链接。如果导出失败,通知中会提示重新导出。等待过程中无需保持弹窗打开。 退款单是每次提交退款申请后系统自动生成的独立账单记录,始终关联原始交易单,无法从发票直接创建。交易单记录的是原始支付行为,退款单则追踪资金退回情况,包括退款金额、退款状态及渠道退款单ID。每次退款(无论全额还是部分)均会生成独立退款单,便于追踪与对账。 可以。退款单的生成方式有两种:手动退款——商家在交易单详情页手动发起退款;自动退款——系统在符合条件时自动处理退款,例如订阅取消或账单调整。两种情况下,退款单均会关联原始交易单,并根据支付渠道返回结果实时更新状态。 退款单使用以下三种状态:(1) 退款中——请求已提交,正等待支付渠道完成处理,此阶段无需额外操作。(2) 失败——退款未成功完成,可重新提交或联系支付渠道跟进。(3) 成功——退款已处理完成,资金已退回至客户的原支付方式,关联发票状态自动更新。 会,但仅在退款成功确认后才会更新。发票更新取决于退款类型:全额退款后发票状态更新为已退款;部分退款后更新为部分退款。如果退款失败,发票状态保持不变。退款单无法从发票直接创建,必须从原始交易单发起。 退款单页面支持6种搜索类型:退款单ID、交易单ID、支付渠道退款单ID、客户姓名、客户邮箱及客户ID。在搜索框左侧下拉菜单中选择搜索类型后输入关键词查询。 退款失败时,退款单状态标记为失败。关键点是:关联发票状态不会发生任何变更,保持原有状态不变,以避免账单数据出现偏差。关联的交易单同样不受影响。待支付渠道问题解决后,可在退款单面板重新提交退款。建议定期关注失败状态的退款单,及时跟进处理,避免遗留未解决的退款。 退款进度可在以下两个位置追踪:(1) 退款单面板——进入 交易 > 退款单,查看退款状态(退款中、成功或失败)、退款金额、原始交易单链接及渠道退款单ID。(2) 发票详情——退款成功后,发票状态自动更新为全部退款或部分退款,并同步反映退款金额。还可下载最新 PDF 发票用于对账或发送给客户。 Subotiz 将来自两个支付渠道的争议集中管理:Subotiz Payments 和 PayPal。两个渠道的所有争议均在统一面板中展示,进入 交易 > 争议订单 即可查看。Subotiz Payments 的争议可直接在后台提交证据;PayPal 的争议在 Subotiz 中仅提供查看与追踪,所有证据提交和处理操作需在 PayPal 调解中心完成。 若未在回应截止日期前提交证据,案件将自动判定客户胜诉——商家无需审核直接败诉。每条争议记录均显示回应截止日期,需密切关注。标准争议一旦超时,无法延期或申诉。PayPal 争议中,状态为待商家回应(可申诉)的案件可能支持补充提交证据。务必优先处理状态为待商家回应的案件,避免超时自动关闭。 争议的最终结果完全由发卡行或支付服务商(如 Subotiz Payments 的卡组织或 PayPal)决定,与 Subotiz 无关。Subotiz 负责集中管理、状态追踪和证据提交工具,但不参与裁定过程。商家通过 Subotiz 后台(Subotiz Payments)或 PayPal 调解中心(PayPal)提交证据,最终裁定由支付渠道根据证据做出。 不同渠道的争议状态略有差异。需要商家立即操作的状态包括:待商家回应(查询)——仅 Subotiz Payments,需在升级为正式争议前回复;待商家回应——两个渠道均有,商家必须选择提交证据或接受争议;待商家回应(可申诉)——仅 PayPal,可提交追加证据进行申诉。其余状态(审核中、审核中(查询)、尚未解决、待客户回应、已关闭、争议胜诉、争议败诉)均为参考状态,无需操作。 以下三种争议原因仅适用于 PayPal,Subotiz Payments 不涉及:(1) 收费金额有误——实际扣款金额与订单金额不一致;(2) 客户通过其他方式付款——客户称该订单已通过其他渠道支付;(3) 汇款问题——资金转账过程中出现错误。相反,客户无法识别的交易(Unrecognized)仅适用于 Subotiz Payments,不出现在 PayPal 争议中。 这两个状态代表 Subotiz Payments 争议的不同阶段:待商家回应(查询)表示案件仍处于调查阶段,商家需在升级为正式争议前回复。在此阶段回应有助于阻止案件演变为正式拒付。待商家回应表示案件已升级为正式争议,商家必须选择:提交证据(反驳争议)或接受争议(系统直接退款并关闭案件)。两种状态都必须在回应截止日期前处理。 不可以。Subotiz Payments 争议的证据只能提交一次。点击确认提交后,材料将转交至发卡行或支付渠道,无法修改或补充。提交前请确认所有材料已准备完整,包括客户沟通记录、访问日志、物流凭证、退款记录及抗辩说明。提交后案件状态更新为审核中,审核周期最长可达3个月。已提交的证据可随时在案件详情页点击查看证据查阅。 点击接受争议后,系统会立即为客户退款并永久关闭案件,状态更新为争议败诉,无法撤销或更改。系统在完成操作前会弹出确认提示,提醒商家一旦接受将无法再补充证据。确认后操作不可逆。接受争议仅适用于商家认可客户索赔合理,或抗辩成本高于争议金额的情况。 不建议。发生争议后,正确做法是立即暂停自动扣款,避免产生新的争议,但不要立即关闭服务访问权限。登录 IP、操作记录和会话日志是重要的证明材料——关闭服务会导致这些证据消失。仅当确认存在欺诈或客户明确提出取消时,才终止订阅,并保留书面确认记录。审核期间,应根据证据强弱决定是否维持服务访问。 以下四类措施可显著降低订阅业务的拒付风险:(1) 账单透明化——在扣费前 3–7 天发送续订提醒并提供可直接取消的链接,确保账单描述包含商户名称、客服电话及网站。(2) 简化取消流程——提供一键取消,通过邮件确认取消日期与剩余服务周期,并保留取消请求的 IP 与时间戳。(3) 明确退款政策——在显著位置展示退款与取消规则,提前设定预期。(4) 保持沟通——通过交易邮件或站内通知提前提醒试用到期、即将续费及政策更新。 不可以。PayPal 争议的证据提交和所有处理操作必须在 PayPal 调解中心完成。Subotiz 仅提供 PayPal 争议的查看与追踪功能——商家可在后台查看案件详情、争议原因、争议金额、回应截止时间及客户信息。如需回应或提交证据,点击案件详情页的跳转至 PayPal 按钮进入 PayPal 调解中心操作。只有 Subotiz Payments 的争议支持直接在 Subotiz 后台提交证据。 提交证据后,争议案件状态会更新为审核中,证据将转交至发卡行或支付渠道进行审核。审核周期最长可达3个月。审核期间商家无需进行任何额外操作。已提交的证据可随时在案件详情页点击查看证据进行查阅。审核完成后,最终结果将通过争议状态反映——争议胜诉或争议败诉。 每条争议记录都会显示支付供应商字段,标明来源为 Subotiz Payments 或 PayPal,通过这个字段可以立即判断处理位置。Subotiz Payments 争议:可直接在 Subotiz 后台查看案件详情并提交证据,在案件详情页点击反驳争议或接受争议进行操作。PayPal 争议:Subotiz 仅提供案件查看与追踪,如需提交证据或回应,需在案件详情页点击跳转至 PayPal,前往 PayPal 调解中心处理。建议在争议列表页使用支付供应商筛选,将两个渠道的案件分开查看。 Subotiz 支持市场主流的国际支付方式,包括 Visa、Mastercard、American Express、Discover、JCB、PayPal、Apple Pay 和 Google Pay。结账页显示的支付方式会根据客户所在地区、设备和浏览器自动调整。例如,Apple Pay 仅在 Apple 设备(iPhone、iPad 或 Mac)且使用 Safari 浏览器时显示;Google Pay 仅在使用 Google Chrome 且钱包中有有效支付卡时显示。商家可在 设置 > 支付方式 中启用或配置支付方式。 即使 Apple Pay 或 Google Pay 已在设置中启用,由于设备和浏览器兼容性要求,结账页面可能不会显示这两种支付方式。Apple Pay:仅适用于 Apple 设备(iPhone、iPad 或 Mac)且使用 Safari 浏览器的用户。Apple ID 需为非中国大陆地区账户。Apple 钱包(Wallet)内需绑定至少一张有效支付卡。如客户使用非 Apple 设备或浏览器,或 Apple ID 属于中国大陆地区,Apple Pay 不会显示。Google Pay:仅在使用 Google Chrome 浏览器时显示。Google Pay 钱包内需绑定至少一张有效支付卡。如客户未使用 Chrome 浏览器或钱包内无有效支付卡,Google Pay 不会显示。 如果客户付款时跳转失败,请引导客户检查以下情况:确认网络连接是否稳定,并检查浏览器是否启用了可能干扰付款的插件(如广告拦截器)。如果问题仍未解决,可以在后台重新发送付款链接,或建议客户尝试其他可用的支付方式。如果以上步骤后问题仍然存在,建议客户尝试用其他浏览器或设备重新访问付款页面。 支持。Subotiz 已集成 3D Secure 2.0。当支付通道或发卡行要求验证时,系统会在结账过程中自动启动 3DS 认证流程,确保交易安全。商家无需手动配置 3DS,系统会根据支付供应商和发卡行的要求自动处理。如需确认账户的 3DS 启用情况或有相关问题,请通过 [merchant-service@subotiz.com](mailto:merchant-service@subotiz.com) 联系 Subotiz 支持团队。 如果付款已成功处理但订阅状态未更新,可能是 Webhook 通知延迟或失败造成的。在后台的交易模块中查看付款记录,确认付款是否已成功完成。如果付款已确认但订阅状态仍未更新,可以从订阅合同详情页手动同步订阅状态。如果问题持续或无法通过上述方式解决,请联系 Subotiz 支持团队协助处理。