この記事では、2026年8月頃に正常に処理できたChatGPTの割引用Checkoutダイレクトカードの記録を補足します。当時は、「まずカードを紐付け、その後Checkoutを作成する」という方法を採用し、特定のカード発行会社の場合、チェックアウトページで直接送信すると拒否されやすいという問題を回避しました。
声明 :本記事は、オープンソースコミュニティの既存プロジェクトを参考にしています。私が担当した部分は、主に注文の作成と自動決済のプロセスを連携させることでした。関連するAPIやリスク管理ルールは随時変更される可能性があります。ここでは、プロトコルの調査およびトラブルシューティングの記録としてのみ記載していますので、違法な目的には使用しないでください。
現在、直卡のリスク管理ではカード発行元がますます重視されるようになっており、単にカードを紐付けるだけではうまくいかない場合もあります。ここでは、当時のプロトコルリンクと実際に遭遇した問題点を記録しておきます。
1. なぜ「まずカードを登録」する必要があるのか
通常の人とコンピューターによる決済の流れは、ユーザーがウェブページを開き、チェックアウト画面に進み、埋め込まれたStripe Elementsにカード番号を入力して送信するというものです。ただし、特定のカード発行会社(テスト用の 4513 (カードリーダー)を使用する場合、決済ページで直接クーポンコードを入力すると、ほぼ確実にエラーになります。
コミュニティは試行錯誤の末、切り離しの方法を見出しました。同じカードであっても、決済ページで直接入力するのではなく、まず独立したカード登録プロセスを経てアカウントに「アタッチ(Attach)」し、その後、保存済みのそのカードを使って決済を行うための割引チェックアウトを作成するという方法です。 pm_(PaymentMethod)で、引き落としが正常に処理されれば問題ありません。
flowchart LR
subgraph Direct ["直接结账路径 (易被拒)"]
D1["优惠 Checkout 页面"] --> D2["Stripe Elements 输入卡号"] --> D3["直接扣款风控拦截 ❌"]
end
subgraph Split ["解耦路径 (先绑后结)"]
S1["SetupIntent 独立绑卡"] --> S2["Stripe 校验卡片生成 pm_"] --> S3["Attach 到账号作为默认卡"]
S3 --> S4["创建优惠 Checkout"] --> S5["消费已有 pm_ 完成确认 ✔️"]
end
2つの入口では、検証プロセスが異なります:
- 直接お支払い :チェックアウトページで新しいカード情報を入力する際、Stripe Radar とプラットフォームは、即時決済ポリシーと入力行動を組み合わせて、リアルタイムの不正利用防止評価を行います。
- 事前バインド :を通じて
/backend-api/payments/payment_methodStripe による決済の連携を開始するSetupIntent、カードの基本的な利用可能性と、その後の引き落とし承認(オフセッション・セットアップ)を検証するために使用されます。2つのプロセスでは検証ルールが異なり、対応する加盟店スライスキー(OpenAIで一般的なKslHRdbaPgとC6h1nxGoI3)も異なる可能性があります。
実装にあたっては、もともと一連の動作であったものを、「カードの個別登録」と「旧カードの参照による支払い」という2つの段階に分割する必要があります。
2. アカウントセッションとコンテキストの分離
自動化を実行する際、入力として通常は有効なアクセス・トークン(以下、AT)が指定されます。プログラムはATからアカウントIDなどの情報を解析し、各実行ユニットごとに独立したセッションコンテキストを確立します。
Account Context
├── Access Token (用于调用业务 API)
├── Account ID (标识计费归属)
├── Device ID (模拟客户端设备)
└── Session Cookies (维护身份与防爬会话)
コンテキストの分離が不十分だと、最もトラブルが発生しやすい箇所となります。Stripe やプラットフォームのAPIは、IP、Cookie、セッションの帰属を確認しています。アカウントAのデバイスIDやCookieがアカウントBのリクエストに混入してしまうと、軽度の場合はステータスが見つからないというエラーが発生し、重度の場合は連座制によりリスク管理の対象となってしまいます。
複数のアカウントを一括処理する場合は並列処理が可能ですが、単一のアカウントについては、内部のカード紐付けおよび決済の手順は、ロックをかけて順次実行する必要があります。
3. カード登録の手順と実際の問題点
カード事前登録の目的は、いかなるサブスクリプション料金も発生させることなく、Stripeから有効な pm_... そして、それを現在のアカウント名に登録する。
3.1 プロトコルの転送経路
- クライアントによるプラットフォームAPI利用申請
SetupIntent、手に入れるclient_secretおよび対応する Stripe Publishable Key(pk_live_...); - ブラウザまたはヘッドレス環境で Stripe Elements を読み込み、カード番号、有効期限、CVC を Stripe に直接送信する。
- 調
stripe.confirmCardSetup、Stripe による検証が完了し、PaymentMethod ID が生成されます; - クライアント通知プラットフォームは、これを
pm_デフォルトの支払い方法に設定する。
sequenceDiagram
participant Client as 自动化客户端
participant OAI as 平台 API (ChatGPT)
participant Stripe as Stripe 网关
Client->>OAI: POST /payments/payment_method (申请 SetupIntent)
OAI-->>Client: 返回 client_secret 与 pk_live
Client->>Stripe: confirmCardSetup (卡号/CVC 提交)
Stripe-->>Client: 返回成功并生成 pm_xxxx
Client->>OAI: 设置默认付款方式 (Attach)
OAI-->>Client: 确认绑定指令已接收
3.2 3つの実際的な問題
このロジックを自動化に組み込む際、3つの具体的な技術的な落とし穴があります:
パブリッシュ可能なキーが見つかりません
一部の新規アカウントが初めて SetupIntent をリクエストした際、API は Intent 本体のみを返し、レンダリングコンポーネントに必要な Publishable Key を返さなかった。 同じアカウントセッション内で、まず軽量版のチェックアウト初期化を一度実行し、その後戻ってきてコンテキストを読み込むことができます。他のアカウントの公開鍵を流用することはできません。
UI コンポーネントの再利用時の並行処理による競合
複数のアカウントを一括処理する場合、サーバー側のSetupIntentは並行して準備できますが、フロントエンドのページには通常、1セットのCard Elementしか表示されません。複数のタスクが同時に呼び出されると confirmCardSetup、その場合は直接「in-flight」の競合として報告されます。
サーバー側はそれぞれのSetupIntentを並行して準備できます。フロントエンドでのカード登録段階になると、単一のキューを使用して1つずつ確認を行います。カードの確認が成功した後、その後のAttachリクエストを並行して送信します。
Stripe がプラットフォーム「Attach」との間の遅延を確認
stripe.confirmCardSetup 「成功」と表示された場合は、Stripe の設定が完了したことを示しているだけです。 pm_、プラットフォーム独自の請求システムでは、現時点ではその情報を確認できない可能性があります。
「デフォルトの支払い方法の設定」を完了したら、プラットフォームをポーリングする必要があります。 saved_payment_methods インターフェース。目標 pm_ リストに表示された後に「チェックアウト」を作成してください。そうしないと、カードの登録は成功したものの、請求明細に一時的にカード情報が表示されない場合があります。
4. 割引の連携:Checkout と金額制限
カードの「Attach」が成功してから、初めて「Checkout」の割引作成が開始されます。ここでいう「抽出」とは、実際には、アカウントにもともとあるキャンペーン参加資格を、ステータスが明確で、APIを呼び出して確認できる一時的な注文に変換することを指します。
flowchart TD
A["已完成 Attach 的账号"] --> B["创建优惠 Checkout (NL/US等)"]
B --> C["应用 Promotion / 折扣代码"]
C --> D["重新读取 Checkout Snapshot"]
D --> E{"金额与币种门禁校验"}
E -- 异常/非预期扣费 --> F["硬终止并告警 🛑"]
E -- 符合预期 (如 0 元试用) --> G["读取当前 Customer Context"]
G --> H["校验 pm_ 归属并生成 ConfirmationToken"]
H --> I["确认支付 (Confirm)"]
金額の確認
キャンペーンの有効期限が切れた後に定価(例えば20ドル)が引き落とされるのを防ぐため、確認する前に金額を確認してください:
- Promotion インターフェースが 200 を返したからといって、割引が実際に適用されたとは限りません。
- 「Checkout Snapshot」内の内容をもう一度読み直す必要があります。
amount_totalとcurrency; - 「無料トライアル」が目的の場合は、支払額が0でなければなりません。金額が正しくない場合や通常のサブスクリプション料金が表示されている場合は、直ちにタスクを中止してください。
5. 支払い前の支払い方法の確認
引き落としを最終確認する前に、必ず双方向の照合を行う必要があります:
- アカウントの観点から
saved_payment_methodsリスト; - 現在の Checkout インスタンス内にマウントされている
Customer Contextお支払い方法。
両側に、先ほど結んだあの1つを必ず同時に含める必要があります pm_、そうして初めて、Stripe の設定を続行できます。 ConfirmationToken(ctoken_...),最後にプラットフォームの設定を調整し、 /confirm インターフェースの送信。
Saved PaymentMethod (账号侧)
↓
Customer Context (订单侧一致性核验)
↓
Stripe ConfirmationToken (生成临时确认凭证)
↓
ChatGPT Checkout Confirm (平台发起终审)
↓
Stripe PaymentIntent / SetupIntent (网关完成状态结算)
0元のトライアル注文の場合、基本的に確認されるのは SetupIntent;もし~に遭遇した場合は requires_action(さらなるチャレンジ検証が必要な場合)、プログラムはチャレンジを捕捉し、対応する検証モジュールに引き渡す必要があり、APIが200を返したからといって、安易に成功とみなしてはならない。
6. 成功の判定方法と再試行のタイミング
リンク全体については、各ステップの実際の状態に基づいて進捗を判断する必要があり、単にリクエストにエラーが発生したかどうかだけを見るだけでは不十分です:
| 段階 | 点検項目 | エラー処理 |
|---|---|---|
| カード認証 | Stripe から返された有効な pm_ | カード拒否のメッセージ:カードヘッドが無効です。タスクを破棄してください。 |
| Attach マウント | アカウントの saved_payment_methods 対象のIDを特定した | 短周期のバックオフポーリング。タイムアウトした場合はセッションをリセットする |
| お得なアプリ | 「Checkout Snapshot」内の amount_total 基準を満たす | 金額が間違っている場合は直ちに取引をキャンセルして終了し、引き落としは厳禁とする |
| 注文の関連付け | チェックアウトで同じものを見つけた pm_ | Checkout Context を再初期化する |
| 最終状態の確認 | 注文ステータスが「Active」になった場合、またはIntentが succeeded | 3DS / hCaptcha の処理またはマーキングの失敗 |
ネットワークの不安定さや一時的なタイムアウトが発生した場合は、現在のステップを再試行できます。金額が正しくない、セッションが期限切れ、またはIDが一致しない場合は、今回のコンテキストをクリアして最初からやり直してください。前回のコンテキストに残ったデータを pm_ あるいは、クッキーを次のラウンドに進める。
当時、正常に動作していた手順は、まずカードを保存し、Attachの完了を確認してから、Checkoutを作成して確認するというものでした。各ステップで対応するステータスを確認する必要があり、エラーが発生した場合でも原因を特定しやすかったです。
iDEAL では、事前にカードを登録する必要はありません。後半では Provider Redirect に切り替わりますので、別途記録してください。次の記事。

