Skip to main content
Elements 把 Clink 管理的支付输入、钱包按钮、3DS、二维码和第三方支付交互,嵌进商户自己的页面里。订单摘要、页面结构、支付按钮和状态提示则完全由商户控制。 想最快收到钱就用 Hosted Checkout。需要自己定义订单摘要、页面结构和交互时,再用 Elements。
@clink-ai/clink-elements 目前发布到 0.0.3,API 还可能调整。建议在 package.json 里锁定版本。

完整链路长什么样

Elements 只替换前端那一段。创建 Session 仍然必须在商户服务端完成,因为那一步要用 Secret Key。 第 1 步要提交的是商品标识,不是浏览器算好的最终金额。金额由第 2 步在服务端重新算。

四方职责

一、服务端:写一个自己的 Session 接口

这一层不是可选优化。它同时是三条边界:Secret Key 的安全边界、金额校验的边界、本地订单关联的边界 下面用的 clinkRequest 就是 Hosted Checkout 接入 里那个带认证头的 helper,它返回的是响应中的 data
三个要点:
  • uiModeelementsreturnUrl 必填。URL 里可以放 {ELEMENTS_SESSION_ID},Clink 会替换成真实 Session ID
  • 字段名是 returnUrl。有些旧资料写成 redirectUrl,那是错的——redirectUrlrequires_action 场景下响应里的跳转地址
  • merchantReferenceId 只用于关联对账,不是幂等键。同一个值调两次会得到两个 Session
上面 clinkRequest 拿到的 data,节选如下:
Clink 的原始响应外面还包着 { "code": 200, "msg": "success", "data": { ... } } 这层信封,clinkRequest 已经剥掉了。
expireTime 当前返回的是 "2026-07-30 12:00:00" 这种格式,不带时区标识,也不是 RFC 3339。别直接丢给 new Date() 或按本地时间解析——不同运行环境的解释会不一致。也不要按”商户账户时区”或浏览器时区去推断。 后端目前用服务进程的默认时区序列化,没有按账户做转换,所以这个字符串代表哪个时区,接口本身没有表达。要精确处理跨时区逻辑,得等后端把输出契约升级成带 offset 的 RFC 3339 或 Unix 时间戳。在那之前,判断 Session 是否还能付款请看 status,不要拿这个字符串自己算。
这是节选,完整字段以 Create checkout session 为准。两件事要注意:
  • 响应里没有 Publishable Key,也没有 environment 这两样来自商户自己的应用配置,见下一节
  • 响应里 url,那是托管收银台地址。Elements 接入不使用它
不要把 Clink 的原始响应整个转发给浏览器。包装接口只返回前端真正需要的字段,推荐就一个 sessionId

二、前端:调自己的接口,然后初始化

浏览器只做两件事:向商户后端要一个 sessionId,然后用它初始化 SDK。
PUBLIC_CLINK_PUBLISHABLE_KEYenvironment应用的部署配置,来自后台 开发者 > API Keys 里的 Publishable Key(pk_uat_ 开头)。它们可以公开出现在浏览器里,但不来自 Create Session 的响应。
SDK 的参数名是 publishKey,正文里说的 Publishable Key 就是它。代码里必须写 publishKey

三、挂载、提交与第三方按钮

结账页上可能出现两类按钮,处理方式完全不同: 商户自己的支付按钮 —— 银行卡这类需要宿主触发提交的流程。点击后调 clink.submit() SDK 内置的第三方按钮 —— Apple Pay、Google Pay、PayPal 等。它们由 paymentMethod 组件内部渲染,点击也由 SDK 接管。这时 SDK 会发 submit-visible: false,宿主页面要把自己的按钮藏起来。
三件事别做:
  • 别按支付方式名称硬编码按钮显隐。 一切以 submit-visible 为准
  • 别在自己的页面里再画一套 Apple Pay、Google Pay 或 PayPal 按钮。 那些由 SDK 渲染,自行绘制的那套点了没用
  • 别对第三方按钮调 clink.submit() 它们的点击由 SDK 处理
另外,第三方方式会不会出现,取决于商户配置、Session、币种、浏览器和设备能力。不要在页面上承诺每次都有。
submit-enabled 报告的是「能不能提交」。按钮写 disabled = !enabled,别把事件值直接塞进 disabled——那样逻辑正好反过来。

配置 SDK 按钮样式

