跳至正文

2026 年 9 月 18 日 · 阅读时长 19 分钟

跨境收单入门:收银台、SDK 与支付模型

准备接入 Stripe 收款,打开文档却先遇到一串名字:SDK、Elements、Checkout Session、PaymentIntent。换到 Checkout.com、Adyen 或 Antom,又会碰到 Flow、Drop-in、Payment Element。它们有的指页面,有的指代码包,有的指服务端保存的支付对象。

这种感觉像走进几家餐厅,同一道番茄炒蛋写出了几种菜名。不过,支付产品的名字相近,也可能有不同的功能边界。例如 Flow、Drop-in 和 Elements 都能用于嵌入支付界面,提供的组件、支付方式和接入流程却不完全相同;Mobile Web、H5、WAP 也不能按字面当成同一个技术标准。

把这些词按「在哪里填卡号、运行在什么终端、服务器怎样通信、支付过程由谁管理」分开,才容易看懂一份接入文档。这里讨论的是商户如何接入支付服务商(Payment Service Provider,PSP)。

先把四个问题分开

可以把接入支付想成开一家店:先摆柜台,再选柜台放在哪种环境里,接着搭好通信管道,最后决定怎样组织结账和付款。

这四个维度需要一起看,但图中的顺序只是理解概念的顺序。例如,商户可以在手机网页中嵌入支付组件,后端通过 SDK 创建 Checkout Session;「用了 SDK」这一句话,还没有说明 SDK 运行在哪里,更没有说明买家看到哪种收银台。

第一步:摆柜台,决定在哪里输入付款信息

前端交互(Frontend Interaction)决定买家在哪里选择支付方式、填写卡号,以及这些数据会经过谁的页面和系统。界面体验和支付卡行业数据安全标准(PCI DSS)的验证工作量,都与这条数据路径有关。

托管收银台:跳到 PSP 的页面付款

托管收银台(Hosted Payment Page)可以理解为「跳出式支付」:买家在商户页面点击付款,浏览器跳到 PSP 提供的收银台,完成支付后再回到商户页面。

在正确集成的托管流程中,原始卡号由 PSP 页面收集,不经过商户自己的输入框和服务器,可以减少商户直接处理卡数据的范围。代价是支付过程中切换了页面;页面加载速度、品牌辨识和返回路径都会影响体验。跳转对转化率的影响需要用实际支付漏斗衡量,不能套用一个固定损失比例。

Antom 的 Hosted Checkout Page 就有两种页面路径:一种在 Antom 页面完成支付操作;另一种先进入 Antom,再跳到所选支付方式的第三方页面。

电脑和手机都可以走这类流程。手机端可能依次出现商品页、托管收银台、付款码或外部支付页面、结果页,最后回到订单页。页面回来了,只能说明买家完成了某段交互;订单的最终付款结果仍要通过服务端通知或查询确认。

嵌入式组件:在商户页面里放入支付窗口

嵌入式组件(Embedded Components)把 PSP 提供的支付界面放进商户页面。对于使用跨域 iframe 的托管卡输入框,买家感觉自己仍在商户网站上,原始卡信息则由 PSP 的独立文档收集;商户页面脚本不能直接读取其中的卡号。

嵌入的范围可以很小。桌面页面可以保留商户自己的商品和账单区,只嵌入付款方式、卡号输入框或付款码。手机页面也可以沿用这个结构:商品区由商户控制,支付区由 PSP 组件提供。

也可以嵌入一整套收银台。例如,Stripe 的 Embedded Checkout 把完整结账界面放在商户页面中。外层页面留在商户网站,不代表所有认证和支付动作都不会离开当前页面;具体支付方式仍可能要求跳转到银行、钱包或认证页面。

Drop-in、Hosted Fields、Elements 这些名字,需要结合产品文档区分:有的提供整套付款方式选择与表单,有的只提供几个托管字段。组件能定制哪些样式、是否处理 3DS(3-D Secure,持卡人认证)、怎样返回结果,也要逐项确认。

