收单 Open API 接口文档(一期)

面向收单商户。能力为 Payment Processing 中转:Checkout Session(创建 / 查询 / 列表 / 更新)与 Payment Intent(查询 / 列表);支付完成后通过独立收单 Webhook 通知商户。

文档版本
2026-08-11
服务前缀
/open/v1/acquiring/**
凭证类型
必须使用 credential_type = ACQUIRING 的 AccessKey
Base URL
由交付环境提供,形如 https://{host}(下文路径相对该 Host)
责任边界
一期为 API / Webhook 技术中转与商户隔离;收单主体、清算、拒付、结算以合同及渠道协议为准
重要:本接口仅接受 ACQUIRING 凭证。使用其他类型凭证调用本路径返回 40314

1. 接入前准备

  1. 联系运营开通商户 acquiring_enabled(未开通时创建 / PATCH Session 返回 40315)。
  2. 获取 ACQUIRING 类型 Open API 凭证:AccessKeyId + SecretKey + MerchantCode(由运营创建)。
  3. 向运营配置收单 Webhook:HTTPS 回调 URL + 订阅事件(建议订阅 checkout_session.completedpayment_intent.succeededpayment_intent.failed),妥善保存 Webhook Secret(仅创建/轮换时展示一次)。
  4. 实现:请求签名(§2)、幂等 Key(创建 Session)、Webhook 验签(§11)、前端用 @slashfi/checkout-js 嵌入托管收银台(§5.6,不可直接浏览器打开 url)。

2. 鉴权与请求签名(商户 → 平台)

除健康检查外,所有请求须带签名头。

2.1 请求头

HTTP 头必填说明
X-Access-Key-IdACQUIRING AccessKey ID
X-Merchant-Code商户编码,须与 Key 所属商户一致
X-Vcc-TimestampUnix 时间戳,单位(UTC)
X-Vcc-SignatureHMAC-SHA256,小写十六进制
Idempotency-Key写操作必填POST 创建 Session 必填;建议 UUID
Content-Type有 body 时application/json
X-Trace-Id调用方追踪 ID

2.2 Canonical Request

\n(ASCII 0x0A)连接 4 行,再做 HMAC:

  1. HTTP 方法(大写),如 POST
  2. Servlet 路径,如 /open/v1/acquiring/checkout-sessions(不含域名与 query)
  3. 规范化查询串:无参数时为空字符串
  4. 请求体原始字节的 SHA-256(小写 hex);无 body 时对空字节做哈希
Signature = hex_lower( HMAC_SHA256( UTF8(SecretKey), UTF8(CanonicalRequest) ) )

2.3 凭证范围

说明
允许的凭证credential_type = ACQUIRING
可调用路径/open/v1/acquiring/**,以及允许的 GET /open/v1/health
错误凭证类型不匹配 → HTTP 403,业务码 40314OPEN_API_CREDENTIAL_SCOPE_DENIED

3. 统一响应

成功(HTTP 200)

{
  "code": "0",
  "message": "OK",
  "data": { },
  "traceId": "..."
}

业务字段均在 data 内。

失败(HTTP 4xx / 5xx)

{
  "code": "40315",
  "message": "商户未开通收单能力",
  "data": null,
  "traceId": "..."
}

请将 traceId 一并提供给支持排查。

4. 接口一览

方法路径说明
POST/open/v1/acquiring/checkout-sessions创建 Checkout Session
GET/open/v1/acquiring/checkout-sessions列出本商户 Session(本地快照,非实时)
GET/open/v1/acquiring/checkout-sessions/{id}查询 Session(非终态会回源渠道刷新)
PATCH/open/v1/acquiring/checkout-sessions/{id}更新 open Session 的 amount / expiresAt
GET/open/v1/acquiring/payment-intents列出本商户已映射 Payment Intent
GET/open/v1/acquiring/payment-intents/{id}查询 Payment Intent(归属校验 + 非终态回源)
GET/open/v1/health健康检查(可不签名)
不含:退款写接口、对账下载、收银台自托管、Portal 自助配置。Session/Intent 响应可含 paymentIntentId(未知时为 null,属合法中间态)。

5. 创建 Checkout Session

POST /open/v1/acquiring/checkout-sessions

5.1 额外请求头

必填说明
Idempotency-Key商户侧幂等键。相同 Key + 相同 body → 返回首次结果;相同 Key + 不同 body → 40904

平台会改写发往渠道的幂等键,不会把商户原始 Key 透传给渠道。

5.2 请求体

字段类型必填说明
amountinteger金额,单位美分;范围 199999999
currencystring仅支持 usd(大小写不敏感)
clientOrderIdstring商户订单号,最长 64
customMetadataobject自定义元数据;值仅允许标量;总大小(含平台注入)≤ 2KB;键名禁止使用平台保留前缀(大小写不敏感)
configobject透传给渠道的收银台配置对象

未知顶层字段 → 40001。平台会在 metadata 中注入只读的商户标识、商户编码等保留字段(若有 clientOrderId 再注入订单映射字段);商户勿写入或依赖覆写这些保留键。

5.3 请求示例

POST /open/v1/acquiring/checkout-sessions HTTP/1.1
Host: {host}
Content-Type: application/json
X-Access-Key-Id: ak_acq_xxx
X-Merchant-Code: M2026...
X-Vcc-Timestamp: 1723276800
X-Vcc-Signature: ...
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000

{
  "amount": 1999,
  "currency": "usd",
  "clientOrderId": "ORD-20260810-001",
  "customMetadata": {
    "sku": "PLAN_PRO",
    "uid": "u_10086"
  }
}

5.4 成功响应 data

字段类型说明
idstringCheckout Session ID(后续查询使用)
urlstring托管收银台 URL(须用 SDK 嵌入,见 §5.6;勿直接在浏览器地址栏打开)
statusstringopen / complete / expired
amountinteger美分
currencystringusd
clientOrderIdstring|null商户订单号
merchantCodestring商户编码
createdAtstringISO-8601 创建时间
expiresAtstring|null过期时间 ISO-8601
paymentIntentIdstring|null关联 Payment Intent;创建当下常为 null
{
  "code": "0",
  "message": "OK",
  "data": {
    "id": "acq_checkout_xxx",
    "url": "https://app.slash.com/checkout/acq_checkout_xxx",
    "status": "open",
    "amount": 1999,
    "currency": "usd",
    "clientOrderId": "ORD-20260810-001",
    "merchantCode": "M2026...",
    "createdAt": "2026-08-10T10:00:00.000Z",
    "expiresAt": "2026-08-11T10:00:00.000Z",
    "paymentIntentId": null
  },
  "traceId": "..."
}

5.5 推荐业务流程

  1. 服务端 POST 创建 Session,落库 id + clientOrderId
  2. url 交给你们自己的前端页面,用 @slashfi/checkout-js 嵌入(见 §5.6)。
  3. 以 Webhook completed 为准更新订单;可用 GET 查询做补偿。
  4. 勿依赖用户关闭页面时机作为支付成功依据。

5.6 打开托管收银台(必须 SDK 嵌入)

必读:渠道 Hosted Checkout 要求在商户页面内用官方 SDK 挂载 data.url。 在浏览器新标签直接打开 https://app.slash.com/checkout/... 常会报 couldn't load——这不是 Session 创建失败,而是错误的打开方式。

不要:

正确做法:

  1. 后端创建 Session,把 data.url(或 data.id,由后端再查)安全下发给前端。
  2. 前端安装并加载 @slashfi/checkout-js(建议钉版本,例如 0.0.4)。
  3. 调用 loadSlashCheckout()createEmbeddedCheckoutPage({ url })mount('#容器')
  4. 监听 SDK 的 onComplete / onError 仅作 UI 提示;订单履约以收单 Webhook checkout_session.completedGET /checkout-sessions/{id}status=complete 为准。
<div id="checkout"></div>
<script type="module">
  import { loadSlashCheckout } from '@slashfi/checkout-js';

  const slashCheckout = await loadSlashCheckout();
  const checkout = await slashCheckout.createEmbeddedCheckoutPage({
    // 来自 POST /open/v1/acquiring/checkout-sessions 的 data.url
    url: checkoutSessionUrl,
    onReady: () => { /* 收银台已渲染 */ },
    onProcessing: () => { /* 支付处理中(UI) */ },
    onComplete: () => { /* 仅 UI;勿在此发货 */ },
    onError: ({ code, message }) => { console.error(code, message); },
  });
  checkout.mount('#checkout');
  // 换单前先 checkout.destroy()
