Pagos x402 2026 v2: implementar y verificar la liquidación

Práctica con Node.js para añadir micropagos a una API con x402 v2. Selecciona las condiciones de pago, vuelve a solicitar la firma y verifica la liquidación en Base Sepolia. Revisa el reenvío y las condiciones para pasar a la red principal.

Los pagos x402 se implementan incluyendo las condiciones de pago en la respuesta 402 de la API. Prepare Node.js y una cartera de prueba. Primero, verifique la firma y la liquidación de v2 en Base Sepolia. Configure la entrega de la respuesta de pago para que solo se envíe después de una liquidación correcta.

La información sobre importes y cadenas se basa en la documentación oficial de x402, Base y Circle enlazada como fuente.

Preparación e instalación para la práctica

Prepare un entorno de desarrollo donde pueda modificar la API y una cartera de prueba. El ejemplo está preparado para Node.js 22 y x402 SDK 2.28.0. La estructura de instalación sigue la guía oficial para vendedores.

  1. Prepare una dirección de cartera EVM para recibir los pagos.
  2. Prepare otra cartera de prueba para hacer los pagos.
  3. Consiga USDC de prueba de Base Sepolia para la cartera de pago.
  4. Cree el proyecto de práctica con los siguientes comandos.
  5. Guarde los archivos TypeScript que aparecen más adelante en la misma carpeta.
mkdir x402-demo
cd x402-demo
npm init -y
npm pkg set type=module
npm install --save-exact [email protected] [email protected] @x402/[email protected] @x402/[email protected] @x402/[email protected] @x402/[email protected]
npm install --save-dev --save-exact typescript tsx @types/node @types/express

El servidor receptor no necesita la clave privada de la cartera receptora. Configure la clave privada de pago para que solo se lea desde el proceso del cliente. El método de firma con la cartera se basa en la guía oficial para compradores.

La validación de este ejemplo se limita a la comprobación de tipos y a un flujo de pago simulado. No es un ejemplo en el que se haya completado una transferencia real en la red de prueba. Compruebe los resultados en la cadena durante el procedimiento de ejecución que se indica a continuación.

Comparación entre x402 v1 y v2

Al implementar v2, debe adaptar tanto las cabeceras como los campos del cuerpo. Cambiar solo los nombres de las cabeceras deja una estructura de datos incompatible. La siguiente tabla se basa en la guía oficial de migración.

Aspecto v1 v2
Versión del protocolo x402Version: 1 x402Version: 2
Condiciones de pago iniciales Cuerpo JSON de la respuesta 402 Cabecera de respuesta PAYMENT-REQUIRED
Datos de pago firmados Cabecera de solicitud X-PAYMENT Cabecera de solicitud PAYMENT-SIGNATURE
Resultado de la liquidación Cabecera de respuesta X-PAYMENT-RESPONSE Cabecera de respuesta PAYMENT-RESPONSE
Identificador de la red principal de Base base eip155:8453
Identificador de Base Sepolia base-sepolia eip155:84532
Campo del importe en las condiciones de pago maxAmountRequired amount
Descripción del recurso resource y otros campos dentro de las condiciones de pago Objeto resource de nivel superior
Condiciones en los datos de pago scheme, network y otros campos de nivel superior Objeto accepted que contiene las condiciones seleccionadas
Ejemplo de paquete TypeScript x402-express @x402/express

La ubicación donde se envían las condiciones de pago en v1 está especificada en la especificación HTTP v1. La ubicación estándar en v2 es la cabecera PAYMENT-REQUIRED. Una implementación también puede devolverlas en el cuerpo, pero debe procesarlas tomando la cabecera como referencia.

La especificación HTTP v2 describe el código de estado de la siguiente manera.

El servidor indica que se requiere un pago mediante el código de estado HTTP 402 «Payment Required».

Fuente: especificación HTTP v2 de x402

Las cabeceras de pago de v2 contienen JSON codificado en Base64. Base64 no es un método de cifrado. Use HTTPS en los servicios externos.

Solicitud HTTP 402 y secuencia de pago

