Descripción general
Cada desarrollador decide cómo monetizar su complemento. Actualmente, la opción recomendada y disponible de forma general es el pago externo, que permite a los usuarios completar la compra en el dominio del desarrollador. Por ahora, solo aprobamos complementos para la compra de productos físicos, aunque estamos trabajando para admitir más casos de uso en el comercio.
También estamos habilitando el pago integrado con el panel de pago de ChatGPT para algunas plataformas de comercio electrónico asociadas (beta). Con el tiempo, planeamos ampliar el acceso a más plataformas y comercios minoristas que venden productos físicos. Mientras tanto, te recomendamos dirigir a los usuarios a tu proceso habitual de pago externo para que completen sus compras.
Opción de monetización recomendada
✅ Pago externo (recomendado)
El pago externo consiste en dirigir a los usuarios desde ChatGPT a un proceso de pago alojado por el comercio en tu propio sitio web o aplicación. Allí te encargas de los precios, los pagos, los envíos y la preparación y entrega de los pedidos de productos físicos que cumplen los requisitos.
Esta es la opción recomendada para la mayoría de los desarrolladores de complementos.
Cómo funciona
- El usuario interactúa con la interfaz de tu complemento en ChatGPT.
- La interfaz de tu complemento muestra los productos físicos que cumplen los requisitos (por ejemplo, con la opción “Comprar ahora”).
- Cuando el usuario decide comprar, la interfaz de tu complemento le ofrece un enlace a tu proceso de pago externo o lo redirige allí para que continúe fuera de ChatGPT.
- En tu dominio te encargas por completo del pago, la facturación, los impuestos, los reembolsos y el cumplimiento normativo.
- Después de la compra, el usuario puede volver a ChatGPT con la confirmación del pedido o los datos de seguimiento.
Pago con métodos de pago guardados
Los desarrolladores de complementos pueden implementar en la interfaz opcional un proceso de pago que permita a los clientes usar los métodos de pago que ya guardaron en el comercio. Este proceso solo puede mostrar métodos de pago guardados y no puede recopilar credenciales de nuevos métodos de pago de los clientes.
Con esta opción, el cliente puede completar la compra sin salir de ChatGPT.
Cómo funciona
- El usuario interactúa con la interfaz de tu complemento en ChatGPT.
- La interfaz de tu complemento muestra los productos físicos que cumplen los requisitos junto con los totales correspondientes.
- La interfaz de tu complemento muestra los métodos de pago admitidos que el cliente ya guardó en tu comercio.
- El cliente selecciona un método de pago guardado y confirma la compra en ChatGPT.
- Tu servidor procesa la compra con el método de pago guardado y devuelve la confirmación al complemento.
Pago con el panel de pago de ChatGPT (beta privada)
Por ahora, el pago con el panel de pago de ChatGPT se limita a algunas plataformas de comercio electrónico y no está disponible para todos los usuarios.
Para recopilar datos de nuevos métodos de pago durante el proceso de compra, los desarrolladores de complementos deben usar el panel de pago de ChatGPT. Llama a requestCheckout con los datos de la sesión de pago (partidas del pedido, totales y métodos de pago guardados) para abrir el panel. Cuando el usuario selecciona la opción de compra, ChatGPT envía a tu servidor MCP un token que representa el método de pago seleccionado mediante una llamada a la herramienta complete_checkout. Usa tu integración con el proveedor de servicios de pago (PSP) para efectuar el cobro con este token y luego devuelve los detalles definitivos del pedido desde complete_checkout.
Resumen del proceso
- El servidor prepara la sesión: una herramienta MCP devuelve los datos de la sesión de pago (identificador de la sesión, partidas del pedido, totales y proveedor de pagos) en
structuredContent. - El widget muestra una vista previa del carrito: el widget muestra las partidas del pedido y los totales para que el usuario pueda confirmarlos.
- El widget llama a
requestCheckout: el widget invocarequestCheckout(session_data). ChatGPT abre el panel de pago y muestra el importe que se cobrará y los distintos métodos de pago. - El servidor finaliza el pedido: cuando el usuario hace clic en el botón de pago, el widget vuelve a comunicarse con tu servidor MCP mediante una llamada a la herramienta
complete_checkout. La herramienta MCP devuelve el pedido completado, que el widget recibe como respuesta arequestCheckout.
Sesión de pago
Te corresponde preparar los datos de la sesión de pago que mostrará el host. Los valores exactos de algunos campos, como id y payment_provider, dependen de tu proveedor de servicios de pago y de tu sistema de comercio. En la práctica, tu herramienta MCP debe devolver lo siguiente:
- Las partidas del pedido con las cantidades que compra el usuario.
- Los totales (subtotal, impuestos, descuentos, cargos y total), que deben coincidir con los cálculos de tu servidor.
- Los metadatos del proveedor que requiere tu integración con el PSP.
- Enlaces a la información legal y a las políticas del comercio (condiciones, política de reembolsos, etc.).
Cómo llamar a requestCheckout desde el widget
El host proporciona window.openai.requestCheckout. Úsalo para abrir el panel de pago de ChatGPT cuando el usuario inicie una compra.
Ejemplo:
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.
}En tu componente, puedes iniciar el proceso cuando el usuario haga clic en un botón:
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>
</>
);
}Este es un ejemplo completo de una sesión de pago que tu widget puede enviar al host. Tu complemento proporciona los campos de la sesión de pago que se muestran a continuación. ChatGPT agrega los campos que administra el host, como merchant, logo_url, conversation_id, connector_id y ecosystem_app_uri. Asigna al campo merchant_id el valor que indique tu 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);Puntos clave:
window.openai.requestCheckout(session)abre la interfaz de pago del host.- La promesa se resuelve con el resultado del pedido o se rechaza si ocurre un error o se cancela la operación.
- Muestra el JSON de la sesión para que los usuarios puedan revisar qué van a pagar.
- Expresa todos los importes como números enteros en la unidad menor de la moneda.
- Usa
payment_provider.managed_payment_methodspara los métodos de pago que el cliente ya guardó en tu comercio. - Mantén los valores de
metadatacomo cadenas de texto. - Usa el slug del PSP que requiere tu integración para
providery consulta a tu PSP para obtener el valor demerchant_id.
Cómo exponer la herramienta complete_checkout en el servidor MCP
Puedes seguir este patrón e incorporar tu propia lógica.
Instala fastmcp y pydantic para ejecutar este ejemplo de Python. El atributo output_schema de la herramienta declara el esquema outputSchema de MCP. El atributo ToolResult.structured_content proporciona el valor de structuredContent y meta proporciona el de _meta. La implementación de prueba local acepta example-session y example-payment-token y devuelve una respuesta de ejemplo sin efectuar ningún cargo ni crear un 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,
)Adapta el ejemplo para realizar estas tareas:
- Integra tu sistema con tu proveedor de servicios de pago para efectuar el cobro con el método de pago incluido en
payment_data. - Guarda el pedido en tu sistema.
- Devuelve los datos oficiales del pedido o del recibo.
- Incluye
_meta.ui.resourceUrisi quieres mostrar un widget de confirmación (por compatibilidad, ChatGPT también admite_meta["openai/outputTemplate"]como alias opcional).
Los siguientes proveedores de servicios de pago pueden procesar pagos realizados desde el panel de pago de ChatGPT:
- Adyen
- Checkout.com
- Fiserv
- PayPal
- Stripe
- Worldpay
Opcional: recibir los datos sin procesar de los métodos de pago
Si tu comercio cuenta con una certificación PCI DSS de nivel 1, puedes recibir directamente los datos sin procesar de los métodos de pago si implementas el punto de acceso Delegate Payment de Agentic Commerce Protocol. La solicitud de pago delegado incluirá todos los datos del método de pago que requiera tu proceso de pago, como el número de tarjeta sin procesar, la fecha de vencimiento, el CVC, la dirección de facturación, los límites de la autorización de pago, las señales de riesgo y los metadatos.
Este es un ejemplo de una solicitud con los datos sin procesar de una tarjeta de pago:
{
"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"
}
}
La respuesta correspondiente debe devolver un identificador que represente el método de pago. Este identificador se pasará 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"
}
}
Manejo de errores
La llamada a la herramienta complete_checkout puede devolver mensajes de tipo error. Los mensajes de error cuyo campo code tenga el valor payment_declined o requires_3ds se mostrarán en el panel de pago de ChatGPT. El widget recibirá todos los demás mensajes de error como respuesta a requestCheckout. Puedes elegir cómo mostrar el error en el widget.
Modo de pago de prueba
Puedes configurar el campo payment_mode con el valor test en la llamada a requestCheckout. Así se abrirá un panel de pago de ChatGPT que acepta tarjetas de prueba (como la tarjeta de prueba 4242). El token resultante, que se incluye en payment_data y se pasa a la herramienta complete_checkout, se puede procesar en el entorno de preproducción de tu PSP. Esto te permite probar el proceso de principio a fin sin mover fondos reales.
Ten en cuenta que, en el modo de pago de prueba, es posible que debas usar otro valor para merchant_id. Consulta la guía de monetización de tu proveedor de pagos para obtener más detalles.
Lista de verificación de la implementación
- Define el modelo de tu sesión de pago: incluye los identificadores, el objeto del proveedor de pagos, las partidas del pedido, los totales y los enlaces a la información legal.
- Devuelve la sesión desde tu herramienta MCP en
structuredContent, junto con la plantilla de tu widget. - Muestra la sesión en el widget para que los usuarios puedan revisar los artículos, los totales y las condiciones.
- Llama a
requestCheckout(session_data)cuando el usuario inicie el pago y procesa el pedido o el error que recibas. - Cobra al usuario mediante la herramienta MCP
complete_checkout, que debes implementar para que devuelva una respuesta conforme a la especificación de pago. - Prueba el proceso de principio a fin con importes, impuestos y descuentos realistas para verificar que el host muestre los totales esperados.