決済を受け付けます
MCP アプリで決済を安全に受け付けます。
プライベートプレビュー
- ChatGPT アプリ内での決済の受け付けは、アメリカで OpenAI によって承認された企業が利用できます。
- ChatGPT 即時決済でサポートされている決済方法は、カード、Apple Pay、Google Pay、および Link です。
このガイドでは、即時決済および Stripe で ChatGPT アプリ内で決済を受け付ける方法を紹介します。このフレームワークについての詳細については、ChatGPT 即時決済ドキュメントをご参照ください。
取引の図
Stripe のプロフィールを作成し、ChatGPT アプリを連結させます
Stripe プロフィールを作成し、OpenAI にあなたの Stripe アカウントへの接続をオーソリしてください。これにより、ChatGPT は顧客の決済情報を表す共有決済トークン (SPT) を安全に提供できるようになります。
- Stripe ダッシュボードで Stripe プロフィールを作成します。
- Stripe の代理販売者規約に同意し、 OpenAI を有効にするためにオーソリ をクリックし、プロフィールに接続してください。
- ネットワーク ID をコピーしてください。ChatGPT アプリで決済リクエストを作成する際に必要になります。
Stripe をセットアップする
まず、バックエンドに Stripe API ライブラリを追加します。
Stripe で購入ウィジェットを構築する
商品購入 MCP ツールおよび UI リソースを作成することで、ChatGPT アプリの UI を設定し定します。このフローは次のとおりです。
- チャットのコンテキストから商品を抽出します。
- 商品情報を表示し、顧客の配送先住所を収集します。
- 顧客がプロセスを進める準備ができたら、
window.を呼び出します。openai. requestCheckout
商品および価格の設定
この例では、ChatGPT アプリで商品の決済フローを表示できます。ダッシュボードや Stripe CLI で商品や価格を設定する方法をご紹介します。
メモ
自社専用のカスタム商品ロジックがある場合は、Stripe 用に商品を設定する必要はありません。代わりに、以降のセクションの Stripe Product API コールを自社の商品ロジックに置き換えてください。
MCP サーバーに商品購入リソースとツールを登録する
顧客が特定の商品を購入するためのチャットを表示したときに、ChatGPT が決済ウィジェットをレンダリングするように設定します。
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { registerAppTool, registerAppResource, RESOURCE_MIME_TYPE, } from "@modelcontextprotocol/ext-apps/server"; import { readFileSync } from "node:fs"; import Stripe from "stripe"; import { z } from "zod"; const stripe = new Stripe() const server = new McpServer({ name: "my-mcp-server", version: "1.0.0" }); const resourceUri = "ui://widget/buy-product-template.html"; registerAppResource( server, "buy-product-widget", resourceUri, { title: "Buy Product", description: "Buy Product widget", mimeType: RESOURCE_MIME_TYPE, }, async () => { const html = readFileSync("dist/ui/buy-product.html", "utf8"); return { contents: [ { uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html, }, ], }; } ); registerAppTool( server, "show-buy-product-widget", { title: "Buy Product", description: "Kickstart a checkout flow for a specific product.", // Add inputs here to help you find the product id inputSchema: { product_name: z.string() }, _meta: { ui: { resourceUri } }, annotations: { readOnlyHint: true } }, async () => { // Add logic here to get product id from input schema const product = await stripe.products.retrieve('prod_123456'); const amount = (await stripe.prices.retrieve(product.default_price as string)).unit_amount; return { content: [], structuredContent: { productName: product.name, amount: amount, priceID: product.default_price, }, }; } );"sk_test_BQokikJOvBiI2HlWgH4olfQ2"
Apps SDK で商品購入 UI を作成する
この UI は、前のステップのツールを実行する時に表示されます。以下の例では、最小限のマークアップを使用しています。本番環境のアプリでは、React などのフレームワークを使用できます。その他の例については、ChatGPT Apps SDK ドキュメントをご参照ください。
<div id="root"></div> <script type="module" src="/ui/mcp-app.js"></script>
import { App } from "@modelcontextprotocol/ext-apps"; const app = new App({ name: "BuyProduct", version: "1.0.0" }); await app.connect(); if (!window.openai?.requestCheckout) { throw new Error("requestCheckout is not available in this host"); } const root = document.getElementById("root"); let product = { name: "", amount: 0, priceID: "" }; const render = () => { root.innerHTML = ` <h1>${product.name || "Loading..."}</h1> <p>$${(product.amount / 100).toFixed(2)}</p> <form onsubmit="handleSubmit(event)"> <button type="submit">Proceed</button> </form> `; }; app.ontoolresult = (params) => { const { productName, amount, priceID } = params.structuredContent ?? {}; product = { name: productName ?? "", amount: amount ?? 0, priceID: priceID ?? "" }; render(); }; render(); </script>
Stripe で配送先住所を収集して税金を回収する
次のステップで使用するための税金を Stripe Tax API を使用して計算することができます。詳細については、税金を回収する をご参照ください。
ChatGPT 即時決済モダールを開く
これにより、決済手段を選択するよう促すメッセージが顧客に表示されます。前のステップの価格 ID に対応するよう、決済セッションを作成するロジックを追加します。以下のコードスニペットは価格 ID に UUID を付け加えて Checkout Session ID を作成します。
const getTax = (priceID) => { // Add your tax integration }; const createCheckoutSession = (priceID) => { const uuid = crypto.randomUUID(); return `${priceID}::${uuid}`; }; const handleSubmit = (e) => { e.preventDefault(); const { name, amount, priceID } = product; const tax = getTax(priceID); window.openai.requestCheckout({ // This is priceID passed in from the MCP buy product tool id: createCheckoutSession(priceID), // remove this when you are ready for live mode payment_mode: "test", payment_provider: { provider: "stripe", // Insert your Network ID from the Stripe dashboard merchant_id: networkID, supported_payment_methods: ["card"], }, status: "ready_for_payment", currency: "USD", line_items: [ { id: "line_items_123", item: { id: priceID, quantity: 1, }, base_amount: product.amount, subtotal: product.amount, tax: tax, total: product.amount + tax, }, ], totals: [ { type: "items_base_amount", display_text: product.name, amount: product.amount, }, { type: "subtotal", display_text: "Subtotal", amount: product.amount, }, { type: "tax", display_text: "Tax", amount: tax, }, { type: "total", display_text: "Total", amount: product.amount + tax, }, ], fulfillment_options: [], fulfillment_address: null, messages: [], links: [ { type: "terms_of_service", url: "https://example.com/terms", }, ], }); }
決済を完了するための MCP ツールを登録する
顧客が ChatGPT 決済 UI で決済方法を選択し、 支払うを選択すると、ChatGPT は complete_ ツールを呼び出し、PaymentIntent の作成に使用する SPT を返します。
入力として共有決済認証済みトークンを受け取り、Payment Intents API に渡して処理する complete_ MCP ツールを登録します。
const retrievePriceID = (checkout_session_id: string) => { const [priceID, uuid] = checkout_session_id.split('::'); return priceID; }; server.registerTool( "complete_checkout", { description: "Complete the checkout and process the payment", inputSchema: { checkout_session_id: z.string(), buyer: z .object({ name: z.string().nullable(), email: z.string().nullable(), phone_number: z.string().nullable(), }) .nullable(), payment_data: z.object({ token: z.string(), provider: z.string(), billing_address: z .object({ name: z.string(), line_one: z.string(), line_two: z.string().nullable(), city: z.string(), state: z.string(), country: z.string(), postal_code: z.string(), phone_number: z.string().nullable(), }) .nullable(), }), }, }, async ({checkout_session_id, buyer, payment_data}) => { const price = (await stripe.prices.retrieve(retrievePriceID(checkout_session_id as string))) // Add your tax logic const tax = getTax() // confirms the SPT stripe.paymentIntents.create({ amount: price.unit_amount + tax, currency: price.currency, shared_payment_granted_token: payment_data.token, confirm: true, }); return { content: [], structuredContent: { id: checkout_session_id, status: "completed", currency: price.currency, buyer, line_items: [], order: { id: "123", checkout_session_id, permalink_url: "", }, }, }; } );
テスト
実際のお金を動かさずにアプリをテストするには、Stripe のテスト環境で ChatGPT の決済テストモードを使用します。
- Stripe ダッシュボードでサンドボックスモードまたはテストモードに入ります。
- テスト用 Stripe プロフィールを作成し、テスト環境内で ChatGPT に連結させ、テスト用のネットワーク ID をコピーします。
- テストカードを想定してテスト用 SPT を生成するために、決済テスト環境を使用するように ChatGPT アプリの設定を更新してください。
- 決済をリクエストする際は、テスト用プロファイル ID を指定し、
payment_をmode testに設定してください。これにより、ChatGPT はテストカードを想定し、テスト用 SPT を生成します。server.jswindow.openai.requestCheckout({ id: priceID, payment_mode: "test", payment_provider: { provider: "stripe", merchant_id: "profile_test", supported_payment_methods: ["card"], }, - テスト用の Stripe API キーを使って、MCP ツールの実装において ChatGPT のテスト SPT を処理します。
- 本番環境とテスト環境で同一の Webhook 構成を設定し、テスト用 Webhook ハンドラーが本番システムに影響を与えないことを確認してください。例えば、本番用の Webhook が出荷をトリガーした場合、本番環境ではテストエンドポイントは出荷されたことだけをログに記録します。
これらのステップを完了したら、実際の資金を動かさずにアプリ内の決済フローを評価してください。
アプリを本番環境に公開する
アプリを本番環境に昇格する準備ができたとき:
- MCP ツールを Stripe の本番シークレットキー
(sk_に更新してください。live_ . . . ) - アプリの決済リクエストを本番プロフィール ID で更新し、テスト
payment_オプションを削除してください。mode
続いて、アプリで、ChatGPT アプリ審査に提出する前に必要となる本番決済の準備が整います。
注意
ChatGPT アプリを提出後は、本番の顧客に公開されているため、テスト決済モードを使用しないでください。