Esta práctica utiliza el flujo de autorización predeterminado del esquema EVM exact. exact es un esquema para pagar un importe fijo. La secuencia sigue la especificación principal de x402 v2.

  1. El cliente solicita la API de pago sin información de pago.
  2. El servidor devuelve HTTP 402 y PAYMENT-REQUIRED.
  3. El cliente selecciona unas condiciones permitidas de accepts.
  4. El SDK firma una autorización de pago que cumple las condiciones seleccionadas.
  5. El cliente repite la solicitud añadiendo PAYMENT-SIGNATURE.
  6. El servidor verifica la autorización mediante /verify del facilitator.
  7. Si la verificación se supera, el servidor procesa el recurso.
  8. El servidor solicita la liquidación mediante /settle.
  9. Tras una liquidación correcta, entrega el cuerpo de pago y PAYMENT-RESPONSE.

Esta secuencia no es fija ni común a todos los métodos de pago. v2 también define flujos con distintos momentos de liquidación. El siguiente código solo permite el flujo predeterminado authorization.

Funciones del servidor de recursos y del facilitator

El servidor de recursos determina el precio y las condiciones de acceso al contenido. El facilitator se encarga de verificar y liquidar los pagos. Esta división de funciones se basa en la documentación oficial del facilitator.

Componente Función Estado que no debe considerarse un éxito
Cliente Seleccionar las condiciones y firmar la autorización de pago Solo se ha generado la firma
Servidor de recursos Declarar el precio y controlar la respuesta de pago El cliente afirma que el pago se ha completado
Facilitator /verify Comprobar la validez de la firma y de las condiciones de pago Solo se ha recibido isValid: true
Facilitator /settle En esta práctica, ejecutar el pago en la cadena y devolver el resultado Se ha enviado, pero no se ha confirmado el resultado

/verify es una comprobación que no modifica el estado de la cadena. Por tanto, superar la verificación no significa que se hayan recibido los fondos. El saldo o el estado de la autorización pueden cambiar incluso después de la verificación.

Bloquee el cuerpo de pago si falla la verificación o la liquidación. Bloquear cuando no se ha podido confirmar el éxito se denomina fail-closed. Este comportamiento también puede comprobarse en la implementación oficial de Express.

Comparación entre la red principal y la red de prueba de Base

En la primera ejecución, use solo Base Sepolia. Circle especifica que el USDC de la red de prueba no tiene valor financiero. Las direcciones se basan en la lista de contratos de USDC de Circle.

Aspecto Red principal de Base Red de prueba Base Sepolia
Uso Pagos con activos reales Pruebas de implementación y gestión de fallos
Chain ID 8453 84532
Red x402 v2 eip155:8453 eip155:84532
Contrato de USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 0x036CbD53842c5426634e7929541eC2318f3dCF7e
RPC público https://mainnet.base.org https://sepolia.base.org
Valor financiero del token Activo con valor financiero real Sin valor financiero

Consulte el Chain ID y el RPC en la documentación de la red Base. Aunque la dirección de la cartera sea la misma, los saldos son independientes si las cadenas son distintas. No registre un pago correcto en la red de prueba como una venta real.

Puede solicitar USDC de prueba en Circle Testnet Faucet. Seleccione Base Sepolia como red. En la dirección de recepción, introduzca la dirección de la cartera de prueba que usará para pagar.

Implementación de una API de pago con Node.js

Conecte paymentMiddleware antes de la ruta de pago. El siguiente ejemplo exige 0.001 USDC por llamada. El importe corresponde al precio de ejemplo de la guía oficial para vendedores. (Valor comprobado: 0.001 USDC por llamada · Fuente: docs.x402.org · Comprobado el 2026-10-28)

Archivo del servidor

Guarde el siguiente código como server.ts. El servidor solo acepta solicitudes en la interfaz local. La dirección receptora se lee de la variable de entorno PAY_TO.

import express from "express";
import { getAddress, zeroAddress } from "viem";
import { paymentMiddleware } from "@x402/express";
import { HTTPFacilitatorClient, x402ResourceServer } from "@x402/core/server";
import { ExactEvmScheme } from "@x402/evm/exact/server";