前端直接收集卡信息:商户自己搭前台

Client-to-API 可以用「自建前台」来理解:商户编写 HTML 输入框,直接收集卡号,再通过允许这种接入方式的接口换取 Token。Token 是后续调用使用的替代标识,可以减少继续传递原始卡号的需要。

这种做法给了商户更多界面与交互控制,但原始卡信息先进入了商户控制的页面。页面脚本一旦被篡改,就可能在生成 Token 之前读走卡号;之后再换成 Token,也不会消除先前的数据接触。是否开放这种接口、需要怎样验证合规,应在接入前与 PSP 和收单机构确认。

PCI DSS(Payment Card Industry Data Security Standard,支付卡行业数据安全标准)规定了支付卡数据的安全要求。Visa、Mastercard、American Express、JCB 等卡业务会涉及 PAN(主账号)、有效期、CVV/CVC 等字段,但它们的分类与存储要求不同,不能统称为一种可以任意保存的数据。

PCI DSS 的适用性也不能简化成「只有碰到卡号才需要一张 PCI 资质」。采用托管页面或合规的托管字段可以缩小评估范围,商户仍有相应责任;适用哪种 Self-Assessment Questionnaire(SAQ,自评问卷)或评估方式,要由接收合规材料的机构确认。PCI SSC 对嵌入式支付表单的 SAQ A 条件还专门说明了页面脚本攻击防护要求。

自建表单之后,也可能出现额外认证:电脑或手机端填写卡信息,按需进入 3DS 流程,再回到商户结果页。还要区分卡数据是否经过商户后端;「前端直接提交给 PSP」与「先传到商户服务器再转发」具有不同的数据路径,不能只凭「API 直连」四个字判断。

第二步:选容器,确认支付运行在哪种终端

终端环境(Terminal & Environment)影响屏幕布局、设备信息采集、钱包唤起,以及 3DS 2 认证的展示与返回。一个支付组件能在桌面浏览器使用,不代表它在 App 内的 WebView 或小程序中也有同样的能力。

  • 电脑网页(PC Web):显示空间较大,可以同时呈现多种本地支付方式、商品信息和详细账单。

  • 手机网页(Mobile Web):在手机浏览器里运行,需要控制输入量和页面长度;支持条件满足时,可以接入 Apple Pay、Google Pay 等钱包。产品文档中的 H5、WAP 有时也指这一终端类别。

  • 原生应用(Native App):运行在 iOS 或 Android 中,可以集成 Mobile SDK。指纹、面容或其他认证方式取决于设备、钱包和银行流程,不能保证每次都无感,也不能据此断言转化率最高。

  • 小程序(Mini Program):运行在微信或其他 Super App 的平台环境里,需要遵守宿主对页面跳转、支付 API 和返回路径的规则。

终端选择需要和支付方式一起确认。例如,同样一个 Apple Pay 按钮,在网页和原生 App 中使用的接口与前置条件可能不同;不能把桌面网页的实现原样搬到所有环境。

第三步:搭管道,决定服务器怎样调用 PSP

后端通信(Backend Integration)回答的是商户服务器怎样与 PSP 服务器对话。这里的服务端 SDK,与前面负责展示输入框、唤起钱包的前端 SDK,是不同位置的代码。

服务端 SDK

服务端 SDK 像一套现成工具:把 PSP 提供的依赖包放进项目,调用对应的方法创建支付、查询状态或处理其他业务。

它可以封装请求参数、身份验证、响应解析等重复工作。有的还提供请求签名、重试、webhook(服务端事件通知)验签或特定数据的加解密能力,但具体覆盖范围取决于 SDK。开发者仍需要配置密钥、超时和重试策略,并接好业务流程;不能假定装上 SDK 后所有安全工作都会自动完成。

直接调用服务端 API

Server-to-Server API 可以理解为「手动搭管道」:不使用 PSP 的服务端 SDK,由商户代码构造 HTTP 请求,按协议完成身份验证、必要的签名、数据校验和错误处理。

