> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anyway.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# 结账会话

> 为一次购买创建结账地址，引导买家付款，并确认对应订单。

需要为某次购买生成付款地址时，由服务端创建结账会话。Anyway 保存购买明细，打开已配置的付款流程，并在收到付款结果后创建或更新订单。无需先创建付款链接。

## 付款链接与结账会话

| | 付款链接 | 结账会话 |
| - | - | - |
| 用途 | 可重复使用的购买入口 | 具有独立购买明细和有效期的一次结账 |
| 发起方式 | 分享已有产品链接 | 后端创建，或从付款链接开始结账 |
| 买家地址 | 使用返回的 `paymentLinkUrl` | 使用返回的 `url` |
| 业务关联 | URL 查询参数 | 服务端提交的 `merchantReference` 和 `metadata` |

重开 API 创建的会话地址会复用本次结账。银行卡付款链接继续使用原有付款页面及返回设置。

## 创建会话

在服务端调用 `POST /v1/checkout-sessions`，携带 `X-API-Key` 和 `Idempotency-Key`。以下示例使用默认银行卡付款方式，并提交本次购买的临时产品和价格：

```bash theme={null}
curl -X POST https://merchant-api-prod.anyway.sh/v1/checkout-sessions \
  -H "X-API-Key: $ANYWAY_MERCHANT_API_KEY" \
  -H "Idempotency-Key: purchase-456-v1" \
  -H "Content-Type: application/json" \
  -d '{
    "pricingData": {
      "productData": {"name": "Consultation"},
      "amount": 3500,
      "currency": "USD",
      "pricingType": "ONE_TIME"
    },
    "quantity": 1,
    "customerEmail": "buyer@example.com",
    "merchantReference": "PUR_456",
    "metadata": {"user_id": "USR_123"},
    "successUrl": "https://merchant.example/payment-result",
    "expiresIn": 3600
  }'
```

创建成功返回 `201` 和可立即打开的 `url`。以下展示部分响应字段：

```json theme={null}
{
  "success": true,
  "message": "Checkout session",
  "data": {
    "id": "CS_EXAMPLE",
    "status": "CREATED",
    "url": "https://app.anyway.sh/checkout/CS_EXAMPLE",
    "amount": 3500,
    "currency": "USD",
    "orderId": null
  }
}
```

将买家带到返回的 `url`，按原样使用地址，不要自行拼接，也不要在其中放入 API 密钥。将返回的 `id` 与你自己的购买记录一起保存。

完整请求与响应数据结构见[创建结账会话](/zh/api-reference/endpoint/create-checkout-session)。

## 选择购买明细

正式产品具有产品 ID，可用于多次购买。临时产品为某次购买提供，信息随会话保存，不会单独创建正式产品。

可以使用已有价格，也可以为本次购买指定价格：

* \*\*使用已有价格：\*\*在请求顶层传 `pricingId`。该价格已经关联产品、金额和币种，无需再传产品 ID。
* \*\*为本次购买指定价格：\*\*在请求顶层传 `pricingData`，包含金额和币种。在它内部，用 `productId` 引用已有的正式产品，或用 `productData` 提供临时产品信息。

`pricingId` 与 `pricingData` 二选一。`productId` 位于 `pricingData` 内部，并不是与 `pricingId` 并列的顶层选项。

| 输入 | 用途 |
| - | - |
| `pricingId` | 当前组织已有的价格 |
| `pricingData.productId` | 已有的正式产品，以及本次购买指定的价格 |
| `pricingData.productData` | 本次购买的临时产品与价格 |

在 `pricingData` 内，`productId` 与 `productData` 也必须二选一。临时产品和价格信息保存在会话中，可通过会话详情读取，不会生成可独立浏览的正式产品或价格目录记录。会话保存购买快照，之后修改目录不会改变本次购买报价。

如果需要使用[产品访问权查询](/zh/api-reference/endpoint/check-entitlement)，请选择 `pricingId` 或 `pricingData.productId`：两种方式都会保留正式产品 ID，临时价格不影响该查询。使用 `pricingData.productData` 的购买没有正式产品 ID，即使付款成功或订阅已激活，也不会纳入产品权益查询。

临时产品的权益需要由商户结合已核实的订单／订阅状态及服务端购买记录自行管理。产品名称只用于展示，不能作为权益标识；结账会话已完成也不代表订阅当前仍然有效。

`amount` 是以币种最小单位表示的单价；会话购买金额包含 `quantity`，数量默认为 1。USD 的 `3500` 表示 \$35.00；USDC 和 USDT 的 `1000000` 表示一个代币。创建会话时，客户信息为可选项，可以同时省略 `customerId` 和 `customerEmail`；如需提供，只能传其中一个。银行卡结账还支持订阅价格，周期字段见生成的接口数据结构。

加密货币使用 `provider: "CRYPTO"`，价格币种选择受支持的 USDC 或 USDT。需先配置组织的收款钱包。托管收银台会提供已配置的网络和收款地址，买家应使用页面显示的网络。加密货币 API 会话目前支持一次性价格。

```json theme={null}
{
  "provider": "CRYPTO",
  "pricingData": {
    "productData": {"name": "Consultation"},
    "amount": 1000000,
    "currency": "USDT",
    "pricingType": "ONE_TIME"
  },
  "merchantReference": "PUR_457",
  "expiresIn": 3600
}
```