const payTo = getAddress(process.env.PAY_TO ?? "");
if (payTo === zeroAddress) throw new Error("Invalid payTo");
const network = "eip155:84532";
const resourceServer = new x402ResourceServer(
  new HTTPFacilitatorClient({ url: "https://x402.org/facilitator" }),
).register(network, new ExactEvmScheme());

const app = express();
app.use((_req, res, next) => {
  res.setHeader("Cache-Control", "private, no-store");
  next();
});
app.use(paymentMiddleware({
  "GET /paid-data": {
    accepts: [{ scheme: "exact", price: "$0.001", network, payTo }],
    description: "Sample paid JSON",
    mimeType: "application/json",
  },
}, resourceServer));
app.get("/paid-data", (_req, res) => {
  res.json({ content: "Paid sample content" });
});
app.listen(4021, "127.0.0.1");

https://x402.org/facilitator es la dirección de prueba de la guía oficial. En este ejemplo se utiliza para la liquidación en Base Sepolia. Para elegir un facilitator de producción, consulte el procedimiento para la red principal de la guía para vendedores.

Ejemplo de cálculo del precio

El precio del ejemplo equivale a 1000 unidades mínimas de USDC. USDC tiene 6 decimales. La conversión de precios del SDK se basa en la implementación del servidor EVM.

0.001 USDC × 10^6 = 1000 최소 단위
Valor que debe comprobarse Valor esperado en este ejemplo
price en la configuración del servidor "$0.001"
amount en las condiciones de pago del 402 "1000"
asset en las condiciones de pago Contrato de USDC de Base Sepolia
payTo en las condiciones de pago Dirección receptora configurada
network en las condiciones de pago eip155:84532

price es un valor de configuración del SDK. En las condiciones de pago reales de v2 se envía amount. Compare los importes enteros como cadenas de texto o como bigint.

Ejecución del servidor y comprobación del 402

Ejecute el servidor en el primer terminal Bash. El valor que debe introducir es la dirección pública receptora, no una clave privada. Mantenga este terminal abierto durante la ejecución.

read -r -p '수취 지갑 주소: ' PAY_TO
export PAY_TO
npx tsx server.ts

Envíe una solicitud sin pago desde un segundo terminal. El siguiente comando no firma ningún pago. Muestra el estado HTTP y las condiciones de pago decodificadas.

node --input-type=module <<'JS'
const response = await fetch("http://127.0.0.1:4021/paid-data");
const header = response.headers.get("PAYMENT-REQUIRED");
console.log(response.status);
console.log(header && JSON.parse(
  Buffer.from(header, "base64").toString("utf8")
));
JS

La respuesta normal a una solicitud sin pago es HTTP 402. Compare las condiciones mostradas con la tabla anterior. Si el contenido de pago se devuelve directamente, corrija primero la configuración de protección de la ruta.

Selección de condiciones de pago e implementación del cliente

Restrinja el cliente para que solo firme las condiciones permitidas. Este ejemplo solo permite el precio fijo de USDC en Base Sepolia. El filtro de opciones de pago utiliza registerPolicy de la implementación oficial de x402Client.

  1. Guarde el siguiente código como client.ts.
  2. Guarde también check-transfer.ts, que aparece en la siguiente sección.
  3. Una vez preparados ambos archivos, continúe con el procedimiento de ejecución.
import { writeFile } from "node:fs/promises";
import { getAddress, zeroAddress, type Hex, type Hash } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { decodePaymentResponseHeader } from "@x402/core/http";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { checkTransfer } from "./check-transfer.js";

const key = process.env.EVM_PRIVATE_KEY ?? "";
if (!/^0x[0-9a-fA-F]{64}$/.test(key)) throw new Error("Invalid test key");
const signer = privateKeyToAccount(key as Hex);
const payTo = getAddress(process.env.PAY_TO ?? "");
if (payTo === zeroAddress) throw new Error("Invalid payTo");
const network = "eip155:84532";
const token = "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
const client = new x402Client().register(network, new ExactEvmScheme(signer));
client.registerPolicy((version, options) => version === 2
  ? options.filter(r =>
      r.scheme === "exact" && r.network === network &&
      r.asset.toLowerCase() === token.toLowerCase() &&
      r.payTo.toLowerCase() === payTo.toLowerCase() && r.amount === "1000" &&
      (!r.extra?.assetTransferMethod || r.extra.assetTransferMethod === "eip3009") &&
      (!r.extra?.paymentFlow || r.extra.paymentFlow === "authorization"))
  : []);

