---
title: "x402 2026 v2: implementar pagamentos e validar liquidação"
locale: pt
category: tutorial
category_name: "Tutorial"
translation_status: reviewed
license: cc_by
author: "injoys"
source_url: https://injoys.com/en/articles/x402-payments-2026-v2-base-usdc-settlement-guide
published_at: 2026-10-28T19:20:55+09:00
---

# x402 2026 v2: implementar pagamentos e validar liquidação

> Exercício prático em Node.js para adicionar micropagamentos a uma API com x402 v2. Na Base Sepolia, selecione as condições de pagamento, solicite novamente a assinatura e valide a liquidação. Verifique os reenvios e as condições para a migração para a mainnet.

## Key Points

- Prepare o endereço de recebimento e a carteira para testes de pagamento e instale o SDK oficial do x402.
- Integre o middleware de pagamento para a Base Sepolia e verifique a resposta 402 a uma requisição sem pagamento.
- Selecione e assine apenas as condições que correspondam à rede, ao token, ao valor e ao destinatário autorizados pelo cliente.
- Consulte o evento USDC Transfer usando o hash da transação presente na resposta de liquidação.
- Teste o bloqueio em caso de falha e a recuperação de requisições duplicadas e, depois, revise as configurações da mainnet.

O pagamento x402 é implementado incluindo as condições de pagamento na resposta 402 da API. Prepare o Node.js e uma carteira de teste. Primeiro, valide a assinatura e a liquidação v2 na Base Sepolia. Configure o envio da resposta paga somente após o sucesso da liquidação.

As informações de valores e redes seguem a documentação oficial de x402, Base e Circle vinculada nas fontes.

## Preparação e instalação para a prática

