# Zahlung akzeptieren Zahlungen sicher akzeptieren mit Ihrer MCP-App. # Weiterleitung > This is a Weiterleitung for when platform is web and ui is stripe-hosted. View the full page at https://docs.stripe.com/agentic-commerce/apps/accept-payment?platform=web&ui=stripe-hosted. Collect payments outside your app with a prebuilt Stripe-hosted Checkout page. This guide shows how to: - Definieren von Model Context Protocol (MCP)-Tools, um Produkte anzuzeigen und Kundinnen und Kunden die Auswahl der zu kaufenden Posten zu ermöglichen - Zahlungen mit [einer vorgefertigten, von Stripe gehosteten Checkout-Seite](https://docs.stripe.com/payments/checkout.md) einziehen - Überwachen Sie nach erfolgreicher Zahlung die Webhooks ## Stripe einrichten Add the Stripe API library to your back end. #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ## Produkte und Preise erstellen This example displays a group of products in the MCP app. [Create products and prices in the Dashboard or with the Stripe CLI](https://docs.stripe.com/products-prices/manage-prices.md). ## Registrieren Sie ein Checkout MCP-Tool Registrieren Sie ein MCP-Tool, das eine [Checkout-Session](https://docs.stripe.com/api/checkout/sessions.md) für einen Satz an *Preisen* (Prices define how much and how often to charge for products. This includes how much the product costs, what currency to use, and the interval if the price is for subscriptions) erstellt. Sie rufen dieses Tool in einem späteren Schritt über die MCP-App auf. ```javascript 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"; // Follow https://docs.stripe.com/keys-best-practices to protect your Stripe API keys. const stripe = new Stripe(process.env.STRIPE_API_KEY); const server = new McpServer({ name: "my-mcp-server", version: "1.0.0" }); const resourceUri = "ui://list-products.html"; 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; } // Register the tool that creates a checkout 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, }, }; } ); ``` ## Registrieren Sie ein Tool für die Nutzeroberfläche und eine Ressource Richten Sie die Nutzeroberfläche für Ihre MCP-App ein, indem Sie ein MCP-Tool und eine Ressource registrieren. Diese Nutzeroberfläche: 1. Eine Produktliste wird angezeigt 1. Ermöglicht der Kundin/dem Kunden die Auswahl der zu kaufenden Produkte 1. Weiterleitung an Stripe Checkout, um die Zahlung abzuschließen ### Register a product list MCP tool Create a product list MCP tool. Its callback returns the price IDs for the products to display in the UI. ```javascript registerAppTool( server, "list-products", { title: "List products", description: "List the products available for purchase", _meta: { ui: { resourceUri } }, }, async () => { const suggestedProducts = [ // The price IDs from the earlier step { priceId: "{{PRICE_ID}}", name: "Test product 1" }, { priceId: "{{PRICE_ID}}", name: "Test product 2" }, ]; return { structuredContent: { products: suggestedProducts }, content: [], }; } ); ``` ### Register a product list UI resource Erstellen Sie eine MCP-Ressource für das Produktlisten-Widget. Sie definiert die Nutzeroberfläche, die die Produkte anzeigt. ```javascript // Register the resource that serves the bundled HTML registerAppResource( server, "list-products-widget", resourceUri, { mimeType: RESOURCE_MIME_TYPE }, async () => { const html = readFileSync("dist/ui/list-products.html", "utf8"); return { contents: [ { uri: resourceUri, mimeType: RESOURCE_MIME_TYPE, text: html, }, ], }; } ); ``` This example uses minimal markup. In a production app, use a framework such as React. See the [MCP Apps documentation](https://modelcontextprotocol.github.io/ext-apps/) for additional examples. ```html
``` ```js import { App } from "@modelcontextprotocol/ext-apps"; const app = new App({ name: "ProductList", version: "1.0.0" }); // Establish communication with the host await app.connect(); /** * UI markup and event handlers */ const renderProduct = (product) => { return ` `; }; const handleSubmit = async (event) => { // We'll fill this in next } const renderApp = (products) => { const root = document.querySelector("#root"); root.innerHTML = `

Select products to purchase