const paidFetch = wrapFetchWithPayment(fetch, client);
const response = await paidFetch("http://127.0.0.1:4021/paid-data", {
  redirect: "error",
});
const raw = response.headers.get("PAYMENT-RESPONSE");
if (!raw) throw new Error(`No settlement receipt: HTTP ${response.status}`);
const settlement = decodePaymentResponseHeader(raw);
await writeFile("settlement.json", JSON.stringify(settlement, null, 2));
if (!response.ok || !settlement.success || settlement.network !== network) {
  throw new Error("Payment unresolved; inspect settlement.json before retrying");
}
const evidence = await checkTransfer(
  network, settlement.transaction as Hash, signer.address, payTo, 1000n,
);
await writeFile("transfer.json", JSON.stringify(evidence, null, 2));
console.log(await response.text());

wrapFetchWithPayment se encarga de procesar el 402 y de repetir la solicitud con la firma. Su uso sigue el ejemplo oficial de fetch. Si no hay condiciones de pago permitidas, se detiene la creación del pago.

Este cliente también puede usarse en agentes de IA. Sin embargo, un límite de precio por llamada no es un límite de gasto acumulado. Gestione por separado el presupuesto para las llamadas repetidas del agente.

Verificación del evento Transfer de USDC

Compruebe los registros de transferencia de USDC mediante el hash de la transacción del resultado de liquidación. El estado correcto de la transacción, por sí solo, no confirma el destinatario. Los campos de Transfer se basan en el estándar ERC-20.

La verificación requiere los siguientes elementos.

Elemento de verificación Valor con el que se compara
Chain ID del RPC Cadena permitida por el servidor
status del recibo de la transacción Estado correcto
Dirección que emitió el evento Contrato oficial de USDC de esa cadena
Transfer.from Pagador confirmado
Transfer.to Dirección receptora definida por el servidor
Transfer.value Importe exigido por el servidor en unidades mínimas

Guarde el siguiente código como check-transfer.ts. La consulta utiliza getTransactionReceipt de viem. La interpretación de los eventos se basa en parseEventLogs.

import {
  createPublicClient, http, getAddress, parseEventLogs,
  erc20Abi, type Address, type Hash,
} from "viem";
import { base, baseSepolia } from "viem/chains";

const configs = {
  "eip155:84532": {
    chain: baseSepolia,
    rpc: "https://sepolia.base.org",
    token: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
  },
  "eip155:8453": {
    chain: base,
    rpc: "https://mainnet.base.org",
    token: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  },
} as const;

export async function checkTransfer(
  network: keyof typeof configs, hash: Hash,
  payer: Address, payTo: Address, amount: bigint,
) {
  const cfg = configs[network];
  const rpc = createPublicClient({ chain: cfg.chain, transport: http(cfg.rpc) });
  if (await rpc.getChainId() !== cfg.chain.id) throw new Error("Wrong chain");
  const receipt = await rpc.getTransactionReceipt({ hash });
  if (receipt.status !== "success") throw new Error("Transaction failed");
  const logs = parseEventLogs({
    abi: erc20Abi,
    eventName: "Transfer",
    logs: receipt.logs.filter(
      log => getAddress(log.address) === getAddress(cfg.token),
    ),
    strict: true,
  });
  const transfer = logs.find(log =>
    getAddress(log.args.from) === getAddress(payer) &&
    getAddress(log.args.to) === getAddress(payTo) &&
    log.args.value === amount,
  );
  if (!transfer) throw new Error("Matching USDC Transfer not found");
  return {
    network, transaction: hash, logIndex: transfer.logIndex,
    blockHash: receipt.blockHash, blockNumber: receipt.blockNumber.toString(),
  };
}

