这篇整理一下 2026 年 7-8 月前后短暂能跑的 iDEAL 提链路线。后来 iDEAL 限制明显收紧,也开始搞一号一扫了。这里保留当时观察到的请求和状态变化。
声明 :本文参考了开源社区的已有项目和提链脚本。我做的部分主要是把链接提取和后续支付流程串起来。相关接口与风控规则随时可能变化,这里只作协议研究和排错记录。
1. iDEAL 提链与直卡的区别
1.1 为什么需要提链?
ChatGPT 的 Checkout 使用 Stripe。访问 IP 位于不同地区时,系统会返回当地可用的支付方式,例如荷兰的 iDEAL、印度的 UPI 和巴西的 PIX。
这里先看访问 IP 所在地区,再让 billing_details.country、billing_details.currency 等结算信息与该地区保持一致。在荷兰 IP 的正常 Checkout 响应中,payment_method_types 可能包含 ideal。
提链没有绕过或强行开启支付方式。程序只在 Checkout 已经返回 ideal 时继续创建对应的 PaymentMethod,并从后续的 requires_action 状态里读取银行收银台的跳转地址(Redirect URL)。
1.2 直卡与 iDEAL 提链的分叉对比
在自动化方案里,“直卡绑定”和“iDEAL 提链”完全是两码事:
| 维度 | 直卡绑定方案 | iDEAL 提链方案 |
|---|---|---|
| 付款方式依托 | 账号里预先存好并 Attach 的 pm_ 银行卡 | 本次 Checkout 临时创建的独立 pm_ |
| 用户交互 | 全程在后台或账号内部完成 | 必须交接给第三方银行收银台 |
| 风控敏感点 | 极度吃卡头(BIN)信誉与 SetupIntent 授权 | 吃全流程 IP/TLS 指纹一致性与重定向真实性 |
| 最终产物 | 直接完成绑定或扣款 | 拿到一条能继续跳转付款的 Provider Redirect 链接 |
flowchart TD
A["有效 Access Token (AT)"] --> B["创建对应区域的优惠 Checkout"]
B --> C["应用 Promotion 并校验最终金额"]
C --> D{"支付路径决策"}
subgraph DirectCard ["直卡分支"]
E1["读取已绑定的默认 pm_"] --> E2["创建 ConfirmationToken"]
E2 --> E3["Stripe 确认扣款"]
end
subgraph IdealExtract ["iDEAL 提链分支"]
F1["向 Stripe 创建 iDEAL pm_"] --> F2["向平台发起 Confirm 确认"]
F2 --> F3["捕获 requires_action 状态"]
F3 --> F4["提取 Provider Redirect URL"]
end
D -->|直卡| E1
D -->|iDEAL| F1
2. iDEAL 提链流程
根据当时的浏览器 HAR 抓包,从拿到用户登录会话(AT)到取得跳转链接,要经过下面 9 步:
1. Session 鉴权准备 → 获取并校验 Access Token
2. 创建 Checkout 会话 → 传入 country="NL", currency="EUR", checkout_ui_mode="custom"
3. 应用优惠 (Promotion) → 绑定试用优惠活动(如 0 元试用资格)
4. 税务与会话初始化 → 调用 Stripe payment_pages/init 或 elements/sessions
5. 前置状态核验 → 校验 payment_method_types 包含 ideal 并对齐金额
6. 创建 PaymentMethod → 向 Stripe 申请 type="ideal" 的临时 pm_
7. 确认支付 (Confirm) → 调用平台 /confirm 接口触发转交
8. 处理审批 (Approve) → 遇 requires_approval 时补充挑战凭证或等待上游放行
9. 提取跳转链接 → 从 requires_action.redirect_to_url 提取目标地址
sequenceDiagram
participant Worker as 自动化 Worker
participant OAI as OpenAI 账单服务
participant Stripe as Stripe 网关
participant Bank as iDEAL 银行网关
Worker->>OAI: POST /payments/checkout (NL/EUR, custom)
OAI-->>Worker: 返回 oaics_xxxx 与 publishable_key
Worker->>OAI: POST /payments/checkout/promotion (应用优惠)
Worker->>Stripe: POST /v1/payment_methods (type=ideal, bank=xxx)
Stripe-->>Worker: 返回 pm_ideal_xxxx
Worker->>OAI: POST /payments/checkout/confirm (带入 pm_)
OAI->>Stripe: 请求扣款/授权
Stripe-->>OAI: 返回 requires_action (redirect_to_url)
OAI-->>Worker: 返回包含 hooks.stripe.com/redirect 的跳转结构
Worker->>Worker: 解析并安全校验 Hostname
Worker-->>Bank: (交付给用户或进一步完成支付)
3. 创建 PaymentMethod 前的检查
中间状态没有对齐时,继续请求只会留下无法使用的对象。因此创建 PaymentMethod 前要先完成下面几项检查。
3.1 Checkout Session 存在性
调完建单接口,必须拿到 oaics_... 格式的会话 ID 和 Stripe Publishable Key。如果只拿到一个普通的 Hosted 网页链接而没有底层会话 ID,后续就没办法调底层 API。
3.2 支付方式检查
Stripe 支持 iDEAL,不等于每个地区、每个访问 IP 下的 Checkout 都会返回它。代码需要检查 payment_method_types 是否包含 "ideal";没有就停止当前任务,不尝试自行添加或开启。
3.3 计费快照(Snapshot)与金额门禁
如果是跑零元试用活动,需要单独核对最终金额:
- 优惠接口返回成功不算数,必须重新读一遍 Checkout Snapshot 里的
amount_total; - 目标是零元试用时,最终应付金额必须严格为 0;如果是原价代充,金额也必须严格吻合标价;
- 金额对不上(例如恢复为原价 20 欧元)时,立即停止确认。
4. 创建 PaymentMethod 并处理确认状态
前置检查都过了,程序才会向 Stripe 申请创建针对本单的 iDEAL PaymentMethod。
4.1 PaymentMethod 的单次约束
iDEAL 的 pm_ 是一次性的,只能绑在当前这笔 Checkout 上。如果这一轮中途挂了,上一轮生成的 pm_ 必须直接扔掉,绝对不能塞给下一张订单复用。
4.2 确认后的几种状态
调用平台的 /confirm 后,响应通常落在下面三种情况:
- 返回
requires_action,其中带有redirect_to_url,可以继续提取 URL; - 返回
requires_approval,需要补上带 Turnstile PoW 算力证明的 Sentinel Token,或者等待平台异步处理; - Stripe 或上游银行仍处于
processing,需要短周期轮询状态。
flowchart TD
A["POST /checkout/confirm"] --> B{"解析当前响应状态"}
B -->|含有 redirect_to_url| C["提取并验证 Redirect URL"]
B -->|requires_approval| D["触发 Sentinel / Turnstile 凭证审批"]
D --> E["短周期轮询 Checkout 状态"]
B -->|processing / pending| E
E -->|成功生成跳转| C
E -->|超时 / 拒单 / 状态失效| F["标记失败并优雅退出"]
C --> G["输出 provider_link_ready"]
5. 网络和重定向检查
自动化过程中,网络出口变化和错误的重定向地址最容易导致失败。
5.1 全流程 IP 与 TLS 指纹一致性
从创单、初始化、建 pm_ 到最后 confirm,整条链路应保持 同一个出口 IP 和同一套 TLS 指纹(例如用 curl_cffi 固定 Chrome 或 Safari 版本)。前面用代理 A 建单、后面换代理 B 确认,可能收到 invalid_request_error 或拒单。
5.2 Redirect 跳转域名的安全校验
拿到 URL 后不能只做字符串查找(比如 url.includes("ideal.nl"))。开放重定向和伪装域名都可能通过这种判断:
https://ideal.nl.attacker.invalid/pay
https://phishing-site.example/?redirect=https://ideal.nl
程序应使用标准 URL 解析库提取 Hostname,再与白名单匹配。只放行 Stripe 官方跳转域(如 hooks.stripe.com)和受信任的银行网关域名,其他地址直接丢弃。
6. 分开记录提链和支付
工具中可以把“提链”和“支付”分成两个状态:
{
"jobId": "ideal_task_98234",
"extractionStatus": "provider_link_ready",
"paymentStatus": "awaiting_payment",
"expiresAt": "2026-08-20T00:25:00Z"
}
provider_link_ready:已经从正常确认结果中取得可付款的收银链接;awaiting_payment:说明钱还没付,依然需要等人在银行页面真正完成扫码或授权。
分开记录后,链接生成和实际付款可以分别处理超时与重试。
这条路线现在还能不能用
这份记录主要保留 Stripe Checkout、PaymentMethod、Confirm 和 Redirect 之间的状态顺序。
支付风控会持续变化。iDEAL 这类路线不涉及绑卡或卡头,需要关注的是支付方式是否开放、全流程 IP/TLS 指纹是否一致,以及确认后的状态。拿到跳转链接也不代表支付完成,后续仍需在银行页面完成授权并确认付款结果。这篇主要保留当时的请求顺序,方便以后排错。

