Visão geral
Cabe aos desenvolvedores decidir como monetizar seus plugins. Hoje, a abordagem recomendada e com disponibilidade geral é usar o checkout externo, em que os usuários concluem a compra no domínio do desenvolvedor. Atualmente, só aprovamos plugins para a compra de produtos físicos, mas estamos trabalhando para oferecer suporte a outras formas de comércio.
Também estamos disponibilizando o checkout integrado com o painel de pagamento do ChatGPT para alguns marketplaces parceiros (versão beta). Planejamos ampliar o acesso a outros marketplaces e varejistas de produtos físicos ao longo do tempo. Até lá, recomendamos direcionar os usuários ao seu checkout externo habitual para concluir a compra.
Abordagem recomendada de monetização
✅ Checkout externo (recomendado)
O checkout externo direciona os usuários do ChatGPT para um fluxo de checkout hospedado pelo lojista no seu próprio site ou aplicativo. Nele, você define os preços, processa os pagamentos e cuida do envio e da entrega dos produtos físicos elegíveis.
Essa é a abordagem recomendada para a maioria dos desenvolvedores de plugins.
Como funciona
- O usuário interage com a interface do seu plugin no ChatGPT.
- A interface do plugin apresenta os produtos físicos elegíveis, por exemplo, com a ação “Comprar agora”.
- Quando o usuário decide comprar, a interface do plugin oferece um link para sair do ChatGPT e acessar o checkout externo ou redireciona o usuário para lá.
- Você cuida dos pagamentos, do faturamento, dos impostos, dos reembolsos e da conformidade inteiramente no seu domínio.
- Após a compra, o usuário pode voltar ao ChatGPT com a confirmação do pedido ou os dados de rastreamento.
Checkout com formas de pagamento salvas
Os desenvolvedores de plugins podem implementar um fluxo de checkout na interface opcional para que os clientes usem formas de pagamento já salvas com o lojista. Esse fluxo só pode exibir formas de pagamento salvas e não pode coletar credenciais de novas formas de pagamento dos clientes.
Com essa abordagem, o cliente pode concluir a compra sem sair do ChatGPT.
Como funciona
- O usuário interage com a interface do seu plugin no ChatGPT.
- A interface do plugin apresenta os produtos físicos elegíveis e os totais correspondentes.
- A interface do plugin exibe as formas de pagamento elegíveis que o cliente já salvou com você.
- O cliente seleciona uma forma de pagamento salva e confirma a compra no ChatGPT.
- Seu servidor processa a compra com a forma de pagamento salva e retorna a confirmação ao plugin.
Checkout com o painel de pagamento do ChatGPT (beta privado)
No momento, o checkout com o painel de pagamento do ChatGPT está restrito a alguns marketplaces e não está disponível para todos os usuários.
Para coletar dados de novas formas de pagamento durante o checkout, os desenvolvedores de plugins precisam usar o painel de pagamento do ChatGPT. Chame requestCheckout com os dados da sessão de checkout (itens do pedido, totais e formas de pagamento salvas) para abrir o painel. Quando o usuário seleciona a opção de compra, o ChatGPT envia ao seu servidor MCP um token que representa a forma de pagamento selecionada. O envio ocorre por meio de uma chamada à ferramenta complete_checkout. Use sua integração com o provedor de serviços de pagamento (PSP) para efetuar a cobrança com esse token. Em seguida, retorne os dados do pedido concluído na resposta de complete_checkout.
Resumo do fluxo
- O servidor prepara a sessão. Uma ferramenta MCP retorna os dados da sessão de checkout (ID da sessão, itens do pedido, totais e provedor de pagamento) em
structuredContent. - O widget exibe o carrinho. O widget mostra os itens e os totais para que o usuário possa conferir e confirmar a compra.
- O widget chama
requestCheckout. O widget executarequestCheckout(session_data). O ChatGPT abre o painel de pagamento e exibe o valor a cobrar e as opções de pagamento. - O servidor conclui o pedido. Quando o usuário clica no botão de pagamento, o widget faz uma nova chamada ao seu servidor MCP por meio da ferramenta
complete_checkout. A ferramenta MCP retorna o pedido concluído, que o widget recebe como resposta arequestCheckout.
Sessão de checkout
Você é responsável por montar o payload da sessão de checkout que o host vai renderizar. Os valores exatos de alguns campos, como id e payment_provider, dependem do seu provedor de serviços de pagamento e do seu sistema de comércio. Na prática, sua ferramenta MCP deve retornar os seguintes dados:
- Os itens que o usuário está comprando e suas quantidades.
- Os totais (subtotal, impostos, descontos, taxas e total) de acordo com os cálculos do seu servidor.
- Os metadados do provedor exigidos pela integração com seu PSP.
- Links para documentos legais e políticas (termos de uso, política de reembolso etc.).
Como chamar requestCheckout no widget
O host disponibiliza window.openai.requestCheckout. Use essa função para abrir o painel de pagamento do ChatGPT quando o usuário iniciar uma compra.
Exemplo:
async function handleCheckout(sessionJson: string) {
const session = JSON.parse(sessionJson);
if (!window.openai?.requestCheckout) {
throw new Error("requestCheckout is not available in this host");
}
// Host opens the ChatGPT payment sheet.
const order = await window.openai.requestCheckout({
...session,
id: String(session.id), // Use a unique ID for every checkout session.
});
return order; // Host returns the order payload.
}No seu componente, você pode iniciar o checkout quando o usuário clicar em um botão:
import { useState } from "react";
function CheckoutButton({
checkoutSessionJson,
}: {
checkoutSessionJson: string;
}) {
const [isLoading, setIsLoading] = useState(false);
const [order, setOrder] = useState<Record<string, unknown> | null>(null);
const checkoutButton = (
<button
onClick={async () => {
setIsLoading(true);
try {
const orderResponse = await handleCheckout(checkoutSessionJson);
setOrder(orderResponse);
} catch (error) {
console.error(error);
} finally {
setIsLoading(false);
}
}}
>
{isLoading ? "Loading..." : "Checkout"}
</button>
);
return (
<>
{checkoutButton}
<pre>{JSON.stringify(order, null, 2)}</pre>
</>
);
}O exemplo a seguir mostra uma sessão de checkout completa que o widget pode enviar ao host. Seu plugin fornece os campos da sessão de checkout mostrados abaixo. O ChatGPT acrescenta os campos que ficam a cargo do host, como merchant, logo_url, conversation_id, connector_id e ecosystem_app_uri. Preencha o campo merchant_id com o valor indicado pelo seu PSP.
const checkoutRequest = {
id: "checkout_session_123",
payment_provider: {
provider: "stripe",
merchant_id: "merchant_123",
supported_payment_methods: [
{
type: "card",
allowed_card_brands: ["visa", "mastercard"],
},
{ type: "apple_pay" },
{ type: "google_pay" },
],
managed_payment_methods: [
{
type: "card",
id: "pm_123",
display_name: "Visa ending in 4242",
display_last4: "4242",
display_brand: "visa",
},
],
},
payment_mode: "live",
status: "ready_for_payment",
currency: "USD",
metadata: {
cart_id: "cart_123",
merchant_order_reference: "order_ref_123",
},
line_items: [
{
id: "line_item_123",
item: {
id: "item_123",
quantity: 1,
},
name: "Canvas backpack",
description: "A weather-resistant everyday backpack.",
images: ["https://merchant.example.com/images/canvas-backpack.png"],
base_amount: 3000,
discount: 0,
subtotal: 3000,
tax: 300,
total: 3300,
},
],
totals: [
{
type: "items_base_amount",
display_text: "Items subtotal",
amount: 3000,
},
{
type: "subtotal",
display_text: "Subtotal",
amount: 3000,
},
{
type: "fulfillment",
display_text: "Shipping",
amount: 550,
},
{
type: "tax",
display_text: "Tax",
amount: 300,
},
{
type: "total",
display_text: "Total",
amount: 3850,
},
],
fulfillment_options: [
{
id: "standard_shipping",
type: "shipping",
title: "Standard shipping",
subtitle: "Arrives in 3-5 business days",
carrier: "USPS",
earliest_delivery_time: "2027-01-15T15:00:00Z",
latest_delivery_time: "2027-01-19T18:00:00Z",
subtotal: 500,
tax: 50,
total: 550,
},
],
fulfillment_option_id: "standard_shipping",
fulfillment_address: {
name: "Jane Customer",
line_one: "123 Main St",
line_two: "Apt 4B",
city: "San Francisco",
state: "CA",
country: "US",
postal_code: "94107",
phone_number: "+14155550123",
},
messages: [
{
type: "info",
param: "fulfillment_address",
content_type: "plain",
content: "Free returns within 30 days.",
},
],
links: [
{ type: "terms_of_use", url: "https://merchant.example.com/terms" },
{ type: "privacy_policy", url: "https://merchant.example.com/privacy" },
{ type: "support_url", url: "https://merchant.example.com/support" },
],
};
const response = await window.openai.requestCheckout(checkoutRequest);Pontos importantes:
window.openai.requestCheckout(session)abre a interface de checkout do host.- A promise é resolvida com o resultado do pedido ou rejeitada em caso de erro ou cancelamento.
- Exiba os dados do JSON da sessão para que os usuários possam conferir pelo que estão pagando.
- Em todos os campos de valor, use números inteiros na menor unidade da moeda.
- Use
payment_provider.managed_payment_methodspara as formas de pagamento que o cliente já salvou com o lojista. - Mantenha os valores de
metadatacomo strings. - Em
provider, use o slug do PSP exigido pela integração. Consulte seu PSP para obter o valor demerchant_id.
Como disponibilizar a ferramenta complete_checkout no servidor MCP
Você pode seguir este exemplo e adaptá-lo à sua lógica.
Instale fastmcp e pydantic para executar este exemplo em Python. O atributo output_schema da ferramenta declara o outputSchema do MCP. ToolResult.structured_content fornece o valor de structuredContent e meta fornece o valor de _meta. A fixture de teste local aceita example-session e example-payment-token e retorna uma resposta de exemplo sem efetuar cobrança nem criar um pedido.
from typing import Any, Literal
from fastmcp import FastMCP
from fastmcp.tools.tool import ToolResult
from pydantic import BaseModel
server = FastMCP("Checkout response fixture")
META_SESSION_ID = "openai/checkoutSessionId"
class Buyer(BaseModel):
email: str
class PaymentData(BaseModel):
# Deliberately accepts only a local fixture token, never real payment credentials.
token: Literal["example-payment-token"]
class CompleteCheckoutOutput(BaseModel):
id: str
status: str
currency: str
line_items: list[dict[str, Any]]
fulfillment_address: dict[str, Any]
fulfillment_options: list[dict[str, Any]]
fulfillment_option_id: str
totals: list[dict[str, Any]]
order: dict[str, Any]
@server.tool(
description="Return the local checkout response fixture; does not charge a payment method or create a real order.",
output_schema=CompleteCheckoutOutput.model_json_schema(),
)
async def complete_checkout(
checkout_session_id: str,
buyer: Buyer,
payment_data: PaymentData,
) -> ToolResult:
if checkout_session_id != "example-session":
raise ValueError("This response fixture only accepts example-session")
return ToolResult(
content=[],
structured_content={
"id": checkout_session_id,
"status": "completed",
"currency": "USD",
"line_items": [
{
"id": "line_item_1",
"item": {
"id": "item_1",
"quantity": 1,
},
"base_amount": 3000,
"discount": 0,
"subtotal": 3000,
"tax": 300,
"total": 3300,
},
],
"fulfillment_address": {
"name": "Jane Customer",
"line_one": "123 Main St",
"line_two": "Apt 4B",
"city": "San Francisco",
"state": "CA",
"country": "US",
"postal_code": "94107",
"phone_number": "+1 (555) 555-5555",
},
"fulfillment_options": [
{
"id": "fulfillment_option_1",
"type": "shipping",
"title": "Standard shipping",
"subtitle": "3-5 business days",
"carrier": "USPS",
"earliest_delivery_time": "2026-02-24T15:00:00Z",
"latest_delivery_time": "2026-02-28T18:00:00Z",
"subtotal": 0,
"tax": 0,
"total": 0,
},
],
"fulfillment_option_id": "fulfillment_option_1",
"totals": [
{
"type": "items_base_amount",
"display_text": "Items subtotal",
"amount": 3000,
},
{
"type": "subtotal",
"display_text": "Subtotal",
"amount": 3000,
},
{
"type": "tax",
"display_text": "Tax",
"amount": 300,
},
{
"type": "total",
"display_text": "Total",
"amount": 3300,
},
],
"order": {
"id": "order_id_123",
"checkout_session_id": checkout_session_id,
"permalink_url": "",
},
},
meta={META_SESSION_ID: "checkout-flow"},
is_error=False,
)Adapte o exemplo para executar estas ações:
- Integrar a ferramenta ao seu provedor de serviços de pagamento para efetuar a cobrança com a forma de pagamento indicada em
payment_data. - Salvar o pedido no seu sistema.
- Retornar os dados oficiais do pedido e do comprovante.
- Incluir
_meta.ui.resourceUrise quiser renderizar um widget de confirmação (o ChatGPT aceita_meta["openai/outputTemplate"]como alias opcional para fins de compatibilidade).
Os seguintes provedores de serviços de pagamento processam transações feitas pelo painel de pagamento do ChatGPT:
- Adyen
- Checkout.com
- Fiserv
- PayPal
- Stripe
- Worldpay
Como receber os dados brutos das formas de pagamento (opcional)
Se você é lojista e tem certificação PCI DSS de nível 1, pode receber diretamente os dados brutos das formas de pagamento ao implementar o endpoint Delegate Payment do Agentic Commerce Protocol. A solicitação de pagamento delegado inclui todos os dados da forma de pagamento exigidos pelo seu fluxo, como o número completo do cartão, a data de validade, o CVC, o endereço de cobrança, os limites da autorização, os sinais de risco e os metadados.
Veja um exemplo de solicitação com os dados brutos de um cartão:
{
"payment_method": {
"type": "card",
"card_number_type": "fpan",
"number": "4242424242424242",
"exp_month": "11",
"exp_year": "2026",
"name": "Jane Doe",
"cvc": "223",
"checks_performed": ["avs", "cvv"],
"iin": "424242",
"display_card_funding_type": "credit",
"display_brand": "visa",
"display_last4": "4242",
"metadata": {}
},
"allowance": {
"reason": "one_time",
"max_amount": 5000,
"currency": "usd",
"checkout_session_id": "cs_01HV3P3ABC123",
"merchant_id": "acme_corp",
"expires_at": "2026-02-13T12:00:00Z"
},
"billing_address": {
"name": "Jane Doe",
"line_one": "185 Berry Street",
"line_two": "Suite 550",
"city": "San Francisco",
"state": "CA",
"country": "US",
"postal_code": "94107"
},
"risk_signals": [
{
"type": "card_testing",
"score": 5,
"action": "authorized"
}
],
"metadata": {
"session_id": "sess_abc123",
"user_agent": "ChatGPT/2.0"
}
}
A resposta deve conter o ID da forma de pagamento. Esse ID será enviado a complete_checkout como parte de payment_data.
{
"id": "vt_01J8Z3WXYZ9ABC123",
"created": "2026-02-12T14:30:00Z",
"metadata": {
"source": "agent_checkout",
"merchant_id": "acme_corp",
"idempotency_key": "idem_xyz789"
}
}
Tratamento de erros
A chamada à ferramenta complete_checkout pode retornar mensagens do tipo error. O painel de pagamento do ChatGPT exibe as mensagens de erro cujo code seja payment_declined ou requires_3ds. O widget recebe todas as outras mensagens de erro como resposta a requestCheckout e pode exibi-las como preferir.
Modo de teste de pagamentos
Você pode definir o campo payment_mode como test na chamada a requestCheckout. Isso abre o painel de pagamento do ChatGPT em um modo que aceita cartões de teste, como o cartão de teste 4242. Você pode processar o token resultante no ambiente de homologação do seu PSP. Esse token é enviado em payment_data à ferramenta complete_checkout. Assim, você pode testar o fluxo de ponta a ponta sem movimentar dinheiro real.
No modo de teste de pagamentos, talvez seja necessário usar outro valor para merchant_id. Consulte o guia de monetização do seu provedor de pagamento para saber mais.
Lista de verificação da implementação
- Defina o modelo da sessão de checkout. Inclua os IDs, o objeto do provedor de pagamento, os itens do pedido, os totais e os links para documentos legais.
- Retorne a sessão na resposta da sua ferramenta MCP em
structuredContent, junto com o template do widget. - Renderize a sessão no widget para que os usuários possam conferir os itens, os totais e os termos.
- Chame
requestCheckout(session_data)quando o usuário iniciar a compra. Trate tanto o pedido retornado quanto eventuais erros. - Efetue a cobrança do usuário implementando a ferramenta MCP
complete_checkout, que deve retornar uma resposta de acordo com a especificação de checkout. - Teste o fluxo de ponta a ponta com valores, impostos e descontos realistas para verificar se o host exibe os totais esperados.