## 输入限制

| 输入 | 限制 |
| - | - |
| `Idempotency-Key` | 必填；1–255 个 ASCII 字符，范围为 `0x21` 至 `0x7E`，不允许空格或控制字符 |
| `quantity` | 1 至 999999 的整数；默认 1 |
| `merchantReference` | 最多 255 字节 |
| `metadata` | 最多 50 组字符串键值对；键须为 1–40 个字符且不含 `[` 或 `]`；值最多 500 个字符 |
| `pricingData.productData.name` | 临时产品必填；去掉首尾空白后须为 1–255 个字符 |
| `customerEmail` | 有效的电子邮箱地址，最多 255 字节 |
| 请求体 | 只能包含一个 JSON 对象，最多 64 KiB；未知字段（包括 `pricingData.flexibleAmount` 等嵌套字段）返回 `400` |

## 幂等与重试

* 每次创建请求生成一个 `Idempotency-Key`。超时或返回 `503` 后，用相同的键和未改动的参数重试。
* 同一个键搭配不同参数会返回 `409`。原结账已经不可支付时，重试也可能返回 `409`；明确发起新的结账时使用新键。
* `merchantReference` 是业务关联值，不是幂等键，也不是唯一性锁。不同创建键可以为同一个业务引用创建独立会话。
* 参数无效返回 `400`。创建失败不会返回可用付款地址。
* 组织被冻结、Card/USD 审核未完成，或银行卡收款账户缺失／尚未开通收款时，创建会返回 `403`。请先完成相应配置再重试。

`metadata` 使用字符串键值映射，随会话返回，并作为 `merchantMetadata` 传递给订单；`merchantReference` 保留为独立字段。

## 查询与确认付款

使用 `GET /v1/checkout-sessions/{id}` 查询当前组织的会话：

```bash theme={null}
curl https://merchant-api-prod.anyway.sh/v1/checkout-sessions/CS_EXAMPLE \
  -H "X-API-Key: $ANYWAY_MERCHANT_API_KEY"
```

| 字段 | 含义 |
| - | - |
| `status` | 会话生命周期：`CREATED`、`COMPLETE`、`EXPIRED` 或 `FAILED` |
| `orderId` | 已存在时返回关联订单 |
| `orderStatus` | 已存在时返回关联订单的付款状态 |
| `url` | 可付款的会话地址；会话不可付款时为 null |
| `lastError` | 最近记录的渠道操作错误；存在错误信息不一定代表会话为 `FAILED` |

`COMPLETE` 不保证款项已到账：异步付款仍可能待确认。订单全额退款后可以是 `orderStatus: "REFUNDED"`，会话仍保持 `COMPLETE`；退款不会重新打开结账。部分退款可能保留订单的 `PAID` 状态，退款信息应查看订单详情。

通过[订单 API](/zh/api-reference/orders-guide) 或已验签的[订单 Webhook](/zh/api-reference/endpoint/webhooks) 确认付款，不要仅根据浏览器回跳或会话生命周期判断。关联会话的订单包含 `checkoutSessionId`。按订单 ID 保证履约幂等。订阅续费是关联订阅与首单的独立订单，不会再次完成首次结账会话。

会话地址同时承接付款与结果收据。重开收据不会创建新的购买。

## 有效期与返回地址

`expiresIn` 单位为秒，默认 3600。银行卡结账允许 1800–86400，加密货币允许 60–86400。停止尚未付款的结账时，调用 `POST /v1/checkout-sessions/{id}/expire`：

```bash theme={null}
curl -X POST https://merchant-api-prod.anyway.sh/v1/checkout-sessions/CS_EXAMPLE/expire \
  -H "X-API-Key: $ANYWAY_MERCHANT_API_KEY"
```

付款链接产生的会话在尚未关联渠道会话时，失效只关闭平台入口，不停用整个付款链接，也无法关闭买家已经打开的渠道页面。

失效成功返回 `EXPIRED`；对已为 `EXPIRED` 的会话再次请求失效也会成功。状态为 `COMPLETE` 或 `FAILED` 的会话返回 `409`。失效请求失败后，应先查询会话，不能假定结账已经关闭。对于加密货币，失效会关闭付款入口，但无法撤回收款地址或取消已经发出的转账。

`successUrl` 和 `cancelUrl` 必须为绝对 HTTPS URL。付款成功后可以携带签名结果返回配置的地址；通过取消链接离开页面，本身不会使会话取消或失败。始终在服务端确认订单。

## 在 Business 中查看会话

打开 **Business → 销售 → 结账会话**。列表默认展示 API 创建的会话，通过**会话来源**选择 **API 创建**、`Payment Link` 或**全部来源**，输入完整的会话 ID 或商户业务单号搜索，点击行查看购买明细和关联订单。可付款的会话提供**打开收银台**操作。

<CardGroup cols={3}>
  <Card title="创建" icon="plus" href="/zh/api-reference/endpoint/create-checkout-session">为一次购买创建结账。</Card>
  <Card title="查询" icon="magnifying-glass" href="/zh/api-reference/endpoint/get-checkout-session">读取生命周期和订单关联。</Card>
  <Card title="失效" icon="clock" href="/zh/api-reference/endpoint/expire-checkout-session">停止尚未付款的结账。</Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.