如果 PSP 没有提供团队所用语言的 SDK,或者项目已有统一的网络与中间件封装,这是一种可选方式。它减少了对特定 PSP 代码包的依赖,也把协议适配、重试语义、超时和版本兼容工作交给了团队。底层仍可能依赖 HTTP 客户端、TLS 和加密库,不能称为系统「零依赖」。

SDK 与直接 API 的取舍

评估维度服务端 SDK直接调用服务端 API
开发效率复用现成请求与响应封装,减少重复代码自行实现协议适配与错误解析
项目体积引入 SDK 及其依赖,大小取决于具体实现可以只封装需要的接口,也需要维护自己的代码
环境稳定性需要关注依赖版本、升级和冲突少一套 PSP SDK,但仍需维护底层网络与安全依赖
代码可控性受公开接口和扩展点约束,开源实现可以审查自己控制封装,同时承担协议正确性的责任
安全审查审查 SDK、依赖及使用方式审查自研签名、验证和重试逻辑,不会自动更简单
性能调优看 SDK 是否开放连接池、超时等配置可以自行组织连接池、超时和熔断,但要负责验证
多通道扩展可能需要维护多套 SDK 和调用风格可以统一接口外形,仍要分别处理各 PSP 的协议差异
团队适配需要快速接入且官方库满足需求时较省事有明确定制需求及长期维护能力时可以考虑

用哪一种方式发请求,与前端是否托管、后端是否创建 Session,没有必然绑定关系。同一个创建支付接口,既可以通过 SDK 调用,也可以直接发送 HTTP 请求。

第四步:选模式,分清结账会话与支付对象

支付模型(Payment Model)决定 PSP 帮商户管理多少结账上下文,以及商户自己控制多少支付流程。它会影响状态跟踪和订单更新;授权后何时 Capture,则是另一个需要单独配置的问题。

支付会话:让 PSP 记住结账上下文

Session / Checkout Flow 的思路是先在服务端创建支付会话,再让前端依据返回的 URL、会话数据或客户端密钥启动付款。Session ID、客户端密钥和跳转 URL 各有用途,不能互换使用,也不能把服务端 Secret Key 当作客户端密钥传到浏览器。

「上下文」(Context)就是完成一件事时需要记住的背景信息和进度。以配置了相应功能的 Stripe Checkout Session 为例,它可以关联:

  • 买什么:商品列表、单价、数量。

  • 按什么条件结账:币种、税费、运费、折扣和优惠券。

  • 谁在付款:客户 Email、账单地址、配送地址等信息。

  • 进行到哪一步:会话是否仍开放、是否已完成或已过期,以及相关支付对象的进度。

后续操作可以引用已创建的上下文,不必每次从头提交全部背景信息。但不同 PSP 的 Session 保存范围不同;名字都叫 Session,也不代表都内置商品目录、增值税或商品与服务税(VAT/GST)的计算功能,以及优惠引擎。

从买家的视角看,过程可能是「开始结账 → 输入卡信息 → 按需完成 3DS → 看到结果」,也可能中途退出或会话过期。这些交互步骤不一定各自对应 Session 的一个状态值。例如,Stripe Checkout Session 的 statuspayment_status 是不同字段;会话已经 complete 时,付款仍可能在处理中。

直接管理支付对象:商户掌握更多结账逻辑

更底层的 Payment API 让商户自己组织商品、折扣、运费和税费,再把最终金额交给 PSP 处理。Stripe 的 PaymentIntent 就属于这种支付对象,它负责跟踪支付及所需认证,商户需要自行组织更多结账逻辑。

可以类比超市收银:商品和优惠由收银系统算好,POS 机接收待付金额,再处理卡付款。这个比喻帮助区分「算出该付多少」和「执行这笔支付」;真实的 PaymentIntent 仍有生命周期,可能等待支付方式、要求认证或处于处理中。

卡支付还可以区分两种 Capture 策略:自动 Capture,或先完成 Authorization(授权,占用可用额度或资金),再由商户发起 Capture(请款)。后者可以理解为先预授权,再完成扣款请求,具体支持范围和授权有效期由支付方式及规则决定。