Esta función confirma que hubo una transferencia de USDC en esa transacción. Debe comprobarse por separado si corresponde a un pedido concreto de la API. En un servidor de producción, use las condiciones guardadas del pedido como valores de comparación.

No confíe en el archivo transfer.json enviado por el cliente como prueba para conceder acceso. El servidor de este ejemplo utiliza los resultados de verificación y liquidación del facilitator. Si quiere usar una consulta independiente como condición para conceder acceso, debe ejecutarla en el servidor.

Un fallo en la consulta del recibo no significa necesariamente que el pago haya fallado. Si se trata de un error del RPC, vuelva a consultar el hash de transacción guardado. Defina en la política operativa el número de confirmaciones adicionales y la respuesta a las reorganizaciones de la cadena.

Ejecución del pago de prueba y comprobación de resultados

Después de guardar todos los archivos, ejecute el ejemplo con la cartera de prueba. La comprobación de tipos no firma ni transfiere fondos. Los siguientes comandos utilizan las herramientas de TypeScript instaladas antes.

  1. Compruebe los tipos con el siguiente comando.
  2. Introduzca en el segundo terminal la misma dirección receptora que usa el servidor.
  3. Introduzca la clave privada de la cartera de pago de prueba sin que se muestre en pantalla.
  4. Ejecute el cliente una vez.
  5. Compruebe el resultado de liquidación y los registros de transferencia guardados.
npx tsc --noEmit --strict --skipLibCheck --target ES2022 --module NodeNext --moduleResolution NodeNext server.ts client.ts check-transfer.ts
read -r -p '같은 수취 지갑 주소: ' PAY_TO
read -r -s -p '테스트 결제 지갑 개인키: ' EVM_PRIVATE_KEY
export PAY_TO EVM_PRIVATE_KEY
npx tsx client.ts
unset EVM_PRIVATE_KEY
Resultado Significado Qué comprobar
settlement.json Resultado de liquidación devuelto por el servidor success, network, transaction
transfer.json Registro de transferencia encontrado en la consulta RPC Cadena, hash de transacción, posición del registro e información del bloque
Cuerpo de pago en la consola Datos mostrados tras la verificación de este cliente Comprobar que sea el contenido solicitado

Una nueva ejecución del cliente puede generar un nuevo pago. Este ejemplo mínimo no incluye un almacenamiento para evitar duplicados por pedido. Añada la función de reintento solo después de cumplir las condiciones de la siguiente sección.

Tratamiento según las condiciones de fallo de verificación

En las pruebas de fallo, compruebe que no se exponga el cuerpo de pago. Si solo comprueba el estado HTTP, puede pasar por alto un fallo de bloqueo. Consulte el middleware oficial de Express como referencia del comportamiento esperado.

Condición de prueba Tratamiento esperado Comprobación adicional
Sin cabecera de pago Devolver 402 y las condiciones de pago Sin cuerpo de pago
Se propone otro token o destinatario Rechazar mediante la política del cliente No generar una firma
Firma incorrecta Bloquear por fallo de verificación No ejecutar el manejador de pago
Saldo insuficiente Bloquear por fallo de verificación o liquidación No registrar la liquidación como correcta
Resultado de liquidación fallido Bloquear la respuesta de pago No enviar ni siquiera el cuerpo ya preparado
Retraso en la respuesta del facilitator Mantener pendiente al no haberse confirmado el éxito Prohibir la generación automática de una nueva autorización
Error al consultar el recibo por RPC Conservar el hash de transacción y volver a consultar No dar por hecho que el pago ha fallado

En el flujo de autorización predeterminado, el manejador se ejecuta antes de la liquidación. Un fallo de liquidación no revierte las operaciones externas. Empiece por consultas sin efectos secundarios, como en este ejemplo.

El envío de correos electrónicos o la creación de pedidos externos requieren un diseño aparte. Registre conjuntamente el estado del pago y el de la operación. Defina qué se volverá a ejecutar en caso de fallo para reducir las operaciones duplicadas.

Pérdida de respuesta tras la liquidación y recuperación mediante reenvío

Guarde como estados separados la finalización del pago y la entrega del contenido. El pago puede haberse completado y, aun así, perderse la conexión de respuesta. El tratamiento de estas situaciones se basa en la documentación de la extensión Payment-Identifier.

