Monetise your ChatGPT app
Use a prebuilt checkout page to collect payment outside your ChatGPT app.
If you need to monetise your ChatGPT app and need to collect payment outside of your app, you can use a prebuilt checkout page, and reference the example we provide in this guide. The steps here describe how to:
- Define MCP tools to facilitate the display of products and selection for purchase
- Collect payment information with a prebuilt Stripe-hosted Checkout page
- Monitor webhooks after a successful payment
MCP and the ChatGPT Apps SDK
This guide demonstrates how to integrate Stripe Checkout into your ChatGPT app. It doesn’t cover:
- Model Context Protocol (MCP) – see the MCP documentation.
- The ChatGPT Apps SDK. To learn how to build a ChatGPT app, see the ChatGPT App SDK documentation.
Set up Stripe
First, add the Stripe API library to your back end:
Create products and prices
In this example, we show you how to display a group of products in the ChatGPT app. Create products and prices in the Dashboard or with the Stripe CLI.
Register a Checkout MCP tool
Register an MCP tool that creates a Checkout Session for a given set of Prices. You call this tool from the ChatGPT App in an upcoming step.
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"
Register a ChatGPT UI tool and resource
Set up the UI for your ChatGPT app by registering an MCP tool and resource. This UI:
- Displays a list of products
- Allows the user to select which products they want to buy
- Redirects to Stripe Checkout to complete payment
Register a list products MCP tool
Create a “list products” MCP tool whose callback returns the price IDs of the products that you want to display in the UI.
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}}"
Register a list products UI resource
Create a “list products widget” MCP resource. This defines the UI code responsible for displaying the products.
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"], }, }, }, ], }) );
For example purposes, the UI markup is simple here. However, you could use UI frameworks such as React in a real app. See the ChatGPT App SDK documentation for additional examples.
<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>
Redirect to Checkout
When the user taps the Buy button in the ChatGPT app:
- Call the “buy products” tool to create a Checkout Session URL.
- Open the Checkout Session URL.
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 }); };