</script>

约束与排障

说明
同源 / HTTPS商户嵌入页应为 HTTPS(本地可用 http://localhost
单实例同一页面同时只能有一个 Embedded Checkout;重新创建前先 destroy()
MIME若自托管 SDK 的 .mjs,静态服务器须返回 Content-Type: text/javascript(否则浏览器报 Failed to fetch dynamically imported module)
load_failedSDK 约 30s 内未收到托管页协议消息;检查账号是否开通 Hosted Checkout、网络是否拦截 app.slash.com、Session 是否仍为 open
IntentPayment Intent 通常在买家支付后才出现;勿用 Session id 去查 Intent

6. 查询 Checkout Session

GET /open/v1/acquiring/checkout-sessions/{id}

6.1 路径与规则

说明
{id}创建时返回的 Session id
归属仅本商户可见;他商户 ID → 40401
关停后acquiring_enabled=0 时仍允许 GET(禁止新建 / PATCH)
非终态平台会回源渠道刷新状态后再返回
终态直接返回本地快照(complete / expired / canceled 等)

6.2 请求示例

GET /open/v1/acquiring/checkout-sessions/cs_xxx HTTP/1.1
Host: {host}
X-Access-Key-Id: ak_acq_xxx
X-Merchant-Code: M2026...
X-Vcc-Timestamp: 1723276800
X-Vcc-Signature: ...

6.3 成功响应 data

字段类型说明
idstringCheckout Session ID
urlstring托管收银台 URL
statusstringopen / complete / expired
amountinteger美分
currencystringusd
clientOrderIdstring|null商户订单号
merchantCodestring商户编码
createdAtstringISO-8601
expiresAtstring|null过期时间 ISO-8601
paymentIntentIdstring|null关联 Intent;未知则为 null
customMetadataobject含商户字段及平台注入的只读保留字段
configobject|null收银台配置快照(若有)
freshnessstring可选;回源失败时为 CACHED
nonRealtimeboolean可选;与 freshness 同时出现
{
  "code": "0",
  "message": "OK",
  "data": {
    "id": "cs_xxx",
    "url": "https://checkout.example/cs_xxx",
    "status": "complete",
    "amount": 1999,
    "currency": "usd",
    "clientOrderId": "ORD-20260810-001",
    "merchantCode": "M2026...",
    "createdAt": "2026-08-10T10:00:00.000Z",
    "expiresAt": "2026-08-11T10:00:00.000Z",
    "paymentIntentId": "pi_xxx",
    "customMetadata": {
      "sku": "PLAN_PRO",
      "uid": "u_10086"
    },
    "config": null
  },
  "traceId": "..."
}

履约权威:Session status=complete(或 Webhook checkout_session.completed)。

7. 列出 Checkout Session

GET /open/v1/acquiring/checkout-sessions
仅返回本商户本地映射快照,不会透传渠道账号级 list。list 不批量回源;要对单笔实时状态请用 §6 GET by id。

7.1 Query 参数

参数类型必填说明
cursorstring上一页返回的 nextCursor;须为正整数字符串,非法 → 40001
limitinteger默认 20,最大 100
statusstringopen / complete / expired
clientOrderIdstring精确匹配商户订单号

排序:按本地主键 id DESC(近似 newest first)。

7.2 请求示例

GET /open/v1/acquiring/checkout-sessions?limit=20&status=open HTTP/1.1
Host: {host}
X-Access-Key-Id: ak_acq_xxx
X-Merchant-Code: M2026...
X-Vcc-Timestamp: 1723276800
X-Vcc-Signature: ...

7.3 成功响应 data

字段类型说明
itemsarraySession 列表;元素字段同创建响应,但不含 customMetadata / config
nextCursorstring|null下一页游标;无更多数据时为 null
countinteger本页条数
{
  "code": "0",
  "message": "OK",
  "data": {
    "items": [
      {
        "id": "cs_xxx",
        "url": "https://checkout.example/cs_xxx",
        "status": "open",
        "amount": 1999,
        "currency": "usd",
        "clientOrderId": "ORD-20260810-001",
        "merchantCode": "M2026...",
        "createdAt": "2026-08-10T10:00:00.000Z",
        "expiresAt": "2026-08-11T10:00:00.000Z",
        "paymentIntentId": null
      }
    ],
    "nextCursor": "42",
    "count": 1
  },
  "traceId": "..."
}

8. 更新 Checkout Session

PATCH /open/v1/acquiring/checkout-sessions/{id}

仅本地归属本商户且本地状态为 open 时可更新;经渠道 PATCH 成功后回写本地 amount / expiresAt不会因 PATCH 单独出站 Webhook。

8.1 路径与门禁

说明
{id}Session ID
归属非本商户 → 40401
开通acquiring_enabled=040315
本地非 open40916 OPEN_API_ACQUIRING_SESSION_NOT_PATCHABLE
渠道冲突(支付中/终态等 409)40916
渠道业务拒绝(400 等)40060

8.2 请求体

字段类型必填说明
amountinteger条件美分;范围同创建 199999999
expiresAtstring条件ISO-8601;须距今 ≥ 30 分钟且 ≤ 7 天

amountexpiresAt 至少填一个。未知顶层字段 → 40001

8.3 请求示例

PATCH /open/v1/acquiring/checkout-sessions/cs_xxx HTTP/1.1
Host: {host}
Content-Type: application/json
X-Access-Key-Id: ak_acq_xxx
X-Merchant-Code: M2026...
X-Vcc-Timestamp: 1723276800
X-Vcc-Signature: ...

{
  "amount": 2999,
  "expiresAt": "2026-08-12T12:00:00.000Z"
}

8.4 成功响应 data

字段同 §6 查询(含 customMetadata / config 若有)。

{
  "code": "0",
  "message": "OK",
  "data": {
    "id": "cs_xxx",
    "url": "https://checkout.example/cs_xxx",
    "status": "open",
    "amount": 2999,
    "currency": "usd",
    "clientOrderId": "ORD-20260810-001",
    "merchantCode": "M2026...",
    "createdAt": "2026-08-10T10:00:00.000Z",
    "expiresAt": "2026-08-12T12:00:00.000Z",
    "paymentIntentId": null,
    "customMetadata": {
      "sku": "PLAN_PRO",
      "uid": "u_10086"
    },
    "config": null
  },
  "traceId": "..."
}

9. 列出 Payment Intent

GET /open/v1/acquiring/payment-intents
仅本商户已映射 Intent(本地表)。不会透传渠道账号级 list。关停后仍允许查询。

9.1 Query 参数

参数类型必填说明
cursorstring上一页 nextCursor;非法 → 40001
limitinteger默认 20,最大 100
statusstringpending / processing / succeeded / failed / canceled
checkoutSessionIdstring精确匹配关联 Session ID

9.2 请求示例

GET /open/v1/acquiring/payment-intents?status=succeeded&limit=20 HTTP/1.1
Host: {host}
X-Access-Key-Id: ak_acq_xxx
X-Merchant-Code: M2026...
X-Vcc-Timestamp: 1723276800
X-Vcc-Signature: ...

9.3 成功响应 data

字段类型说明
itemsarrayIntent 对象列表(字段见 §10.3)
nextCursorstring|null下一页游标
countinteger本页条数
{
  "code": "0",
  "message": "OK",
  "data": {
    "items": [
      {
        "id": "pi_xxx",
        "status": "succeeded",
        "amount": 1999,
        "currency": "usd",
        "checkoutSessionId": "cs_xxx",
        "clientOrderId": "ORD-20260810-001",
        "createdAt": "2026-08-10T10:01:00.000Z",
        "updatedAt": "2026-08-10T10:05:00.000Z"
      }
    ],
    "nextCursor": null,
    "count": 1
  },
  "traceId": "..."
}

10. 查询 Payment Intent

GET /open/v1/acquiring/payment-intents/{id}

对账权威:Intent status=succeeded(或 Webhook payment_intent.succeeded)。履约仍以 Session complete 为主路径。

10.1 路径与规则

说明
{id}Payment Intent ID
归属本地映射属本商户,或渠道响应含本商户 checkoutSessionId → 允许;否则 40401
无 Session 关联(如开票来源 Intent)40401(本产品线不服务)
非终态回源渠道刷新并 upsert
终态可直接返回本地(succeeded / failed / canceled
回源失败且本地有行200 + 本地快照 + freshness: CACHED

10.2 请求示例

GET /open/v1/acquiring/payment-intents/pi_xxx HTTP/1.1
Host: {host}
X-Access-Key-Id: ak_acq_xxx
X-Merchant-Code: M2026...
X-Vcc-Timestamp: 1723276800
X-Vcc-Signature: ...

10.3 成功响应 data

字段类型说明
idstringPayment Intent ID
statusstringpending / processing / succeeded / failed / canceled
amountinteger美分
currencystringusd
checkoutSessionIdstring关联 Checkout Session
clientOrderIdstring|null来自关联 Session
createdAtstringISO-8601
updatedAtstringISO-8601
freshness / nonRealtime可选;回源失败降级时出现
{
  "code": "0",
  "message": "OK",
  "data": {
    "id": "pi_xxx",
    "status": "succeeded",
    "amount": 1999,
    "currency": "usd",
    "checkoutSessionId": "cs_xxx",
    "clientOrderId": "ORD-20260810-001",
    "createdAt": "2026-08-10T10:01:00.000Z",
    "updatedAt": "2026-08-10T10:05:00.000Z"
  },
  "traceId": "..."
}
如何拿到 Intent id:Session 响应 / completed Webhook 的 paymentIntentId(可能暂时为 null)、本接口 list、或 payment_intent.* 出站事件。创建 Session 当下 Intent 可能尚未生成,null 为合法中间态。

11. 收单 Webhook(平台 → 商户)

独立配置:收单回调使用独立 Webhook Secret(与 API SecretKey 不同)。一期由运营为商户配置回调 URL 与 Secret。

11.1 HTTP 约定

说明
方法POST
Content-Typeapplication/json; charset=utf-8
成功返回 HTTP 2xx(建议 200);非 2xx 可能重试
超时连接/读超时约数秒级(以部署为准)

11.2 签名头(与 Open API 入站算法不同)

说明
X-Vcc-SignatureHMAC-SHA256,小写 hex
X-Vcc-TimestampUnix 时间戳,单位毫秒
X-Vcc-Nonce32 字符 hex
X-Vcc-Event-Id与 body eventId 一致,用于幂等
payload = timestamp + nonce + body_raw_utf8
expected = hex_lower( HMAC_SHA256( UTF8(WebhookSecret), UTF8(payload) ) )

11.3 事件类型

eventType说明
merchant.webhook.acquiring.checkout_session.completedSession → complete(履约权威);data 可含 paymentIntentId(可为 null)
merchant.webhook.acquiring.payment_intent.succeededIntent → succeeded(对账通过)
merchant.webhook.acquiring.payment_intent.failedIntent → failed(非退款确认)

11.4 载荷结构(Session completed)

{
  "eventType": "merchant.webhook.acquiring.checkout_session.completed",
  "eventId": "mwh_evt_acq_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "occurredAt": "2026-08-10T10:05:00.000Z",
  "merchantCode": "M2026...",
  "data": {
    "checkoutSessionId": "cs_xxx",
    "status": "complete",
    "amount": 1999,
    "currency": "usd",
    "clientOrderId": "ORD-20260810-001",
    "paymentIntentId": "pi_xxx",
    "customMetadata": {
      "sku": "PLAN_PRO",
      "uid": "u_10086"
    },
    "slashEventId": "可选,渠道侧事件 ID",
    "slashEventTimestamp": "可选"
  }
}
data 字段说明
checkoutSessionId与 Open API Session id 相同
status完成态语义(complete
amount / currency与创建一致
clientOrderId若创建时传入
paymentIntentId已知则 string;未知则为 null
customMetadata创建时写入并含平台注入字段
slashEventId / slashEventTimestamp可选,渠道侧追踪

11.5 载荷结构(Payment Intent 终态)

{
  "eventType": "merchant.webhook.acquiring.payment_intent.succeeded",
  "eventId": "mwh_evt_acq_pi_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "occurredAt": "2026-08-10T10:05:01.000Z",
  "merchantCode": "M2026...",
  "data": {
    "paymentIntentId": "pi_xxx",
    "checkoutSessionId": "cs_xxx",
    "status": "succeeded",
    "amount": 1999,
    "currency": "usd",
    "clientOrderId": "ORD-20260810-001",
    "updatedAt": "2026-08-10T10:05:00.000Z"
  }
}
data 字段说明
paymentIntentId必有
checkoutSessionId关联 Session
statussucceededfailed
amount / currency金额币种
clientOrderId可空
updatedAtISO-8601

同一资源同一终态的 eventId 稳定派生;商户须按 eventId 幂等。Session completed 与 Intent succeeded 可能先后到达,请按 clientOrderId / Session id 幂等履约。

12. 错误码(收单相关)

HTTPcode含义
40040001 / VALIDATION_ERROR参数非法(金额、币种、expiresAt、cursor、未知字段等)
40040003 / OPEN_API_IDEMPOTENCY_REQUIRED缺少 Idempotency-Key
40040060 / ACQUIRING_CHANNEL_REJECTED渠道拒绝(含部分 PATCH 业务拒绝)
401OPEN_API_SIGNATURE_INVALID签名 / 凭证 / 时钟问题
40340314 / OPEN_API_CREDENTIAL_SCOPE_DENIEDKey 类型与路径不匹配
40340315 / OPEN_API_ACQUIRING_DISABLED商户未开通收单(POST/PATCH)
40440401 / NOT_FOUNDSession/Intent 不存在或不属于本商户
40940904 / OPEN_API_IDEMPOTENCY_CONFLICT同幂等键不同请求体
40940916 / OPEN_API_ACQUIRING_SESSION_NOT_PATCHABLESession 当前不可 PATCH
50250260 / ACQUIRING_CHANNEL_UNAVAILABLE渠道不可用

13. 限流与约束

说明
限流创建约 30 rpm / 查询约 120 rpm 每商户(可配置)
币种usd
金额整数美分 199999999
list默认 20 / 最大 100;仅本商户本地快照
幂等创建必带;建议每个业务订单使用稳定且唯一的 Key
安全Secret / Webhook Secret 仅服务端持有,禁止下发到浏览器或 App

14. 签名示例(Python)

14.1 调用 Open API(创建 Session)

import hashlib, hmac, json, time, uuid, urllib.request

BASE = "https://{host}"
AK = "YOUR_ACQUIRING_ACCESS_KEY"
SK = "YOUR_API_SECRET"
MERCHANT = "M..."

body_obj = {
    "amount": 1999,
    "currency": "usd",
    "clientOrderId": "ORD-001",
    "customMetadata": {"sku": "PLAN_PRO"},
}
body = json.dumps(body_obj, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
method = "POST"
path = "/open/v1/acquiring/checkout-sessions"
query = ""
body_hash = hashlib.sha256(body).hexdigest()
canonical = f"{method}\n{path}\n{query}\n{body_hash}"
ts = str(int(time.time()))
sig = hmac.new(SK.encode(), canonical.encode(), hashlib.sha256).hexdigest()

req = urllib.request.Request(
    BASE + path,
    data=body,
    method=method,
    headers={
        "Content-Type": "application/json",
        "X-Access-Key-Id": AK,
        "X-Merchant-Code": MERCHANT,
        "X-Vcc-Timestamp": ts,
        "X-Vcc-Signature": sig,
        "Idempotency-Key": str(uuid.uuid4()),
    },
)
print(urllib.request.urlopen(req).read().decode())

14.2 验签收单 Webhook

import hashlib, hmac

def verify_acquiring_webhook(secret: str, timestamp: str, nonce: str, body: bytes, signature: str) -> bool:
    payload = (timestamp + nonce).encode("utf-8") + body
    expected = hmac.new(secret.encode("utf-8"), payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature.lower())

15. 联调检查清单

16. 变更记录

日期变更
2026-08-11收单文档独立成册,去除其他产品交叉引用与品牌混用
2026-08-11新增 §5.6:托管收银台必须用 @slashfi/checkout-js 嵌入;禁止浏览器直开 url
2026-08-11补齐 List / PATCH Session、Payment Intent get/list 完整字段表与请求响应示例;Webhook 三事件;错误码 40916
2026-08-11发布独立 HTML 公网文档(本页)
2026-08-10初版:收单 Checkout Session 创建/查询、独立 Webhook、错误码与示例