La propiedad que evita procesar una operación por duplicado aunque se solicite de nuevo se denomina idempotencia. payment-identifier proporciona un identificador de pago para este fin. Añadir el identificador no basta para que esta función quede implementada automáticamente.

Comparación entre pagos duplicados y reenvíos

Debe distinguirse entre impedir la reutilización de una misma firma y evitar pedidos duplicados. EIP-3009 impide reutilizar el nonce de una autorización ya utilizada. Este comportamiento está definido en la especificación ERC-3009.

Situación Desde la perspectiva de la autorización en la cadena Desde la perspectiva de la operación de la API
Volver a liquidar la misma autorización Sujeta a la comprobación de nonce ya utilizado Es necesario consultar el resultado existente
Crear una nueva autorización para el mismo pedido Puede tratarse como una autorización independiente Es necesario evitar pagos duplicados
Pérdida de respuesta tras una liquidación correcta El movimiento de activos puede haberse completado Es necesario volver a entregar el contenido
Tiempo de espera agotado tras solicitar la liquidación El resultado aún es incierto Es necesario mantener el estado pendiente y comprobar la liquidación

El siguiente procedimiento es una propuesta de diseño para conectar la extensión oficial con el almacenamiento de producción. No está incluido en el código mínimo anterior. Para aplicarlo en producción, añada almacenamiento persistente y control de solicitudes simultáneas.

  1. Declare en el servidor la compatibilidad con la extensión payment-identifier.
  2. Conserve en el cliente el identificador de la solicitud lógica.
  3. Vincule en el servidor el identificador con el pagador y el contenido de la solicitud.
  4. Registre de forma atómica el estado de procesamiento para impedir ejecuciones simultáneas.
  5. Cuando la liquidación se complete correctamente, guarde las pruebas de la transacción y el resultado de la respuesta.
  6. Si los permisos y el contenido de la nueva solicitud coinciden, devuelva el resultado guardado.
  7. Si el resultado de liquidación es incierto, compruebe primero la autorización existente.

Un identificador de pago no es una contraseña ni un token de acceso. No devuelva contenido de pago almacenado en caché a una solicitud solo porque conozca el identificador. Compruebe también si se está reutilizando para otro usuario o con otro cuerpo de solicitud.

Guarde juntos la cadena, el hash de transacción y la posición del registro en los registros de producción. Vincule estos datos al pedido para impedir su reutilización en otros pedidos. La coincidencia de Transfer por sí sola no demuestra a qué pedido corresponde.

Errores frecuentes en la implementación de pagos

Confundir los campos de versión y las señales de éxito puede dar lugar a una evaluación incorrecta del pago. Use la siguiente tabla en la revisión del despliegue. Las diferencias entre versiones se basan en la guía de migración de x402.

Error frecuente Criterio correcto
Interpretar extra.version: "2" como la versión de x402 Comprobar la versión del protocolo mediante x402Version
Usar maxAmountRequired en v2 Usar amount para el importe de las condiciones de pago
Crear por cuenta propia la cabecera X-PAYMENT-REQUIRED Usar el cuerpo en v1 y PAYMENT-REQUIRED en v2
Tratar isValid: true como confirmación de recepción de fondos Comprobar por separado el resultado de /settle
Tratar el campo to de nivel superior de la transacción como el destinatario de USDC Comprobar Transfer.to de USDC
Suponer que el firmante y el remitente de la transacción son el mismo Comparar el pagador de la autorización con Transfer.from
Sumar los importes recibidos en la red de prueba a las ventas Separar los libros de la red principal y de la red de prueba
Crear un nuevo pago cada vez que se agota el tiempo de espera Recuperar primero el pedido existente y el estado de su autorización
Equiparar la versión del paquete SDK con la del protocolo Gestionar por separado la versión del paquete y x402Version

La información de dominio de la firma de USDC también contiene una cadena de versión. Ese valor tiene una finalidad distinta de la versión del protocolo x402. Consulte la estructura del dominio de firma en la especificación ERC-3009.

Revisión de seguridad y alcance de la confianza en servicios externos