Prepare um ambiente de desenvolvimento em que seja possível modificar a API e uma carteira de teste. O exemplo foi elaborado com Node.js 22 e x402 SDK 2.28.0. A estrutura de instalação segue o [guia oficial para vendedores](https://docs.x402.org/getting-started/quickstart-for-sellers).

1. Prepare um endereço de carteira EVM para receber os pagamentos.
2. Prepare uma carteira de teste separada para efetuar os pagamentos.
3. Obtenha USDC de teste da Base Sepolia para a carteira de pagamento.
4. Crie o projeto de prática com os comandos abaixo.
5. Salve os arquivos TypeScript apresentados a seguir na mesma pasta.

```bash
mkdir x402-demo
cd x402-demo
npm init -y
npm pkg set type=module
npm install --save-exact express@5.3.0 viem@2.57.12 @x402/core@2.28.0 @x402/express@2.28.0 @x402/evm@2.28.0 @x402/fetch@2.28.0
npm install --save-dev --save-exact typescript tsx @types/node @types/express
```

O servidor que recebe os pagamentos não precisa da chave privada da carteira recebedora. Configure a chave privada usada para pagar de modo que ela seja lida apenas pelo processo do cliente. O método de assinatura da carteira segue o [guia oficial para compradores](https://docs.x402.org/getting-started/quickstart-for-buyers).

A validação deste exemplo abrange a checagem de tipos e um fluxo de pagamento simulado. Não é um exemplo em que a transferência real na rede de testes já foi concluída. Confira os resultados on-chain por conta própria nas etapas de execução abaixo.

## Comparação entre x402 v1 e v2

Ao implementar a v2, é preciso adequar tanto os cabeçalhos quanto os campos do corpo. Alterar apenas os nomes dos cabeçalhos deixa a estrutura dos dados incompatível. A tabela a seguir se baseia no [guia oficial de migração](https://docs.x402.org/guides/migration-v1-to-v2).

| Aspecto | v1 | v2 |
|---|---|---|
| Versão do protocolo | `x402Version: 1` | `x402Version: 2` |
| Condições iniciais de pagamento | Corpo JSON da resposta 402 | Cabeçalho de resposta `PAYMENT-REQUIRED` |
| Dados de pagamento assinados | Cabeçalho de requisição `X-PAYMENT` | Cabeçalho de requisição `PAYMENT-SIGNATURE` |
| Resultado da liquidação | Cabeçalho de resposta `X-PAYMENT-RESPONSE` | Cabeçalho de resposta `PAYMENT-RESPONSE` |
| Identificador da rede principal da Base | `base` | `eip155:8453` |
| Identificador da Base Sepolia | `base-sepolia` | `eip155:84532` |
| Campo de valor nas condições de pagamento | `maxAmountRequired` | `amount` |
| Descrição do recurso | `resource` e outros campos dentro das condições de pagamento | Objeto `resource` no nível superior |
| Condições no payload de pagamento | `scheme`, `network` e outros campos no nível superior | Objeto `accepted` com as condições selecionadas |
| Exemplo de pacote TypeScript | `x402-express` | `@x402/express` |

O local de envio das condições de pagamento na v1 está definido na [especificação HTTP v1](https://github.com/x402-foundation/x402/blob/main/specs/transports-v1/http.md). Na v2, o local padrão é o cabeçalho `PAYMENT-REQUIRED`. A implementação também pode retornar um corpo, mas use o cabeçalho como referência para o processamento.

A [especificação HTTP v2](https://github.com/x402-foundation/x402/blob/main/specs/transports-v2/http.md) descreve o código de status da seguinte forma.

> O servidor indica que o pagamento é necessário usando o código de status HTTP 402 "Pagamento necessário".
>
> Fonte: especificação HTTP v2 do x402

Os cabeçalhos de pagamento da v2 contêm valores JSON codificados em Base64. Base64 não é um método de criptografia. Use HTTPS em serviços externos.

## Sequência de requisição HTTP 402 e pagamento

Esta prática usa o fluxo básico de autorização do mecanismo EVM `exact`. `exact` é uma forma de pagamento de um valor definido. A sequência segue a [especificação central do x402 v2](https://github.com/x402-foundation/x402/blob/main/specs/x402-specification-v2.md).

1. O cliente faz uma requisição à API paga sem informações de pagamento.
2. O servidor retorna HTTP 402 e `PAYMENT-REQUIRED`.
3. O cliente seleciona uma das condições permitidas em `accepts`.
4. O SDK assina uma autorização de pagamento compatível com a condição selecionada.
5. O cliente repete a requisição incluindo `PAYMENT-SIGNATURE`.
6. O servidor valida a autorização por meio de `/verify` do facilitador.
7. Se a validação for aprovada, o servidor executa o processamento do recurso.
8. O servidor solicita a liquidação por meio de `/settle`.
9. Após o sucesso da liquidação, entrega o corpo pago e `PAYMENT-RESPONSE`.

Essa não é uma sequência fixa comum a todos os métodos de pagamento. A v2 também define fluxos com outros momentos de liquidação. O código abaixo permite apenas o fluxo básico `authorization`.

### Papéis do servidor de recursos e do facilitador

O servidor de recursos determina o preço e as condições de acesso ao conteúdo. O facilitador é responsável pela validação do pagamento e pela liquidação. A divisão de papéis se baseia na [documentação oficial do facilitador](https://github.com/x402-foundation/x402/blob/main/docs/core-concepts/facilitator.md).

| Componente | Responsabilidade | Estado que não deve ser considerado sucesso |
|---|---|---|
| Cliente | Selecionar condições e assinar a autorização de pagamento | Apenas a geração da assinatura foi concluída |
| Servidor de recursos | Declarar o preço e controlar a resposta paga | O cliente afirma que houve sucesso |
| Facilitador `/verify` | Verificar a validade da assinatura e das condições de pagamento | Apenas `isValid: true` foi recebido |
| Facilitador `/settle` | Nesta prática, executar o pagamento on-chain e retornar o resultado | A transação foi enviada, mas o resultado não foi confirmado |

`/verify` é uma verificação que não altera o estado on-chain. Portanto, uma validação bem-sucedida não significa que o recebimento foi concluído. Mesmo após a validação, o saldo ou o estado da autorização pode mudar.

Se a validação ou a liquidação falhar, bloqueie o corpo pago. Bloquear quando não é possível confirmar o sucesso é um comportamento chamado fail-closed. Esse comportamento também pode ser observado na [implementação oficial para Express](https://github.com/x402-foundation/x402/blob/main/typescript/packages/http/express/src/index.ts).

## Comparação entre a rede principal e a rede de testes da Base

Na primeira execução, use apenas a Base Sepolia. A Circle declara que o USDC da rede de testes não tem valor financeiro. Os endereços seguem a [lista de contratos USDC da Circle](https://developers.circle.com/stablecoins/usdc-contract-addresses).

| Item | Rede principal da Base | Rede de testes Base Sepolia |
|---|---|---|
| Finalidade | Pagamento com ativos reais | Testes de implementação e tratamento de falhas |
| Chain ID | `8453` | `84532` |
| Rede x402 v2 | `eip155:8453` | `eip155:84532` |
| Contrato USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | `0x036CbD53842c5426634e7929541eC2318f3dCF7e` |
| RPC público | `https://mainnet.base.org` | `https://sepolia.base.org` |
| Valor financeiro do token | Ativo com valor financeiro real | Sem valor financeiro |

Confira o Chain ID e o RPC na [documentação de rede da Base](https://docs.base.org/get-started/connect-to-base). Mesmo que o endereço da carteira seja o mesmo, os saldos são separados em redes diferentes. Não registre o sucesso na rede de testes como receita real.

Você pode solicitar USDC de teste no [Circle Testnet Faucet](https://faucet.circle.com/). Selecione Base Sepolia como rede. No endereço de recebimento, informe o endereço da carteira de teste usada para pagar.

## Implementação de uma API paga com Node.js

Conecte `paymentMiddleware` antes da rota paga. O exemplo abaixo exige **0.001 USDC** por chamada. O valor usa o preço de exemplo do guia oficial para vendedores. (Valor conferido: 0.001 USDC por chamada · fonte: docs.x402.org · verificado em 2026-10-28)

### Arquivo do servidor

Salve o código a seguir como `server.ts`. O servidor recebe requisições apenas na interface local. O endereço de recebimento é lido da variável de ambiente `PAY_TO`.

```typescript
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` é o endereço de teste do guia oficial. Neste exemplo, ele é usado para a liquidação na Base Sepolia. Para escolher um facilitador para produção, consulte o [procedimento para a rede principal no guia para vendedores](https://docs.x402.org/getting-started/quickstart-for-sellers#running-on-mainnet).

### Exemplo de cálculo do preço

O preço do exemplo corresponde a `1000` unidades mínimas de USDC. O USDC tem 6 casas decimais. A conversão de preço do SDK se baseia na [implementação do servidor EVM](https://github.com/x402-foundation/x402/blob/main/typescript/packages/mechanisms/evm/src/exact/server/scheme.ts).

```text
0.001 USDC × 10^6 = 1000 최소 단위
```

| Valor a verificar | Valor esperado neste exemplo |
|---|---|
| `price` na configuração do servidor | `"$0.001"` |
| `amount` nas condições de pagamento da resposta 402 | `"1000"` |
| `asset` nas condições de pagamento | Contrato USDC da Base Sepolia |
| `payTo` nas condições de pagamento | Endereço de recebimento configurado |
| `network` nas condições de pagamento | `eip155:84532` |

`price` é um valor de configuração do SDK. Nas condições de pagamento efetivas da v2, o campo enviado é `amount`. Compare valores inteiros como strings ou `bigint`.

### Execução do servidor e verificação da resposta 402

Execute o servidor no primeiro terminal Bash. O valor informado é o endereço público de recebimento, não uma chave privada. Mantenha esse terminal aberto durante a execução.

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

Envie uma requisição sem pagamento no segundo terminal. O comando abaixo não assina nenhum pagamento. Ele exibe o status HTTP e as condições de pagamento decodificadas.

```bash
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
```

A resposta normal sem pagamento é HTTP 402. Compare as condições exibidas com a tabela acima. Se o conteúdo pago for retornado imediatamente, comece corrigindo a configuração de proteção da rota.

## Seleção das condições de pagamento e implementação do cliente

Restrinja o cliente para assinar apenas as condições permitidas. Este exemplo permite somente o preço definido em USDC da Base Sepolia. O filtro de opções de pagamento usa `registerPolicy` da [implementação oficial de x402Client](https://github.com/x402-foundation/x402/blob/main/typescript/packages/core/src/client/x402Client.ts).

1. Salve o código abaixo como `client.ts`.
2. Salve também o arquivo `check-transfer.ts` da próxima seção.
3. Depois de preparar os dois arquivos, siga as etapas de execução.

```typescript
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` cuida do tratamento da resposta 402 e do reenvio da requisição com assinatura. O uso segue o [exemplo oficial de fetch](https://github.com/x402-foundation/x402/tree/main/examples/typescript/clients/fetch). Se não houver condições de pagamento permitidas, a geração do pagamento é interrompida.

Este cliente também pode ser usado por agentes de IA. Porém, o limite de preço por chamada não é um limite de gasto acumulado. Gerencie separadamente o orçamento para chamadas repetidas do agente.

## Validação do evento Transfer de USDC

Confira os logs de transferência de USDC usando o hash da transação retornado no resultado da liquidação. O status de sucesso da transação, por si só, não confirma o destinatário. Os campos de `Transfer` seguem o [padrão ERC-20](https://eips.ethereum.org/EIPS/eip-20).

A validação exige os seguintes itens.

| Item de validação | Referência para comparação |
|---|---|
| Chain ID do RPC | Rede permitida pelo servidor |
| `status` do recibo da transação | Estado de sucesso |
| Endereço que emitiu o evento | Contrato oficial de USDC nessa rede |
| `Transfer.from` | Pagador confirmado |
| `Transfer.to` | Endereço de recebimento definido pelo servidor |
| `Transfer.value` | Valor em unidades mínimas exigido pelo servidor |

Salve o código abaixo como `check-transfer.ts`. A consulta usa [getTransactionReceipt](https://viem.sh/docs/actions/public/getTransactionReceipt) do viem. A interpretação dos eventos se baseia em [parseEventLogs](https://viem.sh/docs/contract/parseEventLogs).

```typescript
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(),
  };
}
```

Essa função confirma que houve uma transferência de USDC na transação em questão. É preciso verificar separadamente se ela está vinculada a um pedido específico da API. No servidor de produção, use as condições do pedido armazenadas como referência para comparação.

Não confie no `transfer.json` enviado pelo cliente como prova para autorizar o acesso. O servidor deste exemplo usa os resultados de validação e liquidação do facilitador. Se quiser usar uma consulta independente como condição de autorização de acesso, ela deve ser executada no servidor.

Uma falha na consulta do recibo não significa necessariamente uma falha no pagamento. Se houver um erro de RPC, consulte novamente o hash da transação armazenado. Defina na política operacional o número de confirmações adicionais e o tratamento de reorganizações da rede.

## Execução do pagamento de teste e verificação dos resultados

Depois de salvar todos os arquivos, execute com a carteira de teste. A checagem de tipos não realiza assinaturas nem transferências. Os comandos abaixo usam as ferramentas TypeScript instaladas anteriormente.

1. Verifique os tipos com o comando a seguir.
2. No segundo terminal, informe o mesmo endereço de recebimento usado no servidor.
3. Digite a chave privada da carteira de pagamento de teste com a entrada oculta.
4. Execute o cliente uma vez.
5. Confira o resultado da liquidação e o log de transferência salvos.

```bash
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 | O que verificar |
|---|---|---|
| `settlement.json` | Resultado da liquidação retornado pelo servidor | `success`, `network`, `transaction` |
| `transfer.json` | Registro de transferência encontrado na consulta RPC | Rede, hash da transação, posição do log, informações do bloco |
| Corpo pago no console | Dados exibidos após a validação deste cliente | Verificar se é o conteúdo solicitado |

Uma nova execução do cliente pode gerar um novo pagamento. Este exemplo mínimo não tem armazenamento para impedir duplicações por pedido. Adicione a funcionalidade de novas tentativas somente depois de atender às condições da próxima seção.

## Tratamento por condição de falha de validação

Nos testes de falha, confirme que o corpo pago não é exposto. Verificar apenas o status HTTP pode deixar passar uma falha no bloqueio. Consulte o [middleware oficial para Express](https://github.com/x402-foundation/x402/blob/main/typescript/packages/http/express/src/index.ts) como referência de comportamento.

| Condição de teste | Tratamento esperado | Verificação adicional |
|---|---|---|
| Ausência do cabeçalho de pagamento | Retornar 402 e as condições de pagamento | Sem corpo pago |
| Apresentação de outro token ou destinatário | Rejeitar pela política do cliente | Não gerar assinatura |
| Assinatura inválida | Bloquear por falha de validação | Não executar o manipulador da rota paga |
| Saldo insuficiente | Bloquear por falha de validação ou liquidação | Não registrar a liquidação como bem-sucedida |
| Resultado de liquidação com falha | Bloquear a resposta paga | Não enviar nem mesmo o corpo já preparado |
| Atraso na resposta do facilitador | Manter pendente, sem confirmação de sucesso | Não gerar automaticamente uma nova autorização |
| Erro na consulta do recibo por RPC | Preservar o hash da transação e consultar novamente | Não concluir que o pagamento falhou |

No fluxo básico de autorização, o manipulador é executado antes da liquidação. Uma falha na liquidação não desfaz operações externas. Comece aplicando a consultas sem efeitos colaterais, como neste exemplo.

O envio de e-mails ou a criação de pedidos externos exige um projeto separado. Registre juntos os estados do pagamento e da operação. Defina o que será reexecutado em caso de falha para reduzir operações duplicadas.

## Perda da resposta após a liquidação e recuperação por reenvio

Armazene a conclusão do pagamento e a conclusão da entrega do conteúdo como estados separados. O pagamento pode ser concluído, mas a conexão da resposta pode cair. A referência para tratar essa situação é a [documentação da extensão Payment-Identifier](https://docs.x402.org/extensions/payment-identifier).

A propriedade de não duplicar o processamento quando a mesma operação é solicitada novamente se chama idempotência. `payment-identifier` fornece um identificador de pagamento para isso. Não é uma funcionalidade que fica pronta automaticamente apenas com a adição do identificador.

### Comparação entre pagamento duplicado e reenvio

É preciso distinguir a prevenção da reutilização da mesma assinatura da prevenção de pedidos duplicados. EIP-3009 impede a reutilização de um nonce de autorização já usado. Esse comportamento está definido na [especificação ERC-3009](https://eips.ethereum.org/EIPS/eip-3009).

| Situação | Perspectiva da autorização on-chain | Perspectiva da operação da API |
|---|---|---|
| Liquidar novamente a mesma autorização | Sujeita à verificação de nonce já utilizado | É necessário consultar o resultado existente |
| Gerar uma nova autorização para o mesmo pedido | Pode ser tratada como uma autorização separada | É necessário impedir o pagamento duplicado |
| Perda da resposta após o sucesso da liquidação | A movimentação dos ativos pode estar concluída | É necessário entregar o conteúdo novamente |
| Tempo limite após a solicitação de liquidação | O resultado ainda é incerto | É necessário manter um estado pendente e verificar a liquidação |

O procedimento a seguir é uma proposta de projeto para conectar a extensão oficial ao armazenamento de produção. Ele não está incluído no código mínimo anterior. Para aplicá-lo em produção, adicione armazenamento persistente e controle de requisições simultâneas.

1. Declare no servidor o suporte à extensão `payment-identifier`.
2. Preserve no cliente o identificador da requisição lógica.
3. No servidor, vincule o identificador ao pagador e ao conteúdo da requisição.
4. Registre atomicamente o estado de processamento para impedir execuções simultâneas.
5. Quando a liquidação tiver sucesso, salve as evidências da transação e o resultado da resposta.
6. Se a autorização e o conteúdo da nova requisição forem os mesmos, retorne o resultado armazenado.
7. Se o resultado da liquidação for incerto, verifique primeiro a autorização existente.

O identificador de pagamento não é uma senha nem um token de acesso. Não retorne o cache pago para uma requisição que apenas conheça o identificador. Verifique também se ele está sendo reutilizado por outro usuário ou com outro corpo de requisição.

Nos registros operacionais, armazene juntos a rede, o hash da transação e a posição do log. Vincule esse registro ao pedido para impedir sua reutilização em outros pedidos. A correspondência de `Transfer`, por si só, não comprova o vínculo com o pedido.

## Erros comuns na implementação de pagamentos

Confundir campos de versão e sinais de sucesso leva a avaliações incorretas do pagamento. Use a tabela abaixo na revisão antes da implantação. As diferenças entre versões se baseiam no [guia de migração do x402](https://docs.x402.org/guides/migration-v1-to-v2).

| Erro comum | Critério correto |
|---|---|
| Interpretar `extra.version: "2"` como a versão do x402 | Verificar a versão do protocolo em `x402Version` |
| Usar `maxAmountRequired` na v2 | Usar `amount` para o valor nas condições de pagamento |
| Criar arbitrariamente o cabeçalho `X-PAYMENT-REQUIRED` | Na v1, usar o corpo; na v2, usar `PAYMENT-REQUIRED` |
| Tratar `isValid: true` como recebimento concluído | Verificar separadamente o resultado de `/settle` |
| Tratar o `to` de nível superior da transação como destinatário do USDC | Verificar `Transfer.to` do USDC |
| Presumir que o signatário é o mesmo que envia a transação | Comparar o pagador da autorização com `Transfer.from` |
| Somar os valores recebidos na rede de testes à receita | Separar os registros da rede principal e da rede de testes |
| Gerar um novo pagamento a cada tempo limite | Recuperar primeiro o pedido existente e o estado da autorização |
| Equiparar a versão do pacote SDK à versão do protocolo | Gerenciar separadamente a versão do pacote e `x402Version` |

As informações de domínio da assinatura do USDC também contêm uma string de versão. Esse valor tem uma finalidade diferente da versão do protocolo x402. Consulte a estrutura do domínio de assinatura na [especificação ERC-3009](https://eips.ethereum.org/EIPS/eip-3009).

## Verificação de segurança e limites de confiança em serviços externos

Controle no servidor a determinação de sucesso do pagamento. A resposta de um facilitador externo também exige uma decisão explícita de confiança. A estrutura que permite operar um facilitador próprio está descrita na [documentação do facilitador](https://github.com/x402-foundation/x402/blob/main/docs/core-concepts/facilitator.md).

- Não libere conteúdo com base na mensagem de sucesso do cliente.
- Compare a rede, o token, o valor e o destinatário declarados pelo servidor.
- Não registre chaves privadas nem frases-semente nos logs.
- Exclua também as assinaturas completas de autorização dos logs comuns de acesso.
- Limite o tamanho dos cabeçalhos de pagamento e o tempo de processamento das requisições.
- Verifique se as respostas pagas não ficam armazenadas em caches compartilhados.
- Separe os locais de armazenamento das chaves de teste e de produção.
- Não crie uma rota alternativa sem pagamento quando o facilitador falhar.
- Teste na prática a expiração das autorizações e as requisições duplicadas.

As dependências com versões fixadas nesta prática ainda apresentam alertas de verificação de segurança. `npm audit` relatou um aviso relacionado ao zod. Consulte os detalhes no [aviso de segurança do GitHub](https://github.com/advisories/GHSA-mrhx-c7xc-m3w5).

```bash
npm audit
```

Antes da implantação em produção, verifique a compatibilidade do SDK na versão corrigida. Forçar a troca de uma versão principal pode alterar o comportamento. Não use esta prática como uma configuração de implantação com validação de segurança concluída.

### Comparação entre servidor próprio e Cloudflare Gateway

Ao usar o Cloudflare Gateway, a forma de validação no servidor de origem muda. A documentação de 30 de setembro de 2026 especifica o uso de x402 v2. A comparação a seguir se baseia na [documentação de x402 da Cloudflare](https://developers.cloudflare.com/monetization-gateway/x402/).

| Aspecto | Abordagem com Express deste artigo | Cloudflare Monetization Gateway |
|---|---|---|
| Processamento do pagamento do cliente | Middleware Express | Gateway |
| Ponto de validação no servidor de origem | Integração com o facilitador escolhido | Validação do JWT `PAYMENT-CONTEXT` |
| Entrega do resultado da liquidação | `PAYMENT-RESPONSE` do middleware | O Gateway gera o recibo de liquidação |
| Verificações adicionais | Redes compatíveis com o facilitador e autenticação | Validação da assinatura JWT e proteção do acesso à origem |

`PAYMENT-CONTEXT` é um cabeçalho entre o Gateway e o servidor de origem. Não é o cabeçalho de assinatura de um cliente x402 comum. Para validar na origem, siga a [documentação Cloudflare Payment validation](https://developers.cloudflare.com/monetization-gateway/configuration/payment-validation/).

Mesmo quando a requisição passa pelo Gateway, não basta decodificar o JWT. Valide a assinatura com a chave indicada na documentação. Se o cabeçalho estiver ausente ou a validação falhar, bloqueie o conteúdo pago.

## Distinção entre uso real e registros de liquidação

A quantidade de transferências on-chain, por si só, não comprova o consumo de conteúdo. Agregue as métricas operacionais vinculando a liquidação à entrega da resposta. Esta é uma proposta de projeto baseada no fluxo de pagamento e no comportamento de reenvio.

| Registro | Pergunta que permite responder | Registro adicional necessário |
|---|---|---|
| Resposta 402 | Quantas vezes as condições de pagamento foram solicitadas | Se houve pagamento de fato |
| Validação bem-sucedida | Se a autorização era válida | Resultado da liquidação |
| Transferência de USDC | Se houve movimentação de ativos | Vínculo com o pedido |
| Liquidação concluída por pedido | Se a requisição paga foi paga | Estado de entrega da resposta |
| Registro de nova entrega | Se uma requisição já paga foi recuperada | Identificador que a distinga de um novo pagamento |

Separe as requisições de teste na apuração do uso real. Identifique também as novas tentativas do mesmo pedido separadamente. Não apresente o volume de transações, por si só, como demanda pela API ou garantia de receita.

## Procedimento de migração para a rede principal da Base

Considere a rede principal depois de verificar os caminhos de sucesso e de falha na rede de testes. Alterar apenas a string de rede não conclui a migração. O procedimento de referência segue o [guia oficial para vendedores](https://docs.x402.org/getting-started/quickstart-for-sellers#running-on-mainnet).

1. Verifique se o facilitador escolhido oferece suporte à rede principal da Base.
2. Em `/supported`, verifique o suporte a v2, `exact` e `eip155:8453`.
3. Configure a autenticação e as condições de uso exigidas pelo provedor.
4. Altere a rede no servidor e no cliente em conjunto.
5. Altere o endereço USDC permitido no cliente para o endereço da rede principal.
6. Confira novamente o valor da resposta 402 e o endereço real de recebimento.
7. Integre o armazenamento para requisições duplicadas e os procedimentos de recuperação de falhas.
8. Conclua a verificação de segurança das dependências de produção.
9. Confirme a transferência real e a entrega do conteúdo com o pequeno valor configurado.

O suporte a múltiplas redes não significa suporte a todas as combinações. Verifique em conjunto o escopo de suporte do SDK e do facilitador. A referência é a [documentação de suporte a redes e tokens](https://docs.x402.org/core-concepts/network-and-token-support).

## FAQ

### Em que o x402 difere da confirmação de um depósito comum em USDC?
Durante a solicitação HTTP, são enviadas as condições de pagamento, e a solicitação é reenviada com uma autorização de pagamento assinada. Diferentemente do método de conferir os registros de depósito posteriormente, esse processo vincula o procedimento de pagamento à solicitação de um recurso pago.

### Quais são os cabeçalhos de pagamento do x402 v2?
As condições de pagamento são enviadas em PAYMENT-REQUIRED, e o payload de pagamento, em PAYMENT-SIGNATURE. O resultado da liquidação é enviado em PAYMENT-RESPONSE.

### Existe um cabeçalho X-PAYMENT-REQUIRED na v1?
A especificação oficial HTTP v1 inclui as condições iniciais de pagamento no corpo da resposta JSON. Para o payload de pagamento e o resultado da liquidação, são usados, respectivamente, X-PAYMENT e X-PAYMENT-RESPONSE.

### Se /verify for bem-sucedido, o pagamento estará concluído?
O sucesso de /verify significa que a autorização de pagamento é válida. Neste exercício, é necessário verificar separadamente o resultado bem-sucedido de /settle.

### O USDC de teste da Base Sepolia pode ser considerado receita real?
A Circle declara que o USDC da rede de testes não tem valor financeiro. Registre as liquidações da rede de testes separadamente das vendas reais.

### É necessário colocar uma chave privada no servidor recebedor?
No servidor recebedor deste exemplo, configura-se apenas o endereço público de recebimento. A chave privada usada para autorizar o pagamento é lida pelo cliente de pagamento.

### Qual é o valor de amount para 0.001 USDC?
Aplicando as 6 casas decimais do USDC, o valor na menor unidade é 1000. Nas condições de pagamento da v2, use a string "1000".

### Se o recibo da transação indicar sucesso, o recebimento de USDC também estará confirmado?
O status de sucesso da transação, por si só, não é suficiente. Confira o pagador, o recebedor e o valor no evento Transfer do contrato oficial do USDC.

### É seguro reenviar a mesma solicitação de pagamento?
A prevenção da reutilização do nonce de uma mesma autorização e a prevenção de pedidos duplicados são questões distintas. Antes de tentar novamente, verifique o status do pagamento existente e implemente o tratamento de idempotência por pedido.

### Se não houver PAYMENT-RESPONSE, basta pagar novamente?
Se houver perda da resposta ou tempo limite excedido, o resultado da liquidação pode não estar claro. Não comece criando uma nova autorização; verifique o status da liquidação da solicitação existente.

### O x402 exige o uso do facilitator de uma empresa específica?
A estrutura oficial permite tanto o uso de um facilitator externo quanto a operação própria. Verifique se a implementação escolhida oferece suporte à versão do protocolo, à forma de pagamento e à blockchain necessárias.

### Os gastos de um agente de IA também são limitados automaticamente?
Este exemplo limita apenas as condições de pagamento de cada solicitação. Gerencie os gastos acumulados por chamadas repetidas com uma política de orçamento separada.

### O PAYMENT-CONTEXT da Cloudflare é um cabeçalho padrão de assinatura de pagamento?
PAYMENT-CONTEXT é um JWT que o Gateway encaminha ao servidor de origem. Sua finalidade é diferente da do PAYMENT-SIGNATURE do cliente.

### Posso implantar o exemplo diretamente na rede principal?
Este código tem uma configuração mínima para testes. Antes da implantação em produção, verifique os alertas de segurança das dependências, o tratamento de solicitações duplicadas, a autenticação do facilitador e a liquidação real.

## Sources

- [Especificação do protocolo x402 v2](https://github.com/x402-foundation/x402/blob/main/specs/x402-specification-v2.md)
- [Transporte HTTP do x402 v1](https://github.com/x402-foundation/x402/blob/main/specs/transports-v1/http.md)
- [Transporte HTTP do x402 v2](https://github.com/x402-foundation/x402/blob/main/specs/transports-v2/http.md)
- [Guia de migração do x402: de V1 para V2](https://docs.x402.org/guides/migration-v1-to-v2)
- [Papel e responsabilidades do facilitador x402](https://github.com/x402-foundation/x402/blob/main/docs/core-concepts/facilitator.md)
- [Guia de início rápido do x402 para vendedores](https://docs.x402.org/getting-started/quickstart-for-sellers)
- [Guia de início rápido do x402 para compradores](https://docs.x402.org/getting-started/quickstart-for-buyers)
- [Exemplo oficial de cliente fetch do x402 em TypeScript](https://github.com/x402-foundation/x402/tree/main/examples/typescript/clients/fetch)
- [Implementação de middleware Express para x402](https://github.com/x402-foundation/x402/blob/main/typescript/packages/http/express/src/index.ts)
- [Seleção de condições de pagamento e implementação de políticas no x402Client](https://github.com/x402-foundation/x402/blob/main/typescript/packages/core/src/client/x402Client.ts)
- [Implementação da conversão de preços no servidor x402 ExactEvmScheme](https://github.com/x402-foundation/x402/blob/main/typescript/packages/mechanisms/evm/src/exact/server/scheme.ts)
- [Endereço do contrato USDC da Circle](https://developers.circle.com/stablecoins/usdc-contract-addresses)
- [Informações sobre a rede principal Base e a rede Base Sepolia](https://docs.base.org/get-started/connect-to-base)
- [Faucet da rede de testes da Circle](https://faucet.circle.com/)
- [viem getTransactionReceipt](https://viem.sh/docs/actions/public/getTransactionReceipt)
- [viem parseEventLogs](https://viem.sh/docs/contract/parseEventLogs)
- [Padrão de token ERC-20](https://eips.ethereum.org/EIPS/eip-20)
- [ERC-3009 Transferência com autorização](https://eips.ethereum.org/EIPS/eip-3009)
- [Extensão de idempotência Payment-Identifier do x402](https://docs.x402.org/extensions/payment-identifier)
- [Protocolo x402 do Cloudflare Monetization Gateway](https://developers.cloudflare.com/monetization-gateway/x402/)
- [Validação de pagamentos do Cloudflare Monetization Gateway](https://developers.cloudflare.com/monetization-gateway/configuration/payment-validation/)
- [Redes e suporte a tokens do x402](https://docs.x402.org/core-concepts/network-and-token-support)
- [Alerta de segurança do GitHub: esgotamento de memória devido à validação de grandes coleções pelo Zod](https://github.com/advisories/GHSA-mrhx-c7xc-m3w5)

## Images

![Um homem de suéter cinza-escuro examina um tablet apoiado na prateleira de um rack de servidores.](https://injoys.com/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzM4MDcsInB1ciI6ImJsb2JfaWQifX0=--49c502fd8da16158a617c3586dfa81ced4bc95df/ai-f0ae2b5c.webp)
![Uma mulher digita num notebook aberto na horizontal, com uma lista e duas rotas convergentes na tela.](https://injoys.com/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzM4MTMsInB1ciI6ImJsb2JfaWQifX0=--4e70727f132519277c68d1c6279d95585a936549/ai-3dbd1c62.webp)