RouteNest 把 Pro 订阅的付款表单放进价格页,荷兰买家点 iDEAL 后,浏览器还是跳到了银行。买家授权回来,页面也不能马上开通会员,因为支付 Webhook 还没到。这个过程没有出错:表单在哪里、付款是否需要离站、付款是否已经确认,本来就是三件事。
如果服务商的完整结账页已经覆盖必需的支付方式和字段,就先用 Hosted Checkout。确实要保留付款前的产品配置,才值得嵌入整张表单;预构建表单放不下席位、增购或实时报价,再拆成独立支付组件。连卡号输入框都由自己的页面生成时,安全和合规责任会陡增,通常不该作为 SaaS 的起点。
在讨论页面怎么做之前,支付账户要能用,价格也要能卖。Product、Plan、Price 和服务商价格仍混在一条记录里时,先处理价格目录建模;主体、产品或结算账户还没有筛出可用候选时,先完成四个平台的条件式比较。RouteNest、金额和业务场景均为合成案例,不对应真实商户。
先看付款页和卡号输入框是谁提供的
“跳转式”“嵌入式”和“站内”只说明买家在哪里看见表单。完整付款页由谁提供、卡号输入框由谁提供、支付完成后由谁确认结果,决定了商户要承担哪些工作。Stripe 当前的 Checkout 对照(在新标签页打开)列出 Full page、Embedded form 和 Elements:Full page 既可以跳到 Stripe 托管页面,也可以把 Stripe 管理的完整页面嵌进商户网站;Embedded form 目前单独标为 Public preview。
Airwallex 则把接入方式分成托管页面、完整 Checkout Element、独立 Elements 和 Payments API。Airwallex 的 Web Checkout 对照(在新标签页打开)说明,即使几种界面都留在商户网站里,需要自己编写和长期维护的代码也可能相差很大。比较不同服务商时,应直接核对页面和卡数据的来源,不能只对齐产品名称。
| 接入方式 | 买家看到什么 | 谁提供付款界面 | 商户负责什么 | 长期代价 |
|---|---|---|---|---|
| 服务商托管整页 | 从产品页进入服务商的完整结账页,结束后返回 | 服务商提供金额摘要、地址、支付方式和付款字段 | 创建 Session、传入已核验价格、配置品牌及返回地址 | 页面编排受限,但首次接入和持续维护最少 |
| 服务商托管嵌入式表单 | 完整结账表单出现在商户页面、弹层或内嵌区域 | 服务商提供表单内部结构和敏感字段,商户提供外层页面 | 容器位置、周边内容、有限主题和页面生命周期 | 还要处理脚本安全、尺寸、加载、焦点和外部动作返回 |
| 可组合支付组件 | 商户页面分别放置钱包、地址、卡字段和其他组件 | 商户安排页面和步骤,服务商托管敏感输入组件 | 字段顺序、分步流程、订单摘要、业务字段和错误提示 | SDK、状态协调、无障碍与浏览器回归明显增加 |
| 完全自建支付界面 | 付款字段也由商户自己的页面元素生成 | 商户提供完整界面并参与采集卡数据;服务商接收后续支付请求 | 全部布局、字段、路由、支付方式和支付流程 | 安全、PCI、测试、维护和迁移责任最高 |
Paddle 的 Overlay Checkout 就是一个容易混淆的例子。它在当前页面上打开由 Paddle 处理的完整结账,金额、支付方式和订阅创建仍走服务商流程;Inline Checkout 则允许商户安排表单周边的布局。两者都可能被称为“站内支付”,商户接手的工作却不同。Paddle 的 Overlay 说明(在新标签页打开)列出了由它处理的商品、合计和付款选项。
“完全自建”不是指页面用了自己的颜色和布局,而是商户提供的页面元素开始采集或处理卡数据。外层页面即使全部由商户安排,只要卡号等敏感输入始终留在服务商托管的 iframe 或组件里,仍属于可组合组件。商户自己的 DOM、JavaScript 或服务器一旦接触卡数据,就要按扩大后的数据路径重新确认 PCI 范围。两种页面看起来可能一样,检查元素来源和网络请求才能分清。
Hosted Checkout 和嵌入式支付,先看哪些条件不能让步
RouteNest 的 Pro 月付必须在目标设备上显示必需的支付方式,收齐完成交易所需的信息,并能在跳转或断网后找回结果。托管整页能做到这些时,改成嵌入或组件就应当解决一个能说清、能衡量的问题;“看起来更像自己的产品”不足以抵消长期维护成本。
| 条件 | 需要确认的事实 | 对选择的影响 |
|---|---|---|
| 客户端 | 普通浏览器、移动浏览器、原生 App 还是 WebView;能否完成服务商要求的跳转和钱包调用 | 只支持 Web 的嵌入组件不能直接搬进原生 App;受限 WebView 也不能假设外部认证一定可用 |
| 支付方式 | 当前商户、买家地区、币种、一次性或续费、设备和接入方式下是否真的可用 | 缺少必需支付方式时直接换方案,样式再合适也不能弥补 |
| 购买流程 | 付款前是否必须调整席位、附加项、配送内容或复杂报价 | 预构建页面放不下必要交互时,才需要组合支付组件 |
| 字段 | 支付、税务、履约和产品账户分别需要哪些数据,是否可以分开采集 | 不能为了少一个页面,把所有业务字段硬塞进有限的自定义字段 |
| 页面与品牌 | 只要颜色和字体一致,还是付款前后必须保留实时配置 | 只有实时上下文不可丢失时,整页跳转才会被排除;普通品牌偏好不够 |
| 维护能力 | 团队能否长期负责 SDK、CSP、浏览器、无障碍、监控和外部支付动作 | 没有明确维护者时,不应选择组件式或完全自建 |
金额与币种不能由浏览器决定。自己的服务端根据内部 Price、数量、优惠资格和税务信息算出本次应付金额,再创建服务商的 Session 或 Payment。买家可以从允许的支付方式中选择,却不能把 price=24 改成 price=1,也不能由浏览器宣布付款成功。Hosted Checkout 省掉的是付款界面,不是服务端核价、下单和确认结果的工作。
同一产品不必强求所有支付方式长得一样。桌面卡支付可以进入嵌入组件,移动钱包可以使用服务商整页,银行支付则按要求跳到外部网站。无论页面怎样变化,服务端都要把它们关联到同一笔购买、同一份应付金额和同一个订单。为了统一外观而限制支付方式,可能让部分买家失去可用选项,也可能让外部认证在 WebView 里无法完成。
判断 PCI 范围,要看实际页面和卡数据
PCI SSC 关心的不是页面看起来像谁家的,而是付款页面元素从哪里加载、卡数据由谁接收。URL redirect 把买家送到第三方页面;第三方 iframe 把第三方表单放进商户页面;Direct Post 可能由商户页面生成付款字段,再把数据直接提交给处理方。三种方式都可以做得很顺畅,但页面被恶意脚本篡改时,商户需要承担的安全与合规范围不同。
PCI SSC FAQ 1291(在新标签页打开) 中的核心条件是:参与收集和处理卡数据的付款页面元素,只能直接来自经过 PCI DSS 验证的第三方服务商。FAQ 1438(在新标签页打开) 对 iframe 场景作了进一步限定:卡数据输入框以及与采集卡数据相关的页面元素必须全部位于服务商 iframe 内;导航、页眉和商品说明等无关内容可以留在 iframe 外,但其他 SAQ A 资格条件仍然适用。因此,不能看到某个品牌 SDK 或一个 iframe 标签就认定符合 SAQ A,还要核对实际 DOM 来源和数据流。
嵌入式页面还要满足脚本攻击防护条件。PCI SSC FAQ 1588(在新标签页打开) 指出,PCI DSS v4.0.1 SAQ A 中关于支付页面脚本攻击的资格条件,适用于包含第三方嵌入式支付页或表单的商户网页,不适用于把买家完整重定向到处理方的页面。商户可以采用相应的脚本保护技术,或取得支付服务商对实施方式的确认;最终仍应咨询接收 SAQ 的机构。
把整张付款页交给服务商,也不等于商户没有 PCI 义务。PCI SSC FAQ 1604(在新标签页打开) 指出,PCI DSS v4.x 的 SAQ A 包含商户电商网页的外部漏洞扫描要求,其中同时提到重定向和嵌入式 iframe 场景。支付处理外包以后,商户仍要管理服务商合规状态、书面责任、自己的网站和定期验证。
服务商标注的 SAQ 类型只能用于初步判断,不能替代对实际接入的确认。Airwallex 当前把托管页面、预构建 Checkout Element 和独立 Elements 标为其方案下的 SAQ A,把自有 Payments API 界面标为更高责任;这个结论只有在按其文档实施并满足全部条件时才成立。更换 SDK、改变卡号输入框的来源、在 iframe 外增加与卡数据采集相关的元素,或让自己的服务器接触卡号,都需要重新确认范围。
嵌入式支付也可能跳去银行或钱包
嵌入到页面里的只是付款入口,不包括银行、钱包和发卡行自己的系统。买家选择 iDEAL、部分实时银行支付、钱包或 3DS 后,服务商可能要求浏览器跳转、展示二维码、调用应用或等待异步结果。Adyen 的 Web Drop-in 即使已经放在商户页面中,遇到 action.type=redirect 仍会把买家带到另一个网站(在新标签页打开);其他动作还可能要求扫描二维码或打开银行应用。
Stripe 的支付方式支持表(在新标签页打开)也分别列出国家、币种、产品能力、API 能力和是否需要重定向。某个支付方式出现在平台 Logo 墙上,不等于它能用于当前商户国家、买家国家、币种、订阅模式和接入方式。先按这些条件确认支付方式,再判断页面怎么呈现,不能反过来先选表单样式。
RouteNest 的荷兰买家选择 iDEAL 后离开嵌入式表单,属于正常付款流程。桌面浏览器可能进入银行网站,移动端可能打开银行应用;买家也可能付完就关闭页面,或者取消授权后返回。产品需要保证的是付款结果可以找回,而不是所有支付方式永远停在当前页面。
不必让所有支付方式采用同一种页面。卡和兼容钱包可以留在嵌入组件中;银行支付按要求使用服务端配置的返回地址;需要较长时间确认的方式,则在订单页显示处理中。页面动作可以不同,但金额、订单编号和最终付款结果必须属于同一笔交易。
地址和业务字段不能全部塞进付款表单
账单地址、税务位置、产品账户名和团队席位看起来都像结账字段,负责这些数据的系统却不同。全部交给支付服务商,会受到自定义字段数量和数据读取方式的限制;全部留在产品页,又可能重复询问地址,甚至让税额和支付记录使用两份不一致的数据。
| 数据 | 谁负责 | 什么时候采集 | 不能怎样处理 |
|---|---|---|---|
| 内部 Product、Price、数量和优惠结果 | 商户自己的服务端 | 创建支付 Session 之前 | 接受浏览器提交的任意金额或外部 Price ID 作为最终依据 |
| 卡号、有效期和安全码 | 合规服务商托管页面或字段,除非商户明确承担更高范围 | 支付方式输入时 | 写入商户日志、分析、URL、普通表单状态或支持工单 |
| 账单地址与付款人姓名 | 支付服务商按支付方式采集;商户只保存允许使用的结果 | 付款表单内,尽量预填已经确认的信息 | 在产品页和付款页用两份互不一致的数据计算交易 |
| 税务位置证据与税号 | 负责税务计算和记录的一方 | 报价或付款前,具体取决于卖方和税务方案 | 把“收了一个国家字段”当成完整税务判定 |
| 工作区名、成员数、部署区域等产品数据 | SaaS 产品 | 付款前的配置步骤,或付款确认后的开通步骤 | 为了少一个页面而塞进有限的支付自定义字段 |
| 条款同意与营销许可 | 对合同和用途负责的一方 | 与相应条款紧邻,分别记录 | 用一个预勾选框同时代表付款、服务条款和营销同意 |
使用 Merchant of Record 时,MoR 可能在自己的结账和合同流程中采集税务字段;使用普通支付处理商时,商户通常仍要为自己的卖方税务判断负责。两者的根本差异见支付处理商与 Merchant of Record 的责任边界。界面嵌入不会改变合同中的卖方,也不会自动把税务责任转给支付服务商。
同一项数据只能有一个最终来源。产品已经保存买家邮箱和公司名称时,可以在服务商允许的范围内预填;服务商返回客户号或交易号后,再写回对应订单。地址会改变税额时,要在买家确认金额之前重新计算,不能页面还显示旧总额,后台却扣取新金额。只有付款后才能确定的产品设置,不必提前塞进支付表单。
不同故障,需要不同的恢复动作
结账失败不能全部归成一个 payment_failed。Session 没创建出来、SDK 没加载、字段校验不通过、发卡行拒绝、买家取消银行授权,以及返回后暂时查不到最终结果,处理方式都不同。如果页面只显示“请重试”,既可能重复创建订单,也可能让买家再次支付一笔已经成功的交易。
| 买家看到的现象 | 问题可能在哪 | 怎么恢复 | 不能怎么做 |
|---|---|---|---|
| 点击购买后没有进入付款界面 | 商户服务端或服务商创建接口 | 用同一笔购买编号和幂等键找回原创建结果;确认失败后才允许新尝试 | 只因响应丢失就再建一笔订单或付款 |
| 嵌入区域空白、尺寸错误或脚本未加载 | 商户页面、CSP、网络或 SDK | 原 Session 未过期且尚未提交时重载组件;否则由服务端核对原尝试,再提供已确认可用的托管页 | 把空白区域记成买家放弃,或无限重载组件 |
| 邮箱、地址或卡字段无效 | 拥有该字段的页面或组件 | 在字段旁给出可理解错误并把焦点移到需要修正的位置 | 用一个页面顶端的“参数错误”代替具体字段反馈 |
| 支付被拒绝 | 服务商和发卡行返回的明确结果 | 保留订单与金额,允许买家选择安全的替代方式或发起新的支付尝试 | 暴露内部拒绝规则,或把付款拒绝直接写成订单取消 |
| 银行、钱包或 3DS 被取消 | 外部支付动作或返回处理 | 回到原订单,显示已取消或仍在确认;结果明确后才允许再次付款 | 只凭浏览器返回参数就创建成功订阅 |
| 买家回来后仍无最终结果 | 支付结果处理 | 显示正在确认,继续等待 Webhook,或查询已经创建的服务商支付对象 | 默认成功、默认失败,或让买家反复点击支付 |
嵌入组件没加载出来时,前端不能直接新开一个 Hosted Checkout。当服务商允许重复挂载、原 Session 尚未过期,而且买家还没有提交付款时,可以继续使用原 Session 重载组件。
如果付款请求可能已经发到服务商,先查询原支付对象或等待 Webhook。只有确认原尝试失败、取消或没有产生扣款,服务端才能创建新的托管付款,并为它分配新的支付尝试编号和幂等键。浏览器只打开服务端返回、且域名经过校验的 Hosted Checkout 地址。
Hosted Checkout 可以省掉组件加载和字段校验代码,但创建接口超时、买家取消、回跳丢失、异步支付和重复事件仍由商户处理。组件式结账还要监控 SDK 初始化、容器卸载、价格变化后的重建、浏览器兼容和 CSP 失败。接入成本不能只数 Quickstart 写了多少行代码,还要算这些故障以后由谁处理。
支付组件可访问,不等于整个结账页可访问
使用经过无障碍评估的支付组件,只能减少卡号输入框内部的实现工作。页面标题、订单摘要、字段阅读顺序、弹层开关时的焦点、加载状态、错误提示、支付按钮、外部动作返回后的落点,以及放大后的周边布局,仍由商户负责。
Adyen 公布了 Web Drop-in 与 Components 的 VPAT,并说明 v5.49.0 及以上版本按 WCAG 2.1 Level AA 评估。VPAT 只覆盖服务商组件,不覆盖商户放在组件周围的页面。Adyen 的无障碍说明(在新标签页打开)也建议使用受评估版本。更换版本、覆盖组件样式或隐藏内置错误以后,原有评估结果不能直接套用。
一次完整键盘操作应当能走完价格确认、支付方式切换、字段输入、错误修正、外部认证和结果返回。焦点进入 iframe 后仍要有可见标记,弹层关闭后要回到打开它的控件,而不是页面顶部。错误文本需要关联到对应字段;页面放大到 200% 或移动键盘弹出时,合计金额和支付按钮仍应可达。屏幕阅读器需要读出当前步骤和结果,也不能反复播报没有变化的加载文字。
托管整页通常让服务商负责更完整的付款页面,商户仍要保证入口和返回页可用。嵌入式完整表单增加了容器、焦点和父页面脚本;可组合组件又把字段顺序、错误提示和响应式布局交回商户。团队无法持续测试浏览器和辅助技术时,多出来的页面控制权只会变成维护负担。
买家回到成功页,不代表付款已经成功
成功地址和取消地址只是浏览器要去哪里,不是付款证明。买家可以修改 URL、刷新结果页、在多个标签页打开同一链接,也可能付完款就断网,根本没有访问成功页。Stripe 的 Checkout 履约文档明确要求使用 Webhook,因为买家不一定会访问落地页;同一订单的开通请求还可能并发到达,因此必须防止重复执行。Stripe:Fulfill orders(在新标签页打开)
返回地址应由服务端从允许的 HTTPS 模板生成,只携带不能用来授权付款的内部订单号或购买编号。密钥、完整支付凭证和可长期复用的 Bearer Token 不能进入 URL、日志、Referer 或分析系统。浏览器收到服务商返回的数据后,只把它交给自己的服务端处理,再读取当前用户有权查看的订单结果。
付款结果和 SaaS 开通结果不能共用一个状态。结果页先显示付款仍在确认、付款失败或取消、付款已经确认;确认收款以后,再查询订阅或权益有没有开通。开通尚未完成时显示“付款已确认,正在开通”,只有订阅服务返回可用状态后才显示 Pro 权益。开通失败应由服务端重试或转人工处理,不能要求买家再次付款。
访问过 return_url、收到 SDK 成功回调或一次查询没有报错,都不能把付款写成成功。Adyen 也说明同步 resultCode 可能随后变化,不建议用它直接更新订单系统;最终支付结果应通过 Webhook 进入商户服务端。Adyen:Payment result codes(在新标签页打开)。
Webhook 可能先到,也可能在买家回到页面以后才到,后台对账还可能更晚。无论哪条消息先到,都要用同一笔购买编号和服务商支付 ID 找到原记录。付款一旦确认,迟到的取消回跳不能再把它改成失败。订阅服务随后按订单号和付款编号开通一次;即使买家连续刷新、Webhook 重试,或主动查询与事件同时完成,也不会重复开通 Pro,更不会因为开通暂时失败而再次扣款。
转化率要用同一购买任务验证
页面是否跳转,不能直接决定转化率。加载速度、支付方式是否出现、钱包有没有配置好、字段数量、地址自动完成、错误提示、品牌可信度、移动键盘遮挡和外部认证后的恢复,都可能比页面域名更直接地影响付款完成率。
2026 年 9 月 4 日的官方演示只能确认页面归属、总额、支付字段和支付方式入口,不能代表真实付款结果。Stripe 的 Full page 与 Elements 来自同一个官方交互演示;Airwallex Drop-in 来自它的官方沙箱,页面显示 Lumario 商品和 68 美元价格。两家的商品不同,因此 Airwallex 演示只用于确认嵌入式页面由谁负责,不参与转化率比较。
| 官方演示界面 | 能直接观察到什么 | 商户仍要完成什么 |
|---|---|---|
| Stripe Full page | 服务商页面连续显示订单摘要、优惠、税额、地址和付款字段;移动预览变成单列 | 从自己的服务端创建 Session,并处理取消、回跳和最终付款结果 |
| Airwallex Drop-in | 商户页面显示 68 美元商品摘要,Airwallex dropIn element iframe 内显示卡、钱包、先买后付和本地支付入口;当时还出现 CAPTCHA | 维护外层摘要、iframe 容器、页面脚本、错误和外部动作返回 |
| Stripe Elements | 示例商户拥有订单摘要,Payment、Express Checkout、Email 和 Address 是独立组件;移动布局仍由商户编排 | 决定组件顺序、状态协调、响应式、错误和无障碍行为 |
Stripe Full page 与 Elements 的界面状态来自 Stripe Checkout 官方演示(在新标签页打开);预构建 Drop-in 的外层页面和 iframe 状态来自 Airwallex 官方沙箱(在新标签页打开)。演示中出现的支付方式只代表当时沙箱状态,不证明任意商户、国家、币种或订阅交易都能使用这些方式。
这些演示只能说明页面由谁提供、组件怎样排列,不能说明哪种方式的真实交易转化率更高。演示商品、流量、用户信任和网络条件都不代表 RouteNest 的生产环境。要得到可靠结果,两种方案必须面对同一商品、价格、优惠、买家地区、支付方式和流量,而且都能正常加载、显示相同的可用方式并安全处理错误。
| 指标 | 它回答什么 | 必须保持的共同条件 |
|---|---|---|
| 结账启动率 | 买家是否愿意从价格页进入付款 | 同一价格与购买入口,避免按钮文案差异污染结果 |
| 付款字段到达率 | 页面是否加载成功,买家是否理解前置字段 | 按相同设备和网络条件分别统计,并保持必填业务信息一致 |
| 支付提交率 | 买家是否能完成输入并发起支付 | 同一支付方式可见性、地址与税务要求 |
| 最终付款成功率 | 提交后是否完成认证、跳转并得到成功结果 | 同一支付方式、地区、币种、风控与统计时间窗口 |
| 错误恢复率 | 遇到校验、拒绝或取消后能否继续付款 | 同一错误类型和可用替代方式 |
| 完成时间分布 | 哪个阶段产生等待或回退 | 从同一事件起点到服务端确认结果,不只计算成功页加载 |
实验结果要按支付方式和设备分别统计。Hosted 组显示 Apple Pay,而 Embedded 组因为域名配置错误只显示卡时,测到的只是配置差异;一组使用服务商优化过的地址表单,另一组多出五个产品字段时,测到的则是字段负担。两条路径先具备相同能力,才看得出把页面留在站内有没有实际收益。
三种 SaaS,为什么会选出不同结账方式
RouteNest Solo 由两名开发者维护,销售每月 24 美元的标准团队订阅。买家只需确认套餐、邮箱、账单或税务地址并选择支付方式,不会在付款过程中调整席位或购买复杂附加项。候选服务商的预构建页面已经覆盖目标支付方式,团队也没有专人维护支付前端。Hosted Checkout 因此足够:服务端创建 Session,浏览器跳转,返回页查询订单,Webhook 确认付款并防止重复开通。改成嵌入组件只会多出脚本、焦点和响应式维护。
RouteNest Enterprise 允许管理员在付款前调整 20 至 200 个席位、选择审计记录保留期限,并实时看到税前价格和年度折扣。服务商的完整付款页放不下这些相互依赖的设置,但卡号输入框仍可以由服务商托管。产品先在自己的页面完成配置,服务端生成一份有有效期且不能由浏览器修改的 Quote,再嵌入完整表单,或组合 Payment、Address 和钱包组件。预构建嵌入表单能放进确认区并接收最终金额时,就没有必要继续拆组件;只有支付字段必须与实时配置交错时,可组合组件才解决了真实问题。
RouteNest Global 面向美国、荷兰和东南亚团队,同时提供卡、钱包和当地银行方式。桌面卡支付可以留在嵌入组件中,iDEAL 会进入银行网页,部分移动钱包会打开应用,二维码则可能显示在电脑上、由手机完成。这里不存在一种始终不跳转的页面。服务端按买家、币种、设备和交易类型提供可用方式,所有路径都关联到同一笔购买;结果还没确认时,订单页继续显示处理中。页面可以不同,应付金额、订单和最终付款结果不能分叉。
Solo 只有在托管页缺少必需支付方式或字段时,才需要换成嵌入式;Enterprise 只有在完整嵌入表单仍放不下必要配置时,才拆成组件;Global 每增加一个地区或支付方式,都要重新确认它会不会跳转、怎样返回。完全自建只有同时满足三个条件才成立:服务商组件确实做不到关键流程,接管页面带来的收益能够量化,团队也能长期承担更大的 PCI、安全和运行责任。
接入后的升级和故障,才是主要成本
照着支付服务商的 Quickstart 显示出付款页,只能说明第一次接入跑通了。上线以后,托管页通常由服务商增加新支付方式、适配浏览器并修复字段可访问性;嵌入式表单要求商户继续维护容器、脚本加载和页面安全;可组合组件还要协调多个组件的版本、状态和错误;完全自建则要承担最完整的发布与合规测试。
| 上线后发生的变化 | 托管整页 | 托管嵌入式 | 可组合组件或自建 |
|---|---|---|---|
| 新增支付方式 | 多数情况下由服务商页面接入,商户仍需验证资格和回跳 | 需要确认组件版本、尺寸与外部动作 | 可能新增组件、布局、状态、错误和测试路径 |
| SDK 大版本升级 | 主要核对服务端 API 和 Session 行为 | 还要测试前端 SDK、初始化和父页面集成 | 每个组件、事件、样式覆盖和状态协调都要重新测试 |
| CSP 或脚本策略变化 | 商户仍要维护入口页和跳转安全 | 直接影响表单加载与 SAQ A 脚本条件 | 影响所有支付组件、监控和自有代码 |
| 浏览器或钱包规则变化 | 服务商承担大部分付款页适配 | 商户还要验证 iframe、弹层和顶层跳转 | 域名注册、用户手势、组件布局和降级都可能变化 |
| 无障碍要求或组件评估变化 | 重点复核入口和返回页 | 增加父页面、容器和焦点交接 | 整个字段顺序、错误提示和响应式界面重新验证 |
| 服务商或商户域名变化 | 重新核对品牌、返回 URL 和允许域 | 还要核对脚本来源、iframe 与钱包域名 | 支付适配代码、组件、令牌化流程和全部相关测试同时变化 |
Adyen 的 Drop-in 文档(在新标签页打开)把“增加支付方式通常不需要额外开发”列为预构建组件的优点,同时仍要求商户从服务端创建支付请求、处理额外认证动作和接收 Webhook。Adyen Web v6 的升级说明(在新标签页打开)还区分两种导入方式:一次打包全部支付方式时,可以只改账户配置;按需导入独立组件时,仍要修改前端代码。支付方式的界面可以交给服务商维护,下单、额外动作、Webhook 和订单状态仍是商户的工作。
客户端、支付方式、SDK、域名、服务商、卡号输入框来源或业务字段发生变化后,原来的选择都可能不再成立。这类变化可能同时改变页面元素来源、钱包资格、外部认证、返回地址、合规证明或无障碍评估。此时要重新检查这笔购买怎样下单、卡数据流向哪里,不能因为产品名称没变就沿用旧结论。
想换界面或服务商,哪些数据必须留在自己手里
降低退出成本,不需要从第一天就造一个包住所有服务商的万能 Checkout SDK。Product、Plan、Price、Quote、订单、订阅和开通状态要留在商户自己的系统里;服务商 Session、Payment、Price ID、界面配置和原始事件只保存在对接该服务商的记录与代码中。浏览器只执行服务端签发的短期支付动作,不能把某家 SDK 返回的对象直接当成内部订单。
在同一家服务商内,从 Hosted Checkout 换成嵌入式表单时,内部购买编号、成交金额和付款成功的判断规则不应改变。切换过程需要创建新支付尝试时,新尝试要有自己的编号和幂等键,但仍属于原订单;两个不同请求不能强行共用一个幂等键。
更换服务商时,需要替换的是外部价格映射、创建支付的对接代码、浏览器动作、事件转换和对账来源,内部目录与历史订单不应重写。如果业务代码到处保存 checkout_session_id、直接比较某家服务商的状态字符串,或收到组件事件就开通权益,服务商对象已经侵入内部订单,迁移时就只能逐处拆除。
| 要做的变化 | 需要改什么 | 哪些业务数据不能跟着变 | 最容易遗漏的后续工作 |
|---|---|---|---|
| 同一服务商:托管整页改为嵌入式完整表单 | Session 的展示方式、前端挂载、CSP、容器尺寸、焦点和回跳页面 | Product、Price、Quote、购买编号、订单、幂等规则、付款状态和 Webhook 处理 | 外部认证仍会离开页面;父页面脚本和无障碍责任增加 |
| 同一服务商:完整表单改为可组合组件 | 组件布局、SDK 事件、错误提示、地址和钱包排列、响应式与辅助技术测试 | 服务端核价、Session 或 Payment 创建规则、订单和开通结果 | 组件升级、字段顺序和多个加载状态要由商户长期维护 |
| 支付服务商 A 改为服务商 B | 外部价格映射、创建支付的适配代码、浏览器动作、Webhook 验签与事件转换、查询和对账来源 | 内部目录、固定报价、订单编号、订阅权益和历史账务引用 | 旧订阅续费、退款、争议和迟到事件仍要回到原服务商 |
| 关闭旧结账入口 | 停止为新购买创建旧渠道动作;旧支付对象继续由原接入处理 | 已有订单、订阅、退款和争议的完整历史 | 最后一笔新付款结束后,仍不能马上删除旧密钥、Webhook 或查询能力 |
旧结账入口停用后,正在进行的付款还要继续处理。旧 Session 可能收到迟到的 Webhook,已有订阅仍会在原渠道续费,退款和争议也要找到原支付对象。新购买改用另一种界面或服务商以后,旧渠道仍要保留处理存量交易所需的映射、密钥和查询能力,只是不再接收新订单。
RouteNest 的 iDEAL 跳转并不是嵌入失败。买家回到站内时,页面先显示“付款确认中”;服务端收到验签 Webhook 或主动查询确认付款后,订阅服务只开通一次 Pro,页面再显示权益可用。即使买家早于 Webhook 返回,也不会被误判为失败,更不会重复付款。
下一项工作是支付方式可用性诊断:确认目标买家、币种、设备和续费场景中哪些方式真的会出现,以及认证、回跳和异步等待分别怎样处理。