Controle desde el servidor la decisión de considerar un pago correcto. La respuesta del facilitator externo también es un elemento en el que se confía de forma explícita. La arquitectura que permite operarlo por cuenta propia se explica en la documentación del facilitator.

Las dependencias fijadas para esta práctica aún presentan advertencias de seguridad. npm audit informó de un aviso relacionado con zod. Consulte los detalles en el aviso de seguridad de GitHub.

npm audit

Antes de desplegar en producción, compruebe la compatibilidad del SDK con la versión corregida. Forzar un cambio de versión principal puede alterar el comportamiento. No use esta práctica como una configuración de despliegue cuya seguridad ya haya sido validada.

Comparación entre un servidor propio y Cloudflare Gateway

Al usar Cloudflare Gateway, cambia el método de verificación del servidor de origen. La documentación del 30 de septiembre de 2026 especifica el uso de x402 v2. La siguiente comparación se basa en la documentación de x402 de Cloudflare.

Aspecto Método con Express de este artículo Cloudflare Monetization Gateway
Procesamiento del pago del cliente Middleware de Express Gateway
Punto de verificación del servidor de origen Integración con el facilitator elegido Verificación del JWT PAYMENT-CONTEXT
Entrega del resultado de liquidación PAYMENT-RESPONSE del middleware Gateway genera el recibo de liquidación
Comprobaciones adicionales Cadenas admitidas y autenticación del facilitator Verificación de la firma JWT y protección del acceso al origen

PAYMENT-CONTEXT es una cabecera entre Gateway y el servidor de origen. No es la cabecera de firma de un cliente x402 convencional. Para la verificación en el origen, siga la documentación Payment validation de Cloudflare.

Aunque se use Gateway, no basta con decodificar el JWT. Verifique la firma con la clave indicada en la documentación. Si falta la cabecera o falla la verificación, bloquee el contenido de pago.

Distinción entre uso real y registros de liquidación

El número de transferencias en la cadena, por sí solo, no demuestra el consumo de contenido. Calcule las métricas operativas vinculando la liquidación con la entrega de la respuesta. Esta es una propuesta de diseño basada en el flujo de pago y el comportamiento de los reenvíos.

Registro Pregunta que permite responder Registro adicional necesario
Respuesta 402 Cuántas veces se han solicitado las condiciones de pago Si el pago se ha producido realmente
Verificación correcta Si la autorización era válida Resultado de liquidación
Transferencia de USDC Si se han movido los activos Pedido al que corresponde
Liquidación completada por pedido Si se ha pagado la solicitud de pago Estado de entrega de la respuesta
Registro de reentrega Si se ha recuperado una solicitud ya pagada Identificador que permita distinguirla de un pago nuevo

Distinga las solicitudes de prueba al calcular el uso real. Marque también por separado los reintentos de un mismo pedido. No presente el volumen de transacciones en sí como prueba de demanda de la API ni como garantía de ingresos.

Procedimiento de transición a la red principal de Base

Considere el paso a la red principal después de comprobar los casos correctos y de fallo en la red de prueba. Cambiar solo la cadena de texto de la red no completa la transición. El procedimiento de referencia sigue la guía oficial para vendedores.

  1. Compruebe que el facilitator elegido admita la red principal de Base.
  2. Compruebe en /supported la compatibilidad con v2, exact y eip155:8453.
  3. Configure la autenticación y las condiciones de uso exigidas por el proveedor.
  4. Cambie la red tanto en el servidor como en el cliente.
  5. Cambie la dirección permitida de USDC del cliente por la dirección de la red principal.
  6. Vuelva a contrastar el importe de la respuesta 402 y la dirección receptora real.
  7. Integre el almacenamiento para solicitudes duplicadas y el procedimiento de recuperación ante fallos.
  8. Complete la revisión de seguridad de las dependencias de producción.
  9. Compruebe la transferencia real y la entrega del contenido con el importe pequeño configurado.

La compatibilidad con varias cadenas no significa que se admitan todas las combinaciones. Compruebe conjuntamente el alcance de la compatibilidad del SDK y del facilitator. La referencia para esta comprobación es la documentación sobre compatibilidad con redes y tokens.

