1. Tudo já funciona separadamente…
Neste ponto, você já entende como o fluxo de commerce gira em torno do ChatGPT. O lojista tem um product feed, os endpoints ACP (/checkout_sessions e afins) estão implementados, o Instant Checkout processa o pagamento e o backend recebe webhooks e cria pedidos. Tudo isso pode funcionar até sem o seu ChatGPT App: é suficiente ter Product Feed + ACP‑backend.
Separadamente, você já sabe:
- montar o Product Feed conforme a especificação da OpenAI;
- projetar e implementar Agentic Checkout / Delegated Payment;
- escrever um ChatGPT App com widget e ferramentas MCP para busca de presentes.
Isoladamente tudo parece ótimo, mas junto é fácil virar um “zoológico de serviços”. O widget vive sua própria vida, o servidor MCP — a dele, o ACP‑backend outra, e a lógica de pedidos e webhooks — uma quarta. Na primeira tentativa de depurar uma compra real ou corrigir um bug estranho, você de repente percebe que ninguém enxerga direito o quadro geral.
O objetivo desta aula é tirar você desse estado e dar uma arquitetura coesa, porém implementável: como exatamente o Product Feed se conecta ao ACP‑backend, como ambos se relacionam com o ChatGPT App e o widget, onde entra o provedor de pagamento e como tudo isso se encapsula em componentes compreensíveis para o time: serviços, bancos de dados e APIs.
Ao mesmo tempo, vamos enfatizar constantemente: o que é um padrão rígido (SPEC) e o que é apenas nossa escolha arquitetural para o GiftGenius.
Insight: ChatGPT é o Google gratuito
O ChatGPT trabalha com usuários mais ou menos como o Google: ele traz tráfego relevante para você gratuitamente, porque ganha dinheiro com outra coisa — com os próprios usuários.
Do ponto de vista do negócio, isso significa algo simples: o ChatGPT se torna um “canal de mídia” gratuito para seus produtos, desde que você tenha conectado o Product Feed e o ACP‑backend. O modelo vai recomendar seus itens se eles atenderem bem à intenção do usuário, e você não precisa pagar separadamente por impressões ou cliques.
Daí vêm duas conclusões práticas:
- A janela de oportunidade é TEMPORARIAMENTE muito barata. Agora a concorrência no ecossistema ACP é baixa, e a entrada em segmentos de preço elevados pode ser alcançada sem os orçamentos de mídia de sempre. É uma situação rara em que tráfego com alta conversão para produtos caros (aviação, imóveis, produtos premium, seguros) pode não custar nada.
- Vale a pena começar pelas verticais mais rentáveis. Se você tem acesso a categorias com alto ticket médio, é racional conectá‑las primeiro:
- venda / locação de aviões, iates, vilas;
- venda / locação de casas e imóveis premium;
- joias, relógios caros, produtos e serviços de seguros.
Isso não garante “milhões rápidos”, mas cria uma assimetria: quem primeiro publicar um Product Feed de qualidade e um ACP‑backend confiável nos segmentos caros terá um ganho desproporcional com o canal, enquanto ele estiver subavaliado e praticamente gratuito.
2. Arquitetura de referência do GiftGenius: a grandes traços
Comecemos pela visão de alto nível. Vamos lembrar o quadro geral dos módulos anteriores: o usuário escreve no ChatGPT, o modelo chama suas ferramentas, e a camada de commerce vive em um backend separado.
Vamos definir os blocos principais do GiftGenius.
Primeiro, o UI do ChatGPT e o modelo GPT, que conversam com o usuário e, quando necessário, conectam o GiftGenius‑App (ou até funcionam sem App — apenas com Product Feed).
Segundo, o widget do GiftGenius (Next.js + Apps SDK), que mostra cards de presentes e, quando necessário, o progresso do checkout. Ele vive no sandbox do window.openai e não sabe nada sobre credenciais reais de pagamento.
Terceiro, a camada MCP, que dá ao modelo ferramentas para buscar presentes no catálogo (Product Feed) e, possivelmente, para ler o histórico de pedidos.
Quarto, o commerce / ACP‑backend, que:
- lê o Product Feed como a fonte da verdade sobre produtos e SKUs;
- implementa a Agentic Checkout Spec (/checkout_sessions, webhooks, status);
- conversa com o provedor de pagamento (por exemplo, Stripe) pelo Delegated Payment Spec.
Quinto, os bancos de dados do catálogo (se o feed é formado a partir de uma BD), de pedidos e de estruturas auxiliares (usuários, configurações).
E, por fim, o provedor de pagamento, que armazena e processa os dados de pagamento e também envia webhooks sobre os resultados dos pagamentos.
De forma esquemática, podemos desenhar assim:
graph LR U[Usuário no ChatGPT] --> GPT[Modelo GPT] GPT -->|renderiza| W[Widget GiftGenius
Next.js + Apps SDK] GPT -->|MCP tools| MCP[Servidor MCP
busca de presentes] MCP --> PF["Product Feed
(BD/JSON)"] GPT -->|ACP HTTP| ACP[GiftGenius Commerce Backend
Agentic Checkout] ACP --> ORDERS[Base de pedidos] ACP --> PSP["Provedor de pagamento
(Stripe etc.)"] PSP --> ACP ACP -->|webhooks/eventos| GPT
Este diagrama descreve a arquitetura do GiftGenius como um exemplo de implementação. O formato do Product Feed, o contrato de /checkout_sessions e o protocolo de Delegated Payment continuam sendo parte do padrão ACP; já a localização dos serviços, os esquemas de BD e a divisão em processos — é uma escolha arquitetural sua.
3. Como Product Feed, ACP e o widget se conectam logicamente
Para não nos perdermos em setas, vamos fixar uma ideia simples, porém fundamental: você tem exatamente uma única fonte da verdade sobre os produtos.
No mundo do GiftGenius, que seja a tabela products + skus no PostgreSQL. A partir dela, você:
- Forma o Product Feed conforme a especificação da OpenAI (diretamente ou por exportação).
- Cria um índice de busca para as ferramentas MCP (por exemplo, search_gifts).
- Faz a validação das requisições do ACP‑backend — verifica que o sku_id recebido realmente existe e tem preço e moeda corretos.
Dessa forma, a busca MCP e o checkout ACP olham para os mesmos dados, e o widget apenas exibe os resultados que chegam ou das ferramentas MCP, ou indiretamente do ACP (por exemplo, informações do pedido).
Você pode imaginar isso como duas “janelas” para o mesmo catálogo: uma janela — para busca e recomendações, outra — para a finalização da compra. Se essas janelas olham para bancos diferentes, você está a um passo de uma vida divertida com desencontros.
4. Modelando dados: do Product Feed ao pedido
Comecemos com tipos simples de TypeScript, que viverão no seu repositório do GiftGenius (por exemplo, em src/domain/commerce.ts). Esses tipos não são uma cópia literal das especificações, mas refletem suas ideias principais em uma forma conveniente para o app.
// src/domain/commerce.ts
export interface ProductSku {
id: string; // ID de SKU estável (igual ao Product Feed)
title: string; // título legível
priceCents: number; // preço em centavos
currency: string; // código ISO, por exemplo "usd"
}
export type CheckoutStatus = "pending" | "succeeded" | "failed";
export interface CheckoutSession {
id: string;
skuId: string;
totalCents: number;
currency: string;
status: CheckoutStatus;
}
Aqui trazemos explicitamente para a CheckoutSession a referência ao skuId e a moeda/quantia fixas. Este é nosso modelo interno; a Agentic Checkout Spec real é mais rica, mas a ideia básica é a mesma: a sessão é “quanto, por quê e em qual status”.
Em seguida, precisamos do tipo de pedido:
export interface Order {
id: string;
userId: string;
skuId: string;
totalCents: number;
currency: string;
checkoutSessionId: string;
status: "awaiting_payment" | "paid" | "canceled" | "refunded";
}
Percebe-se aqui a influência das entidades gerais do módulo anterior: intent, checkout_session, order. No nosso projeto didático, comprimimos um pouco intent e order para não multiplicar entidades, mas mantemos o vínculo com checkoutSessionId.
5. Como o widget do GiftGenius “enxerga” o mundo de commerce
Ponto importante: o widget por si só não chama a solução de pagamento e nem precisa saber detalhes do ACP; seu papel é mostrar ao usuário o estado que foi calculado e consolidado nos backends.
O cenário útil mais simples: após uma compra bem-sucedida, o usuário pode voltar ao chat e perguntar “Mostre meus últimos pedidos no GiftGenius”. O GPT chamará uma ferramenta MCP como get_user_orders, que vai ao seu backend, e o widget exibirá a lista.
Imagine uma rota de API do Next.js que retorna os últimos pedidos (simplificado):
// app/api/orders/recent/route.ts
import { NextRequest, NextResponse } from "next/server";
import { getRecentOrdersForUser } from "@/lib/orders";
export async function GET(req: NextRequest) {
const userId = req.headers.get("x-giftgenius-user-id")!;
const orders = await getRecentOrdersForUser(userId);
return NextResponse.json({ orders });
}
A função getRecentOrdersForUser já vive na sua camada de commerce, trabalha com a BD e conhece a estrutura dos pedidos. O widget, por sua vez, pode chamar essa rota via window.fetch (como fizemos nos módulos anteriores) e exibir os cards de compras.
A combinação “ferramenta MCP → sua API → BD de pedidos → widget” dá ao usuário a sensação de que o App tem “memória” das compras, embora o widget apenas exiba o estado do backend.
6. Implementação simples de um endpoint ACP no estilo Next.js
Agora vamos esboçar como pode ser a implementação didática de um dos endpoints ACP principais — a criação de checkout_session. Pela especificação, o contrato é rico, mas para o curso podemos manter a essência: chega um skuId, validamos pelo feed/BD, criamos a sessão e retornamos seu ID e o valor.
Suponha que temos a rota POST /api/checkout-sessions:
// app/api/checkout-sessions/route.ts
import { NextRequest, NextResponse } from "next/server";
import { findSkuById, createCheckoutSession } from "@/lib/checkout";
export async function POST(req: NextRequest) {
const body = await req.json(); // { skuId: string }
const sku = await findSkuById(body.skuId);
if (!sku) {
return NextResponse.json(
{ error: "SKU not found" },
{ status: 400 },
);
}
const session = await createCheckoutSession(sku);
return NextResponse.json({ session });
}
Há alguns pontos importantes aqui.
Primeiro, é aqui que a camada de commerce confere com o Product Feed/BD: findSkuById precisa olhar para a mesma fonte da qual o feed é formado. Não confiamos em nada que veio “do ar” — nem do GPT, nem do widget.
Segundo, retornamos apenas o que o cliente ChatGPT/ACP precisa: o ID da sessão, o valor, a moeda e o status (por padrão pending ou not_ready_for_payment, dependendo da terminologia escolhida). No ACP real há mais campos, incluindo informações sobre métodos de pagamento disponíveis e fulfillment, mas o exemplo didático foca na criação inicial da sessão.
Terceiro, é conveniente cobrir uma rota dessas com testes de contrato: se amanhã a estrutura do Product Feed mudar, os testes de findSkuById e createCheckoutSession devem capturar isso antes de o ChatGPT começar a mostrar erros estranhos aos usuários.
7. Vínculo entre as sessões ACP e o provedor de pagamento
Até agora não tocamos no provedor de pagamento. Em uma integração real, acontece mais ou menos o seguinte (cenário simplificado).
Primeiro, o ChatGPT (via ACP) chama seu POST /checkout_sessions. Seu backend cria uma sessão local na sua BD. Quando o usuário confirma o pagamento no UI do Instant Checkout, a plataforma solicita ao PSP um token de pagamento delegado (Shared Payment Token) para um merchant e valor específicos. Esse token chega a você na requisição complete (ou chamada análoga pelo Delegated Payment Spec).
Depois disso, você cria o pagamento no PSP usando o token, sem acesso aos dados reais de pagamento. O PSP envia um webhook com o resultado; você atualiza o status do pedido e/ou da checkout‑session.
No nosso código didático, podemos nos limitar a imitar essa etapa. Por exemplo, a função completeCheckoutSession pode ser assim:
// src/lib/checkout.ts
export async function completeCheckoutSession(sessionId: string, spt: string) {
// Aqui, na prática, chamamos a API do PSP com o token delegado (SPT)
const paymentOk = await mockChargeWithToken(spt);
return paymentOk
? { status: "succeeded" as const }
: { status: "failed" as const };
}
A chamada ao PSP e o uso do Shared Payment Token fazem parte do padrão de Delegated Payment, enquanto a função mockChargeWithToken é nossa camada arquitetural didática que imita essa particularidade.
8. Fluxo ponta a ponta do GiftGenius: do pedido até o presente pago
Agora vamos juntar tudo em uma sequência de passos. Esta é a história “de produção” do GiftGenius, pela qual combinamos todas as camadas. É importante não misturar dois mundos diferentes, então vamos analisá‑los separadamente.
Esquema A: sem App, apenas Product Feed + ACP
Neste cenário você tem o Product Feed e o ACP‑backend, mas não tem ChatGPT App nem widget. É o merchant clássico de Instant Checkout.
O usuário escreve no ChatGPT algo como: “Encontre um presente digital de até $50”. O GPT usa seu Product Feed para encontrar SKUs adequados e os mostra no UI nativo dele como cards de compra. Aqui não há nenhum código React seu — os cards são totalmente renderizados pelo ChatGPT.
O usuário clica no botão “Buy” em um desses cards. Esse clique é processado pelo próprio ChatGPT. A plataforma:
- Forma line_items com base no Product Feed.
- Chama seu POST /checkout_sessions conforme a Agentic Checkout Spec.
- Mostra ao usuário o UI do Instant Checkout (método de pagamento, endereço etc.).
- Após a confirmação, obtém o Shared Payment Token do PSP e chama seu .../complete.
- Recebe de você o estado final da checkout_session e, se necessário, aguarda o webhook do pedido.
Do ponto de vista do seu código, aqui funcionam apenas os endpoints ACP e o Product Feed. Não existe Apps SDK, window.openai nem widget. E este é um cenário absolutamente válido, “puro”, de um merchant ACP.
Esquema B: com ChatGPT App e o widget do GiftGenius
Agora adicionamos o ChatGPT App e o widget do GiftGenius por cima. O Product Feed e o ACP‑backend continuam lá: eles seguem fornecendo a busca e o pagamento. A diferença é que agora temos um UI próprio e a lógica de passos dentro do App.
Imagine o diálogo: o usuário escreve no ChatGPT: “Encontre um presente para minha mãe de até $50”. O GPT entende que é uma intenção de commerce e propõe usar o GiftGenius‑App. O widget faz algumas perguntas de esclarecimento: idade, interesses, país. Em seguida, o GPT chama sua ferramenta MCP search_gifts com filtros, e o servidor MCP consulta o catálogo (BD ou índice preparado), encontra alguns SKUs adequados e os retorna de forma estruturada.
O GPT passa esses dados ao widget, e o widget exibe seus cards de presentes (componentes React, carrosséis etc.). Este já é seu design e seu UX, e não o UI de shopping padrão do ChatGPT.
Quando o usuário clica no botão “Comprar” no widget, acontece algo diferente do esquema A. Esse clique é processado pelo widget:
- O widget entende qual SKU o usuário escolheu.
- Pelo seu próprio API (por exemplo, POST /api/checkout-sessions) chama seu backend para criar a checkout_session (ou obter o ID de uma sessão já preparada).
- Em seguida, o widget chama um método de runtime do Apps SDK, algo como:
// Consulte a assinatura atual do método na documentação do Apps SDK await window.openai.requestCheckout({ checkoutSessionId: session.id, ... });Essa chamada é uma iniciativa do widget. Para o ChatGPT é o sinal: “Hora de abrir o Instant Checkout para esta checkout_session”.
Depois, a plataforma do ChatGPT trabalha de forma muito parecida com o esquema A, mas nos bastidores:
- exibe ao usuário o UI nativo do Instant Checkout;
- obtém o Shared Payment Token no PSP;
- chama seu endpoint ACP de conclusão da sessão (.../complete);
- participa do recebimento e processamento dos webhooks do seu backend.
Ou seja, no esquema B o widget inicia o checkout via Apps SDK, e as chamadas ao ACP (criação/conclusão da checkout_session) acontecem ou antes disso (quando você mesmo cria a sessão no backend), ou já depois do requestCheckout, mas sempre no lado do servidor.
Enquanto isso, o widget pode exibir em paralelo as etapas de “Finalização da compra”, status e o preview do pedido, baseando‑se na sua API (/api/orders/...) e nas ferramentas MCP.
Se representarmos o esquema B em um diagrama, teremos algo como:
sequenceDiagram
participant User as Usuário
participant GPT as ChatGPT / GPT
participant W as Widget GiftGenius
participant MCP as Servidor MCP
participant ACP as Commerce Backend
participant PSP as Provedor de pagamento
User->>GPT: "Encontre um presente de até $50"
GPT->>MCP: search_gifts(...)
MCP-->>GPT: lista de SKUs
GPT->>W: dados para renderização dos cards
User->>W: clique em "Comprar"
W->>ACP: POST /api/checkout-sessions (skuId)
ACP-->>W: checkout_session (id, valor, moeda)
W->>GPT: window.openai.requestCheckout({ checkoutSessionId })
GPT->>User: UI do Instant Checkout
User->>GPT: confirmação do pagamento
GPT->>PSP: solicitação do Shared Payment Token
PSP-->>GPT: SPT
GPT->>ACP: complete(sessionId, SPT)
ACP->>PSP: charge(SPT)
PSP-->>ACP: resultado do pagamento
ACP->>GPT: status do pedido
GPT->>User: mensagem de sucesso/fracasso do pagamento
Diferença-chave em relação ao esquema A:
- No A, os cards e o botão “Buy” são renderizados pelo próprio ChatGPT, e é ele que inicia a chamada ao ACP diretamente.
- No B, os cards e o botão “Comprar” são renderizados pelo seu widget, e é ele que chama window.openai.requestCheckout(...). Só então o ChatGPT, nos bastidores, conversa com seu ACP‑backend e com o PSP.
Insight
A equipe do ChatGPT escreveu no SDK que em breve haverá monetização nos apps. E é isso mesmo. Já há vários métodos ainda não anunciados disponíveis para widgets. E o mais interessante deles é o requestCheckout().
Uma chamada típica fica assim:
window.openai.requestCheckout({
id: "checkout_session_123",
payment_provider: {
merchant_id: "stripe",
supported_payment_methods: ["card"]
},
...
}
Ele exibe uma janela de diálogo que permite ao usuário concluir o pagamento. Então, projete seu aplicativo como se a monetização já estivesse ativada: quando você terminar o trabalho, é assim que vai funcionar.
9. Mini-implementação para o curso: backend monolítico
Nos módulos sobre arquitetura, já surgiu a questão: fazer tudo em um único serviço ou dividir logo em servidor MCP, commerce‑backend e um serviço separado para a integração de pagamentos. Para fins educacionais, na maioria das vezes basta “quase um monólito”: um repositório, um deploy, mas com a lógica bem separada por camadas.
A versão didática do GiftGenius pode ser assim: um app Next.js, no qual:
- o widget vive em app/widget/page.tsx;
- os endpoints ACP — em app/api/checkout-sessions e rotas vizinhas;
- as ferramentas MCP — em app/api/mcp/route.ts ou em uma pasta separada;
- o trabalho com pedidos — em src/lib/orders.ts, src/lib/checkout.ts e módulos próximos.
Fisicamente, é um único servidor (especialmente em dev/staging), mas logicamente você já pensa em termos de três papéis: UI (widget), MCP (ferramentas/recursos para o GPT) e ACP (commerce‑backend).
Mais tarde, nos módulos sobre produção, você verá como esse “monólito” é separado em vários serviços e ambientes, e diante deles aparece um MCP Gateway. Mas no nível do módulo 14, esse “monólito com camadas corretas” já fornece uma arquitetura bem plausível.
10. Tarefa prática: sua arquitetura em torno do ACP
Para que tudo o que foi descrito acima não fique só na teoria, faz sentido aplicar isso ao seu domínio agora. Dentro da aula, dá para fazer dois mini‑exercícios.
Primeiro, escolha seu próprio cenário: assinatura SaaS, reserva, delivery, cursos online — qualquer caso em que haja produto/serviço, preço e um checkout razoável. Lembre do modelo por fases: discovery → decision → checkout → pós‑pagamento.
Segundo, baseando‑se na arquitetura do GiftGenius, descreva livremente: como você vai construir o Product Feed (onde vivem os SKUs e preços, quem os atualiza), onde vai implementar o contrato ACP (serviço separado ou parte do backend existente), como vai conectar o provedor de pagamento e como seu widget (se existir) vai interagir com tudo isso via MCP e Apps SDK.
É útil declarar explicitamente se seu projeto vai usar apenas o esquema A (Instant Checkout sem App), apenas o esquema B (App + widget) ou ambos os cenários. Mesmo um rascunho textual da arquitetura reduz muito o risco de surpresas na fase de integração real.
11. Erros comuns ao integrar Product Feed, ACP e widget
Erro nº 1: dois catálogos diferentes — um para busca, outro para o checkout.
Às vezes o time primeiro levanta um feed “rápido” de busca para o GPT (por exemplo, um pequeno JSON) e depois cria separadamente a BD de commerce para pedidos. Se eles não forem vinculados por IDs comuns e lógica de atualização comum, o GPT pode oferecer ao usuário produtos que já não podem ser comprados, ou por preço antigo. A abordagem correta — uma única fonte da verdade, a partir da qual são formados tanto o Product Feed quanto as tabelas internas para os endpoints ACP.
Erro nº 2: confiar nos dados vindos do GPT ou do widget.
Quando chegam checkout_session com skuId e preço, é tentador confiar nesses valores: “ora, o GPT não vai mentir”. Mas o modelo pode “criar” ou confundir um SKU, e o usuário pode tentar adulterar a requisição. Se não conferir os dados de entrada com o Product Feed/BD, você corre o risco de vender o item errado e pelo preço errado. Qualquer endpoint ACP deve começar pela validação no armazenamento primário do catálogo.
Erro nº 3: misturar os papéis do widget e do commerce‑backend.
Às vezes os desenvolvedores, por hábito, chamam diretamente o SDK de pagamento do front-end, criam sessões no Stripe e funcionam como em um site comum. No contexto de ChatGPT Apps, isso quebra o modelo de segurança e contradiz o ACP: o fluxo de pagamento deve passar pelo ChatGPT e pelo seu commerce‑backend, e o widget — apenas exibir estado e enviar eventos (como requestCheckout). Se o widget sabe demais sobre o contorno de pagamento, você ganha complexidade e riscos elevados.
Erro nº 4: simplificação excessiva do contrato ACP.
No exemplo didático, deixamos propositalmente apenas o skuId, o valor e o status para não afundar nos detalhes. O problema começa quando esse “contrato de demo” escorrega para a produção. Você percebe de repente que faltam campos para endereço, impostos, métodos de entrega, cupons, e começa a “acoplar” isso caoticamente. É melhor projetar os modelos internos já com folga para cenários reais, mesmo que parte dos campos fique sem uso no começo.
Erro nº 5: ausência de vínculo entre pedidos e usuários.
No demo é fácil se limitar a orderId e skuId, sem pensar em como o usuário vai voltar em uma semana e perguntar: “Mostre minhas compras”. Se desde o início você não incluir userId (ou outro identificador estável) no pedido e na checkout‑session, depois terá que fazer migrações e criar pontes complexas. A arquitetura de commerce em torno do ChatGPT quase sempre pressupõe que o GPT poderá vincular a conversa atual ao histórico de pedidos do usuário — vale considerar isso com antecedência.
Erro nº 6: subestimar a importância de webhooks e idempotência.
Nesta aula só falamos de webhooks; você vai se aprofundar nos próximos módulos. É fácil pensar: “o webhook vai chegar uma vez, atualizamos o pedido — e pronto”. Na prática, os provedores de pagamento gostam de retentar eventos, e a rede — de perder respostas. Se você não projetar pedidos e checkout‑sessions como estruturas idempotentes (por checkoutSessionId ou paymentId), pode ter cobranças duplicadas, pedidos em duplicidade e divergências sutis entre o PSP e sua BD.
Erro nº 7: ignorar restrições e políticas no Product Feed.
Na corrida por um feed de demo rápido é fácil esquecer restrições etárias, disponibilidade por país, categorias proibidas e outras “miudezas”. Depois, o GPT passa a oferecer ao usuário um produto que não pode ser vendido para o país ou idade dele. Campos relacionados a política e restrições precisam ser projetados e preenchidos desde o início, mesmo que você esteja vendendo apenas presentes digitais inofensivos por enquanto.
GO TO FULL VERSION