这两种策略不专属于某一种接口模型。Stripe 的 Checkout Sessions 和 Payment Intents 都能为支持的支付方式配置手动 Capture。「Direct」或「Direct Charge」在不同平台也可能有别的含义,不能把名字直接翻译成「一定立即扣款」。

会话模型究竟托管了什么

能力使用结账会话时直接管理更底层支付对象时
状态与生命周期PSP 管理会话生命周期,商户仍要同步订单状态PSP 仍管理支付对象状态,商户组织结账步骤与订单关联
购物车、税费与折扣某些产品可处理商品、运费、VAT/GST 和优惠,需启用对应功能商户或所接业务系统先计算最终金额,再提交付款
支付界面与方式选择可结合托管页或嵌入组件,按产品支持展示卡、钱包、先买后付(BNPL)等方式也可以结合预制组件;例如 Payment Element 支持 Payment Intents
设备与风控上下文可能由前端组件采集部分浏览器信息,并关联会话;商户仍需传必要数据同样可能需要 IP、设备和浏览器信息,不能只发送一个金额就省略全部终端交互
重定向与异步结果产品可以协助衔接银行或钱包页面,商户接收服务端通知也可能发生重定向和异步处理,同样要取得可靠支付结果

四个维度如何组合

具体产品会限制可用组合。判断时需要看它实际提供什么接口、组件和支付方式,而不能只看 Hosted、Session 或 API 这些标签。

场景需要确认的组合关系
使用 Hosted Payment Page先创建平台要求的结账或付款记录,再取得支付页。Stripe Checkout 使用 Checkout Session;PayerMax 的托管流程则通过创建付款请求返回收银台 URL,接口不必叫 Session
使用嵌入式组件查组件支持哪些服务端流程。例如 Stripe Payment Element 可以配 Checkout Sessions 或 Payment Intents;Adyen 的客户端库也有不同服务端接法
接 Apple Pay / Google Pay需要终端侧的钱包交互,可以使用 PSP 组件,也可以按钱包官方前端 API 接入;仅发一个服务端 HTTP 请求无法代替用户确认付款
接 Boleto、网银或 BNPL分别确认是否跳转、展示付款凭证、要求后续操作,以及结果何时确定;这些支付方式不能全部归为「必须离开商户页面」
运行在 Native App / 小程序核对 Mobile SDK、内嵌页面、外部浏览器和回跳的支持条件,不能一概认定 Hosted 页面不可用
自建输入框收集原始卡信息同时评估前端安全、数据经过的系统和 PCI DSS 范围。后端不用 SDK,并不要求前端也自行收卡号
可能发生 3DS 或其他异步交互前端返回可用于展示进度,服务端按 PSP 文档接收并校验 webhook 或查询结果;买家关掉页面不应让订单永远失去付款结果
希望由 PSP 处理税费与优惠选择确实提供这些功能的产品,并配置适用规则;仅创建一个名为 Session 的对象并不能保证平台替商户算税

例如,使用 Stripe 提供的 Payment Element,可以让卡信息留在托管字段中;商户后端仍可以直接调用 HTTP API 创建 PaymentIntent。前端组件、服务端 SDK 与支付对象分别解决各自的问题。

附录:平台名称与基础术语

平台里的名字怎么对照

下表列出各家文档中的入口和名称,便于查找;同一格内的产品不代表具有完全相同的功能。产品名称与能力核对日期为 2026 年 9 月 18 日。

平台托管或嵌入式界面服务端流程与接口名称链接支付入口
AntomCheckout Page(CKP)、Payment Element创建支付会话、API-only 等接入路径按具体产品文档确认
AdyenDrop-in、Components;另有链接进入的托管支付页Sessions flow、Advanced flowPay by Link,用于补充网店的主支付集成
Checkout.comHosted Payments Page、Flow按 Hosted 或 Flow 的集成文档创建所需支付记录Payment Links
PayerMaxPayerMax Checkout、Drop-InCheckout 创建付款、Direct APIPayByLink
StripeStripe-hosted Checkout、Embedded Checkout、Payment ElementCheckout Sessions、Payment IntentsPayment Links