FAQ

¿En qué se diferencia x402 de la confirmación de un depósito normal de USDC?

Durante la solicitud HTTP se comunican las condiciones de pago y se repite la solicitud con una autorización de pago firmada. A diferencia del método que coteja después los registros de depósitos, vincula el proceso de pago con la solicitud de un recurso de pago.

¿Cuáles son las cabeceras de pago de x402 v2?

Las condiciones de pago se transmiten mediante PAYMENT-REQUIRED y la carga útil de pago mediante PAYMENT-SIGNATURE. El resultado de la liquidación se transmite mediante PAYMENT-RESPONSE.

¿Existe la cabecera X-PAYMENT-REQUIRED en v1?

La especificación oficial HTTP v1 incluye las condiciones iniciales de pago en el cuerpo de la respuesta JSON. Para la carga útil de pago y el resultado de la liquidación se usan X-PAYMENT y X-PAYMENT-RESPONSE, respectivamente.

¿El éxito de /verify significa que el pago se ha completado?

El éxito de /verify significa que la autorización de pago es válida. En esta práctica, debes comprobar por separado que el resultado de /settle sea satisfactorio.

¿Se pueden considerar los USDC de prueba de Base Sepolia como ingresos reales?

Circle indica expresamente que los USDC de la red de pruebas no tienen valor financiero. Registra las liquidaciones de la red de pruebas por separado de las ventas reales.

¿Hay que introducir una clave privada en el servidor receptor?

En el servidor receptor de este ejemplo solo se configura la dirección pública de recepción. La clave privada usada para la autorización de pago se lee en el cliente de pago.

¿Cuál es el valor de amount para 0.001 USDC?

Al aplicar los 6 decimales de USDC, el valor en la unidad mínima es 1000. En las condiciones de pago de v2 se usa la cadena "1000".

¿Un recibo de transacción satisfactorio confirma también la recepción de USDC?

El estado satisfactorio de la transacción no basta. Coteja el pagador, el destinatario y el importe en el evento Transfer del contrato oficial de USDC.

¿Es seguro reenviar la misma solicitud de pago?

La prevención de la reutilización del nonce de una misma autorización y la prevención de pedidos duplicados son cuestiones distintas. Antes de reintentar, comprueba el estado del pago existente e implementa un mecanismo de idempotencia por pedido.

¿Si no hay PAYMENT-RESPONSE, basta con volver a pagar?

Si se pierde la respuesta o se agota el tiempo de espera, el resultado de la liquidación puede ser incierto. No empieces creando una nueva autorización; comprueba el estado de liquidación de la solicitud existente.

¿Con x402 hay que usar únicamente el facilitador de una empresa específica?

La arquitectura oficial permite tanto usar un facilitador externo como operar uno propio. Comprueba que la implementación elegida admita la versión del protocolo, el método de pago y la cadena que necesitas.

¿También se limita automáticamente el gasto de los agentes de IA?

Este ejemplo solo limita las condiciones de pago de cada solicitud. Gestiona el gasto acumulado por las llamadas repetidas con una política de presupuesto independiente.

¿PAYMENT-CONTEXT de Cloudflare es una cabecera estándar de firma de pago?

PAYMENT-CONTEXT es un JWT que Gateway envía al servidor de origen. Su finalidad es distinta de la de PAYMENT-SIGNATURE del cliente.

¿Se puede desplegar el ejemplo directamente en la red principal?

Este código es una configuración mínima para pruebas. Antes de desplegarlo en producción, compruebe las advertencias de seguridad de las dependencias, la gestión de solicitudes duplicadas, la autenticación del facilitador y la liquidación real.

Sources

Images

Un hombre con un suéter gris oscuro revisa una tableta sobre la bandeja de un rack de servidores.
Un hombre con un suéter gris oscuro revisa una tableta sobre la bandeja de un rack de servidores.
Una mujer teclea en un portátil abierto en plano; la pantalla muestra una lista y dos rutas que convergen.
Una mujer teclea en un portátil abierto en plano; la pantalla muestra una lista y dos rutas que convergen.