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

# 选择接入方式

> 三种收银台承载方式和四条服务端路径，分别适合什么场景。

接入前要定两件事：客户在哪个页面上付款，以及你的后端调哪个接口。这两件事互相独立，可以分开选。

## 客户在哪里付款

| 方式              | 客户看到什么                       | 你要写多少前端               | 适合                       |
| --------------- | ---------------------------- | --------------------- | ------------------------ |
| Hosted Checkout | 跳到 Clink 的结账页                | 几乎不用写，跳转就行            | 新项目、想快点上线                |
| JS SDK          | 同样跳走，或把完整结账页以 iframe 留在你的页面里 | 装个包调一个方法；嵌入还要管容器和生命周期 | 前端已经在用这个 SDK，或不想让客户离开你的站 |
| Elements        | 支付输入框、钱包按钮、3DS 嵌在你自己设计的结账页   | 订单摘要、支付按钮、优惠码输入都你自己写  | 需要品牌化或多步骤结账              |

<Tip>
  没有特殊要求就先用 Hosted Checkout。它能最快把「下单 → 付款 → Webhook → 发货」这条链路跑通。确认链路没问题之后，再决定要不要把前端换成 Elements——后端那部分不用重写。
</Tip>

### Hosted Checkout

后端创建 Session 时传 `uiMode: "hostedPage"`，把返回的 `url` 给前端，前端跳过去。

```javascript theme={null}
// 你的前端只需要这几行
const { checkoutUrl, merchantOrderId } = await fetch('/api/checkout/create', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ productId: 'prd_xxx', quantity: 1 }),
}).then((r) => r.json());

sessionStorage.setItem('merchantOrderId', merchantOrderId);
window.location.assign(checkoutUrl);
```

客户付完款会跳回你填的 `successUrl`。回到你的页面后，用 `merchantOrderId` 查一下你自己后端的订单状态，把结果显示给客户。

<Warning>
  回跳页面显示「支付成功」是给客户看的，不是发货依据。发货由 Webhook 那条链路决定，两件事分开。
</Warning>

完整的服务端代码见 [Hosted Checkout 接入](/cn/build-integration)。

### JS SDK 跳转与嵌入

装 [`@clink-ai/clink-js`](/cn/api-reference/javascript_sdk)，用 Publishable Key 初始化。

* `redirectToCheckout()` 跳转到完整结账页
* `initEmbeddedCheckout()` 把完整结账页作为 iframe 挂到你指定的容器里

嵌入模式下，后端仍然要负责创建 Session，SDK 通过你提供的 `fetchSession` 回调来拿。创建时用 `uiMode: "hostedPage"`——SDK 挂的是完整的托管结账页，不需要 `elements` 模式。前端拿到的只有 Publishable Key 和 Session 相关字段。

用法、参数和事件见 [JavaScript SDK](/cn/api-reference/javascript_sdk)。

### Elements

Elements 把页面拆成两半：订单摘要、支付按钮、优惠码输入、状态提示由你写；卡号输入、钱包按钮、3DS 验证、二维码由 SDK 接管。

用 Elements 时后端要改两个地方：

* 创建 Session 传 `uiMode: "elements"`
* 必须传 `returnUrl`，常见写法是 `https://YOUR_DOMAIN/complete.html?session_id={ELEMENTS_SESSION_ID}`，Clink 会把 `{ELEMENTS_SESSION_ID}` 替换成真实 session ID

后端返回给前端的是 `publishKey`、`environment` 和 `sessionId`，不是 `url`。

完整用法见 [Elements 嵌入式收银台](/cn/elements)。

<Note>
  `@clink-ai/clink-js` 的嵌入模式和 `@clink-ai/clink-elements` 是两个不同的包，别混着用。前者挂的是完整结账 iframe，后者挂的是可组合的支付组件。同一个结账页选一种。
</Note>

## 后端调哪个接口