0.0.3 开始,可以通过 presetOptions.sdkButtons 配置 Apple Pay、Google Pay、Link 和 PayPal 的按钮样式。
完整配置类型如下:
  • 为兼容当前所有按钮渲染方式,请将高度设置在 4055 像素之间
  • 非有限值或小于等于 0 的高度会回退到 45;其他不受支持的正数不会回退,可能导致对应按钮初始化失败
  • 非有限值或负数圆角会回退到 6;超过按钮高度一半时会自动取高度的一半
  • 不受支持的主题和类型会回退到对应默认值
  • 所有 SDK 按钮都是 100% 宽度
  • Apple Pay 没有设置主题时,浅色模式用 black,深色模式用 white
  • PayPal 的高度和圆角由 Clink 应用在 PayPal 组件的外层容器上,不会作为 PayPal SDK 参数传入
按钮设置只在初始化时读取。如果设置发生变化,需要销毁当前实例后重新调用 loadClinkElements()

获取 SDK 按钮可用状态

在挂载 paymentMethod 之前监听 sdk-button-initialized,避免漏掉首次事件。
返回值类型如下:
  • true 表示按钮初始化成功,并且当前设备可以使用
  • false 表示设备不支持、配置有误、网关不支持、第三方 SDK 加载失败,或按钮在当前初始化周期内超过 10 秒仍未完成
  • 只返回当前 Session 中存在的按钮;没有第三方按钮时返回 {}
每个按钮的当前 loading 周期都有 10 秒超时。当前轮次的全部第三方按钮成功、失败或超时后,事件才会触发。按钮重新进入 loading,或可用支付方式发生变化时,会开始新的等待周期;新周期结束后事件会再次触发,即使结果和上一次相同。

四、事件

按用途分两组。 更新宿主 UI 流程提示
session-success 不是付款凭证returnUrl 也不是。浏览器里的事件可以被伪造。正确做法是:收到 session-success 后跳到商户自己的结果页,结果页查询商户后端的订单状态。发货、充值、开通权益只能由后端根据验签后的 Webhook 和服务端查询结果决定。验签、去重和订单匹配见 Hosted Checkout 接入

五、优惠码

可选能力。服务端的 Coupon 和 Promotion Code 怎么建,见 优惠与促销码。这里只讲前端。
回调参数是 { amount },金额字段在 amount 里面。写成 (info) => info.enablePromotionCode 拿到的是 undefined,优惠码入口会一直不显示。 折扣和最终应付金额以 amount 返回的为准,不要自己算。

六、错误处理

0.0.3 会抛出三类东西,处理方式不一样。

初始化:loadClinkElements()

不是只抛 ClinkApiError。至少有三条路径: 响应体不是合法 JSON 时,await res.json() 还会抛原生 SyntaxError 所以 catch 参数要按 unknown 处理,并且一定要留兜底分支
0.0.3 还导出了 SessionExpiredErrorSessionCompleteErrorSessionLoadErrorSessionNotSupportedErrorPromoCodeError。这几个类在当前版本的产物里只有类定义,没有任何抛出路径不要按它们写 instanceof 分支,条件永远不成立。等后续版本真的用上了再说。
拿到初始化错误时,按这几样查——注意每一项各有各的判断依据,不要都往一个接口上归因:

初始化之后:部分错误是同步抛的

不是所有运行期问题都走事件。 下面这些是同步抛出的原生 Error,必须用 try/catch 接:

支付流程中的错误:走事件

真正跟支付流程有关的错误由收银台 iframe 发事件转发,不会被包装成异常类。

七、实现约束

这几条写错会直接导致接入失败,其余布局细节按自己的设计来就行。

上线自查

  • 浏览器 Network 和构建产物里没有 Secret Key,也没有 Webhook 签名密钥
  • 浏览器只调用商户自己的 Session 包装接口,没有直接调 Clink 的 Create Session
  • 后端不相信浏览器传来的最终金额,按商品或购物车重新计算
  • 本地订单、merchantReferenceIdsessionId 三者的映射已保存
  • Publishable Key 和 environment 来自应用公开配置,没有被当成 Create Session 的响应字段
  • Apple Pay、Google Pay、PayPal 等按钮出现时,submit-visible 能让宿主页面的按钮隐藏
  • session-success 不直接触发发货,最终状态来自验签 Webhook 和后端查询
  • Session 变化或页面卸载时销毁了旧实例

接下来

Hosted Checkout 接入

后端和 Webhook 那两块,Elements 和 Hosted Checkout 完全一样。

上线检查

切生产前要过的清单。