创建结账会话,锁定产品版本、定价和货币。这是一次性产品和订阅产品结账流程的第一步。
典型流程:
- 商户创建结账会话(服务端)
- 将
checkoutUrl 返回给前端
- 消费者点击链接进入托管结账页面
- 消费者填写账单信息、预览税额并完成订单
POST /v1/actions/checkout/create-session
认证方式: API Key 或 Store Slug
请求体(API Key)
| 字段 | 类型 | 必需 | 说明 |
|---|
storeId | string | 是 | 门店 ID(Short ID 格式 STO_xxx) |
productId | string | 是 | 产品 ID(Short ID 格式 PROD_xxx) |
productType | string | 是 | onetime 或 subscription |
currency | string | 是 | ISO 4217 货币代码(如 USD、EUR、JPY) |
priceSnapshot | object | 否 | 创建会话时覆盖定价(仅 API Key) |
withTrial | boolean | 否 | 启用试用期(仅订阅产品) |
buyerEmail | string | 否 | 在结账页面预填消费者邮箱 |
billingDetail | object | 否 | 预填账单信息(见下方) |
successUrl | string | 否 | 覆盖支付成功后的重定向 URL |
expiresInSeconds | number | 否 | 会话 TTL(秒),默认 2700(45 分钟,仅 API Key) |
darkMode | boolean | 否 | 结账页面启用暗色模式 |
metadata | object | 否 | 附加到会话的自定义键值对 |
请求体(Store Slug)
| 字段 | 类型 | 必需 | 说明 |
|---|
productId | string | 是 | 产品 ID(Short ID 格式 PROD_xxx) |
productType | string | 是 | onetime 或 subscription |
currency | string | 是 | ISO 4217 货币代码 |
withTrial | boolean | 否 | 启用试用期(仅订阅产品) |
buyerEmail | string | 否 | 预填消费者邮箱 |
billingDetail | object | 否 | 预填账单信息(见下方) |
successUrl | string | 否 | 覆盖支付成功后的重定向 URL |
darkMode | boolean | 否 | 结账页面启用暗色模式 |
metadata | object | 否 | 附加到会话的自定义键值对 |
Store Slug 认证不支持 priceSnapshot 和 expiresInSeconds,以防止客户端进行价格篡改和会话操控。
账单信息对象
| 字段 | 类型 | 必需 | 说明 |
|---|
country | string | 是 | ISO 3166-1 alpha-2 国家代码(如 US、JP、DE) |
isBusiness | boolean | 是 | 是否为企业购买 |
postcode | string | 否 | 邮政编码 |
state | string | 条件 | US 和 CA 必填(如 CA、NY、ON) |
businessName | string | 条件 | isBusiness 为 true 时必填 |
taxId | string | 条件 | isBusiness 为 true 时欧盟国家必填(VAT 号码) |
会话锁定
创建结账会话时,以下值被锁定,在会话生命周期内无法更改:
productVersionId、productName、priceInfo、storeName、billingPeriod、withTrial、theme、buyerEmail、billingDetail
请求示例
import { WaffoPancake, CheckoutSessionProductType } from "@waffo/pancake-ts";
const client = new WaffoPancake({
merchantId: process.env.WAFFO_MERCHANT_ID!,
privateKey: process.env.WAFFO_PRIVATE_KEY!,
});
const session = await client.checkout.createSession({
storeId: "STO_2D5F8G3H1K4M6N9P",
productId: "PROD_7J3K5L8M2N4P6Q9R",
productType: CheckoutSessionProductType.Onetime,
currency: "USD",
buyerEmail: "customer@example.com",
successUrl: "https://example.com/thank-you",
});
console.log(session.sessionId); // "cs_550e8400-e29b-41d4-a716-446655440000"
console.log(session.checkoutUrl); // "https://checkout.waffo.ai/..."
console.log(session.expiresAt); // "2026-01-22T10:30:00.000Z"
成功响应
{
"data": {
"sessionId": "cs_550e8400-e29b-41d4-a716-446655440000",
"checkoutUrl": "https://checkout.waffo.ai/my-store-abc123/checkout/cs_550e8400-e29b-41d4-a716-446655440000",
"expiresAt": "2026-01-22T10:30:00.000Z"
}
}
响应字段
| 字段 | 类型 | 说明 |
|---|
sessionId | string | 结账会话 ID(cs_ + UUID 格式,非 Short ID) |
checkoutUrl | string | 将消费者重定向到托管结账页面的完整 URL |
expiresAt | string | 会话过期时间的 ISO 8601 时间戳 |
| 状态码 | 消息 | 说明 |
|---|
| 400 | 缺少必填字段 | productId、productType 或 currency 缺失 |
| 400 | 无效的 productType | 必须为 onetime 或 subscription |
| 400 | 无效的 billingDetail | 账单信息验证失败(如 US 缺少 state) |
| 401 | 未授权 | 无效的 API Key 签名或 Store Slug |
| 403 | 门店未激活 | 门店不处于 active 状态 |
| 403 | 门店未启用生产模式 | 门店无法处理正式支付 |
| 403 | 产品不在门店中 | 产品不属于指定门店 |
| 404 | 门店未找到 | 没有匹配给定 storeId 或 slug 的门店 |
| 404 | 产品未找到 | 没有匹配给定 productId 的产品 |
默认会话 TTL 为 45 分钟(2700 秒)。使用 API Key 认证时,可通过 expiresInSeconds 自定义。会话在创建时锁定产品版本和定价,因此价格变更不会影响已有会话。