| 你要做的事              | 调这个                      | 什么时候用                                                |
| ------------------ | ------------------------ | ---------------------------------------------------- |
| 让客户进收银台选支付方式       | `POST /checkout/session` | 网站支付的默认选择                                            |
| 直接扣一笔款             | `POST /payment`          | 后端已经有这个客户，且有可用的支付方式                                  |
| 创建订阅               | `POST /subscription`     | 已有周期性商品和支付工具，要直接开通订阅。完整流程见 [订阅支付](/cn/subscriptions) |
| 让客户自己换卡、退订、升降级、看账单 | `POST /billing/session`  | 已有 Clink 客户，需要管理订阅、账单或支付方式，跳客户门户，不要重新走一遍 Checkout    |

绝大多数网站支付走第一条。

`POST /payment` 是给"后台直接扣款"这类场景用的，它不会弹收银台，所以也没有 3DS 交互界面——需要验证时它返回 `status: 5` 和一个 `action`，得你自己引导客户完成。

用银行卡这类方式时，得先有已保存的支付工具（`paymentInstrumentId`）；CashApp、GCash、TNG、微信、Kakao、支付宝、QRIS、PromptPay 这些钱包由后端按支付方式自动创建，不用你先建。

## 商品怎么定义

两种模式，按商品是不是长期固定来选：

**注册商品**——先在后台或用 `POST /product`、`POST /price` 建好，创建 Session 时传 `productId` 和 `priceId`。适合套餐、会员等级这类长期在卖的东西。订阅必须用这种，而且价格得是周期价（recurring price）。

**临时商品**——不预先创建，创建 Session 时用 `priceDataList` 直接描述商品名、单价、数量。适合充值、自定义金额、一次性的东西。

两种可以在同一个系统里共存，按商品类型分别选。

<Note>
  两种模式的金额都用主货币单位。19.99 美元传 `19.99`，不是 `1999`。

  **订阅只能用注册商品**，而且价格必须是周期价（`priceType: "recurring"`）。临时商品建不了订阅，见 [订阅支付](/cn/subscriptions)。
</Note>

## 要不要做优惠

需要打折时，还得决定优惠码在哪一层出现：

| 方式              | 怎么配                                            | 适合         |
| --------------- | ---------------------------------------------- | ---------- |
| 让客户自己输入         | 创建 Session 传 `allowPromotionCodes: true`       | 公开发码、做活动   |
| 后台预先绑定，前台不显示输入框 | 加 `showPromotionCode: false` 和 `promotionCode` | 定向发券、渠道专属价 |
| Elements 自定义输入框 | Session 开启后由前端调 `promoCodeChange`              | 结账页要自己设计   |

创建规则、校验条件和订阅折扣持续多久，见 [优惠与促销码](/cn/promotions)。

## 把选择记下来

定完之后，这几项应该写进你的接入文档或配置，后面写代码时直接查：

| 决策    | 你的选择                                | 影响到                                          |
| ----- | ----------------------------------- | -------------------------------------------- |
| 商品模式  | 注册商品 / 临时商品                         | 传 `productId` + `priceId` 还是 `priceDataList` |
| 服务端路径 | Checkout / 直接支付 / 订阅 / 客户门户         | 调哪个接口                                        |
| 前端承载  | Hosted / SDK 跳转 / SDK 嵌入 / Elements | `uiMode` 取值、后端返回哪些字段、前端装哪个包                  |

## 接下来

<CardGroup cols={2}>
  <Card title="Hosted Checkout 接入" icon="wrench" href="/cn/build-integration">
    后端、前端、Webhook 分别要写什么。
  </Card>

  <Card title="结账会话" icon="banknote" href="/cn/guides/payments/checkout_session">
    Checkout Session 的完整参数说明。
  </Card>

  <Card title="用 AI Agent 接入" icon="bot" href="/cn/agent-integration">
    项目本来就有 agent 在写代码的话，可以让它替你接。
  </Card>
</CardGroup>