${products.map(renderProduct).join("")}
`; document .querySelector("#product-form") ?.addEventListener("submit", handleSubmit); }; /** * Render the list of products from the tool's structuredContent */ app.ontoolresult = (params) => { const { products } = params.structuredContent ?? {}; if (products) { renderApp(products); } }; ``` ## Weiterleiten zu Checkout Wenn die Kundin/der Kunde in der MCP-App auf **Kaufen** klickt: 1. Call your “buy products” tool to create a Checkout Session URL. 1. Öffnen Sie die URL der Checkout-Session. Aktualisieren Sie die `HandleSubmit`-Funktion: ```javascript const handleSubmit = async (event) => { event.preventDefault(); const formData = new FormData(event.target); const priceIds = Array.from(formData.values()); // Call the buy-products tool to create a Checkout Session const { structuredContent } = await app.callServerTool({ name: "buy-products", arguments: { priceIds }, }); if (typeof structuredContent?.checkoutSessionUrl === "string") { await app.openLink({ url: structuredContent.checkoutSessionUrl }); } }; ``` ## Bearbeiten Sie erfolgreiche Aufträge Handle successful orders by listening to `checkout.session.completed` (and `checkout.session.async_payment_succeeded` for delayed methods) and calling an idempotent fulfillment function that retrieves the Checkout Session (expand `line_items`), verifies payment_status, and fulfills the items. Verwenden Sie eine `success_url-`Zielseite, um die Ausführung unmittelbar nach der Weiterleitung auszulösen, verlassen Sie sich jedoch auf Webhooks, um sicherzustellen, dass jede Zahlung ausgeführt wird. Test locally with the Stripe CLI, then deploy your webhook endpoint. For step-by-step instructions, see [Fulfill payments received with the Checkout Sessions API](https://docs.stripe.com/checkout/fulfillment.md?payment-ui=stripe-hosted). ## See also - [Steuern einziehen](https://docs.stripe.com/payments/checkout/taxes.md) - [Erfassen von Versand- und sonstigen Kundeninformationen](https://docs.stripe.com/payments/checkout/collect-additional-info.md) - [Branding anpassen](https://docs.stripe.com/payments/checkout/customization.md) - [Anpassen Ihrer Bestätigungsseite](https://docs.stripe.com/payments/checkout/custom-success-page.md) # Sofort-Bezahlvorgang > This is a Sofort-Bezahlvorgang for when platform is web and ui is direct-api. View the full page at https://docs.stripe.com/agentic-commerce/apps/accept-payment?platform=web&ui=direct-api. > - Das Akzeptieren von Zahlungen in ChatGPT-Apps ist für von OpenAI zugelassene Unternehmen in den USA verfügbar. - Beim ChatGPT-Instant-Checkout unterstützte Zahlungsmethoden sind Karten, Apple Pay, Google Pay und [Link](https://docs.stripe.com/payments/link.md). This guide shows how to accept a payment within your ChatGPT app using Instant Checkout and Stripe. For details about this framework, see the [ChatGPT Instant Checkout documentation](https://openai.com/index/buy-it-in-chatgpt/). ## Transaktionsdiagramm Diagramm für den ChatGPT Instant Checkout Flow (See full diagram at https://docs.stripe.com/agentic-commerce/apps/accept-payment) ## Stripe-Profil erstellen und ChatGPT-App verbinden Erstellen Sie ein Stripe-Profil und autorisieren Sie OpenAI, sich mit Ihrem Stripe-Konto zu verbinden. So kann ChatGPT auf sichere Weise ein [Shared Payment Token (SPT)](https://docs.stripe.com/agentic-commerce/concepts/shared-payment-tokens.md) bereitstellen, das die Zahlungsdaten der Kundin/des Kunden darstellt. 1. Erstellen Sie Ihr [Stripe-Profil](https://docs.stripe.com/get-started/account/profile.md) im Stripe-Dashboard. 1. Akzeptieren Sie die allgemeinen Konditionen für Verkäufer/innen von Stripe und klicken Sie auf **Autorisieren, um OpenAI zu aktivieren**, um sich mit Ihrem Profil zu verbinden. 1. Copy your Network ID. You need this ID to build checkout requests in the ChatGPT app. ## Stripe einrichten Add the Stripe API library to your back end: #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ## Kauf-Widget mit Stripe erstellen Set up the UI for your ChatGPT app by creating a “buy product” MCP tool and UI resource. This flow: - Entnimmt ein Produkt aus dem Chat-Kontext. - Zeigt Produktinformationen an und erfasst die Versandadresse von der Kundin/dem Kunden. - Ruft `window.openai.requestCheckout` auf, wenn die Kundin/der Kunde bereit ist, fortzufahren. ### Produkte und Preise erstellen This example shows a checkout flow for a product in the ChatGPT app. [Create products and prices in the Dashboard or with the Stripe CLI](https://docs.stripe.com/products-prices/manage-prices.md). > Wenn Sie Ihre eigene maßgeschneiderte Produktlogik haben, müssen Sie keine Stripe-Produkte erstellen. Ersetzen Sie stattdessen die Stripe Produkt-API-Aufrufe in den folgenden Abschnitten durch Ihre eigene Produktlogik. ### Register a “buy product” resource and tool in your MCP server Konfigurieren Sie ChatGPT so, dass Ihr Checkout-Widget gerendert wird, wenn Kundinnen und Kunden den Chat auffordern, ein bestimmtes Produkt zu kaufen. ```javascript 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"; // Follow https://docs.stripe.com/keys-best-practices to protect your Stripe API keys. const stripe = new Stripe(process.env.STRIPE_API_KEY); 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: "Start 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('{{PRODUCT_ID}}'); 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, }, }; } ); ``` ### Create the “buy product” UI with the Apps SDK This UI appears when the tool from the previous step runs. The following example uses minimal markup. In a production app, use a framework such as React. See the [ChatGPT Apps SDK documentation](https://developers.openai.com/apps-sdk) for more examples. ```html
``` ```js 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 = `

${product.name || "Loading..."}

$${(product.amount / 100).toFixed(2)}

`; }; app.ontoolresult = (params) => { const { productName, amount, priceID } = params.structuredContent ?? {}; product = { name: productName ?? "", amount: amount ?? 0, priceID: priceID ?? "" }; render(); }; render(); ``` ### Versandadresse und Steuer mit Stripe einziehen Sie können die Stripe Tax API verwenden, um Steuern für den nächsten Schritt zu berechnen. Weitere Informationen finden Sie unter [Standalone Tax API verwenden](https://docs.stripe.com/tax/standalone-tax-api.md). ### ChatGPT Instant Checkout-Modal öffnen Dadurch werden Kundinnen und Kunden aufgefordert, eine Zahlungsmethode auszuwählen. Fügen Sie Logik hinzu, um eine Checkout-Sitzung zu erstellen, der der Preis-ID aus dem vorherigen Schritt zugeordnet wird. Der folgende Codeausschnitt fügt der Preis-ID eine UUID hinzu, um eine Checkout-Sitzung-ID zu erstellen. ```javascript 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-Tool registrieren, um Bezahlvorgang abzuschließen When the customer selects a payment method in the ChatGPT payment UI and clicks **Pay**, ChatGPT calls your `complete_checkout` tool and returns the SPT that you use to create a `PaymentIntent`. Registrieren Sie ein `complete_checkout`-MCP-Tool, das ein gewährtes gemeinsames Zahlungstoken als Eingabe nimmt und zur Verarbeitung an die [Payment Intents API](https://docs.stripe.com/api/payment_intents.md) übergibt. ```javascript 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: "{{ORDER_ID}}", checkout_session_id, permalink_url: "", }, }, }; } ); ``` ## Testen Verwenden Sie den Test-Modus für Zahlungen von ChatGPT mit einer Stripe-Testumgebung, um Ihre App zu testen, ohne echtes Geld zu bewegen. 1. Geben Sie im Stripe-Dashboard eine [Sandbox](https://docs.stripe.com/sandboxes.md) ein. 1. Erstellen Sie ein Stripe-Testprofil, verbinden Sie sich mit ChatGPT in der Testumgebung und kopieren Sie Ihre Test-Netzwerk-ID. 1. Aktualisieren Sie Ihre ChatGPT-App-Einstellungen, um des Test-Modus für Zahlungen zu verwenden, sodass Testkarten erwartet und Test-SPTs generiert werden. 1. Wenn Sie einen Bezahlvorgang anfordern, geben Sie Ihre Testprofil-ID an und legen Sie `payment_mode` auf `test` fest, damit ChatGPT Testkarten erwartet und Test-SPTs generiert. ```javascript window.openai.requestCheckout({ id: priceID,payment_mode: "test", payment_provider: { provider: "stripe",merchant_id: "profile_test", supported_payment_methods: ["card"], }, ``` 1. Verwenden Sie Ihren Test-Stripe-API-Schlüssel in Ihrer MCP-Tool-Implementierung, um Test-SPTs von ChatGPT zu verarbeiten. Befolgen Sie [Best Practices](https://docs.stripe.com/keys-best-practices.md), um den Schlüssel sicher zu verwenden: Betten Sie ihn nicht direkt in Ihren Code ein und verwenden Sie einen Geheimschlüssel-Manager, wenn Ihre Plattform einen bereitstellt. 1. Richten Sie in Ihrer Live- und Testumgebung identische Webhook-Konfigurationen ein und stellen Sie sicher, dass sich Test-Webhook-Handler nicht auf Ihre Produktionssysteme auswirken können. Wenn beispielsweise Ihr Live-Webhook den Versand auslöst, sollte der Test-Endpoint nur protokollieren, dass er im Live-Modus versendet worden wäre. Nachdem Sie diese Schritte ausgeführt haben, bewerten Sie den Zahlungsablauf in Ihrer App, ohne echtes Geld zu bewegen. ### App im Live-Modus veröffentlichen Wenn Sie bereit sind, Ihre App in den Live-Modus zu versetzen: 1. Erstellen Sie einen live [eingeschränkten API-Schlüssel](https://docs.stripe.com/keys-best-practices.md#limit-access) (`rk_live_...`) mit **Payment Intents: Write**-Berechtigungen. Mit einem eingeschränkten Schlüssel können Sie Ihrem MCP-Tool genau die Berechtigungen erteilen, die es benötigt. 1. Aktualisieren Sie Ihr MCP-Tool, um den live eingeschränkten API-Schlüssel zu verwenden. 1. Aktualisieren Sie die Checkout-Anfrage Ihrer App mit Ihrer Live-Profil-ID und entfernen Sie die Testoption `payment_mode`. Your app is then ready to handle live payments. You must complete this step before submitting for ChatGPT app review. > Nachdem Sie Ihre ChatGPT-App eingereicht haben, dürfen Sie den Zahlungsmodus nicht mehr verwenden, da er für Live-Kundinnen und -Kunden sichtbar ist. ## See also - [Modellkontextprotokoll](https://modelcontextprotocol.io/) - [ChatGPT Apps SDK](https://developers.openai.com/apps-sdk)