ChatGPT アプリを収益化する
構築済みの決済画面を使用して、ChatGPT アプリ外で決済を受け付けます。
ChatGPT アプリを収益化し、アプリ外で決済を受け付ける必要がある場合は、構築済みの Checkout ページを使用し、このガイドで提供している例を参照してください。ここでは、以下の手順について説明します。
- MCP ツールを定義して、商品の表示と購入商品の選択を容易にする
- Stripe がホストする構築済みの Checkout ページで決済情報を収集する
- 決済成功後の Webhook の監視
MCP と ChatGPT Apps SDK
このガイドでは、Stripe Checkout を ChatGPT アプリに統合する方法を説明します。以下については説明していません。
- Model Context Protocol (MCP)。MCP ドキュメントを参照してください。
- ChatGPT Apps SDK。ChatGPT アプリの構築方法については、ChatGPT App SDK ドキュメントを参照してください。
Stripe をセットアップする
まず、バックエンドに Stripe API ライブラリを追加します。
商品および価格を作成する
この例では、ChatGPT アプリで商品のグループを表示する方法を説明します。ダッシュボードまたは Stripe CLI で商品と価格を作成します。
Checkout MCP ツールを登録する
所定の価格に対して Checkout Session を作成する MCP ツールを登録します。このツールは、後続の手順で ChatGPT アプリから呼び出します。
server.js
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 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" }); async function createCheckoutSession(priceIds) { const lineItems = priceIds.map((price) => ({ price, quantity: 1 })); const session = await stripe.checkout.sessions.create({ mode: "payment", line_items: lineItems, success_url: "https://example.com/checkout/success", }); return session; } server.registerTool( "buy-products", { title: "Buy products", description: "Create a checkout page link for purchasing the selected products", inputSchema: { priceIds: z.array(z.string()) }, }, async ({ priceIds }) => { const session = await createCheckoutSession(priceIds); return { content: [ { type: "text", text: `[Complete your purchase here](${session.url})`, }, ], structuredContent: { checkoutSessionId: session.id, checkoutSessionUrl: session.url, }, }; } );"sk_test_BQokikJOvBiI2HlWgH4olfQ2"
ChatGPT UI ツールとリソースの登録
MCP ツールとリソースを登録して、ChatGPT アプリの UI を設定します。この UI では以下を実行します。
- 商品のリストを表示する
- ユーザーが購入する商品を選択できるようにする
- Stripe Checkout にリダイレクトして決済を完了する
list products MCP ツールを登録する
コールバックで UI に表示する商品の価格 ID を返す「list products」MCP ツールを作成します。
server.js
const listProductsUri = "ui://list-products-v1.html"; server.registerTool( "list-products", { title: "List products", description: "List the products available for purchase", _meta: { "openai/outputTemplate": listProductsUri }, }, async () => { const suggestedProducts = [ // The price IDs from the earlier step { priceId:, name: "Test product 1" }, { priceId:"{{PRICE_ID}}", name: "Test product 2" }, ]; return { structuredContent: { products: suggestedProducts }, content: [], }; } );"{{PRICE_ID}}"
list products UI リソースの登録
「list products widget」MCP リソースを作成します。これにより、商品を表示する UI コードが定義されます。
server.js
const listProductsHTML = readFileSync("ui/list-products.html", "utf8"); server.registerResource( "list-products-widget", listProductsUri, {}, async (uri) => ({ contents: [ { uri: uri.href, mimeType: "text/html+skybridge", text: listProductsHTML, _meta: { "openai/widgetCSP": { connect_domains: ["https://checkout.stripe.com"], resource_domains: ["https://checkout.stripe.com"], }, }, }, ], }) );
この例では、UI マークアップはシンプルにしています。ただし、実際のアプリでは React などの UI フレームワークを使用できます。その他の例については、ChatGPT App SDK ドキュメントを参照してください。
ui/list-products.html
<div id="root"></div> <script> /** * UI markup and event handlers */ const renderProduct = (product) => { return ` <label> <input type="checkbox" name="cart[]" value="${product.priceId}"> ${product.name} </label> `; }; const renderApp = (products) => { const root = document.getElementById("root"); root.innerHTML = ` <h1>Select products to purchase</h1> <form onsubmit="handleSubmit(event)"> ${products.map(renderProduct).join("")} <button type="submit">Buy</button> </form> `; }; /** * Render the list of products from the tool's structuredContent */ const handleSetGlobal = (event) => { const { products } = event.detail.globals["toolOutput"] ?? []; renderApp(products); }; window.addEventListener("openai:set_globals", handleSetGlobal, { passive: true, }); </script>
Checkout にリダイレクトする
ユーザーが ChatGPT アプリで 購入 ボタンをタップすると、以下のようになります。
- 「buy products」ツールを呼び出して、Checkout Session URL を作成します。
- Checkout Session URL を開きます。
ui/list-products.html
const handleSubmit = async (event) => { event.preventDefault(); const formData = new FormData(event.target); const priceIds = Array.from(formData.values()); const { structuredContent } = await window.openai.callTool("buy-products", { priceIds, }); window.openai.openExternal({ href: structuredContent.checkoutSessionUrl }); };