Skip to main content
Elements 把 Clink 管理的支付输入、钱包按钮、3DS、二维码和第三方支付交互,嵌进你自己的页面里。订单摘要、页面结构、支付按钮和状态提示都由你控制。 想最快收到钱就用 Hosted Checkout。需要自己定义订单摘要、页面结构和交互时,再用 Elements。
@clink-ai/clink-elements 目前发布到 0.0.1,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,节选如下:
这是节选,完整字段以 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——那样逻辑正好反过来。

四、事件

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

五、优惠码

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

六、错误处理

SessionNotSupportedError 是接入初期最常见的一个,基本都是后端还在用 uiMode: "hostedPage"

七、实现约束

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

上线自查

  • 浏览器 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 完全一样。

上线检查

切生产前要过的清单。