跳转到主要内容
创建收银台会话,锁定商品版本、定价和货币。这是一次性商品和订阅商品收银台流程的第一步。 典型流程为:
  1. 商户在服务端创建收银台会话
  2. checkoutUrl 返回给前端
  3. 消费者点击链接进入托管收银台页面
  4. 消费者填写账单信息、预览税费并完成订单
POST /v1/actions/checkout/create-session
认证方式: API Key 或 Store Slug

请求体(API Key)

字段类型必需说明
productIdstring商品 ID(Short ID 格式 PROD_xxx
currencystringISO 4217 货币代码(例如 USDEURJPY
priceSnapshotobject在会话创建时覆盖定价(仅 API Key,见下方)
withTrialboolean启用试用期(仅订阅商品)
buyerEmailstring在收银台页面预填消费者邮箱
billingDetailobject预填账单详情(见下方)
successUrlstring覆盖支付成功后的跳转 URL
expiresInSecondsnumber会话 TTL(秒)(默认 2700 = 45 分钟,仅 API Key)
darkModeboolean启用收银台页面暗色模式
metadataobject附加到会话的自定义键值对
orderMerchantExternalIdstring商户业务侧订单编号(最大 128 字符)

请求体(Store Slug)

字段类型必需说明
productIdstring商品 ID(Short ID 格式 PROD_xxx
currencystringISO 4217 货币代码
buyerEmailstring预填消费者邮箱
billingDetailobject预填账单详情(见下方)
successUrlstring覆盖支付成功后的跳转 URL
darkModeboolean启用收银台页面暗色模式
Store Slug 认证不支持 priceSnapshotexpiresInSecondsmetadataorderMerchantExternalIdwithTrial。这些字段会被静默忽略,以防止客户端篡改价格和操纵会话。
ID 命名约定:同一组扁平双 key 名(checkout 端的 orderMerchantExternalId、退款工单端的 refundTicketMerchantExternalId)贯穿请求体、webhook 载荷以及承载这些值的每个 GraphQL 类型 — 在 checkout 创建时写入的值可在 OrderPaymentRefund 及 webhook 载荷中以相同的字段名读回。

价格快照对象

字段类型必需说明
amountstring显示格式的价格字符串(例如 “29.00” = $29.00)
taxIncludedboolean金额是否已包含税费
taxCategorystring用于税率计算的税务类别(例如 saasdigital_goods

账单详情对象

字段类型必需说明
countrystringISO 3166-1 alpha-2 国家代码(例如 USJPDE
isBusinessboolean是否为企业购买
postcodestring邮政编码
statestring条件性USCA 必填(例如 CANYON
businessNamestring条件性isBusinesstrue 时必填
taxIdstring条件性isBusinesstrue 时欧盟国家必填(VAT 号码)

会话锁定

创建收银台会话时,以下值被锁定,在会话有效期内无法更改: productVersionIdproductNamepriceInfostoreNamebillingPeriodwithTrialthemebuyerEmailbillingDetail 邮箱规范化:所有邮箱字段(email / buyerEmail / contactEmail)在服务端会被规范化(trim().toLowerCase())后再用于存储、cache、下游调用。Foo@Bar.COMfoo@bar.com 视为同一账户。

请求示例

import { WaffoPancake } 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({
  productId: "PROD_7J3K5L8M2N4P6Q9R",
  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"

成功响应 (200)

{
  "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"
  }
}

响应字段

字段类型说明
sessionIdstring收银台会话 ID(cs_ + UUID 格式,不是 Short ID)
checkoutUrlstring将消费者重定向到托管收银台页面的完整 URL
expiresAtstring会话过期的 ISO 8601 时间戳

错误响应

重试策略:4xx 一律不要重试 — 修正请求后重发。5xx 指数退避重试(起步 5s,最多 3 次)。
状态码errors[0].message含义推荐处理
400Missing or invalid header: x-context-environmentenvironment 请求头缺失或不是 test / prod修正请求头后重发
400Invalid JSON body请求体不是合法 JSON修正请求体后重发
400Missing required fields: productId, currencyproductIdcurrency 缺失修正请求体后重发
400Invalid currency format: "X". Must be 3 uppercase letters (e.g., "USD", "EUR", "JPY")货币代码不是 3 位大写字母(ISO 4217)使用合法 ISO 4217 代码后重发
400Invalid billingDetail账单详情验证失败(例如 US 缺少 state修正 billingDetail 后重发
400Expected format: PROD_xxx, got "..."productId Short ID 解码失败修正 productId 格式后重发
400orderMerchantExternalId must not be empty字段已传但 trim 后为空不传该字段或传入非空值
400orderMerchantExternalId must be at most 128 characters值超过 128 字符缩短到 128 字符以内
400Currency X is not supported for this product产品在请求的货币下无 price snapshot使用产品支持的货币
401UnauthorizedAPI Key 签名无效或 Store Slug 无法识别检查认证请求头
403Store is not active门店状态非 active先激活门店
403Store is not approved for production payments门店未获 prod 环境审批使用 test 环境或申请门店审批
403Product does not belong to this store产品不属于当前访问的门店验证产品/门店配对
404Store not found没有匹配的 slug验证 slug 和 environment
404Product not found产品不存在验证 productId
404Product not found or not active for this environment该 environment 下产品无 active 版本为此环境激活产品版本
500Internal server error服务端意外失败指数退避重试(起步 5s,最多 3 次)
默认会话 TTL 为 45 分钟(2700 秒)。使用 API Key 认证时,可通过 expiresInSeconds 自定义。会话在创建时锁定商品版本和定价,因此价格变更不会影响已有会话。