链接支付(Payment Link)就是生成一个链接,再让客户通过链接进入支付页。它描述的是付款入口;客户打开链接后,仍要经过相应的收银台与支付流程。

还要避免把表格横向读成固定绑定。例如,PaymentIntent 本身不要求商户直接读取原始卡号;Elements 也可以结合 Checkout Sessions。看到「API-only」时,应继续查看卡信息由谁收集、买家在哪里操作,以及是否需要重定向。

缩写速查

缩写英文全称在这里的含义
APIApplication Programming Interface应用程序编程接口;可以用于前端、服务端或系统内部,不限于服务器之间
SDKSoftware Development Kit软件开发工具包;具体可能提供组件、接口封装和辅助工具
PCPersonal Computer个人电脑,PC Web 指桌面浏览器环境
H5来自 HTML5:HyperText Markup Language 5中文产品语境中用来称呼移动网页,不是独立的支付协议
WAPWireless Application Protocol无线应用协议,源自早期移动上网技术;某些支付文档沿用它标记移动网页,不等于 HTML5
AppApplication应用程序;在本文的终端语境中主要指移动应用,例如手机上的微信
vsVersus表示对比或相对

组件是一块可复用的积木

UI 组件(Component)把一项界面功能及其交互封装起来,供其他页面复用。可以把它想成乐高里的轮胎或方向盘:拼一辆车时,拿现成零件组合,不必每次重新制作。

卡号输入框、支付按钮、优惠券弹窗都可以做成组件。组件的价值在于把重复的结构与行为组织起来,让开发者在不同地方使用同一套实现。

  • 功能内聚:把相关的 HTML 结构、CSS 样式和 JavaScript 交互组织在一起,减少调用方需要了解的细节。

  • 可以复用:同一个支付确认按钮,可以出现在购物车、结算页和订单详情页。

  • 参数与状态分开管理:以 React 为例,Props 接收外部参数,例如商品金额;State 保存内部状态,例如按钮是否正在加载、能否继续点击。

组件封装属于代码组织方式。Props 与 State 不构成安全隔离,普通组件也不会自动让页面脚本读不到其中的数据。

iframe 是嵌入另一张网页的窗口

iframe 让一张网页在自己的区域里显示另一份网页文档。支付场景中,外层可以是商户的商品与订单页面,内层则是 PSP 托管的付款输入区域。

可以把它想成客厅里的一扇窗口:透过窗口能看到隔壁房间的电视和沙发,但它们属于另一套装修。对应到网页里,外层和内层各有自己的文档;脚本能否直接访问彼此,还要看是否同源以及采取了哪些限制。

这里有三个需要分开的特征:

  • 独立文档:iframe 内外的 HTML 与 CSS 分属不同文档,外层样式不会直接套用到内层元素。它不等于默认启用了完整沙箱;sandbox 是另外的限制机制,同源文档也可能相互访问。

  • 跨域访问受限:当 PSP 输入框来自不同的源时,浏览器的 Same-origin policy(同源策略)限制商户脚本直接访问它的 DOM。跨域托管卡字段正是利用了这种边界。

  • 嵌入和通信受规则约束:对方可以通过 frame-ancestorsX-Frame-Options 等策略限制被嵌入;允许嵌入后,双方仍可使用 postMessage 按约定交换必要信息。

iframe 可以限制对内层卡字段的直接读取,但商户页面本身仍需防护脚本篡改和伪造输入界面。确认一个支付组件的安全边界时,要看真实的数据路径与跨域设计,不能仅凭页面里出现了 iframe 就认定风险已经消失。

参考资料

CO

我是 Cooper,一名生活在中国的开发者,多年来一直在家远程工作。

主要使用 Go、PHP 和 Rust,从事移动端、Web、跨境支付与资金系统开发。目前主要采用 Vibe Coding 构建产品,并以真实运行结果完成验证与交付。