---
title: "x402-Zahlungen 2026: v2 umsetzen und Abrechnung prüfen"
locale: de
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-Zahlungen 2026: v2 umsetzen und Abrechnung prüfen

> In dieser Node.js-Praxisübung erweitern Sie eine API mit x402 v2 um Mikrozahlungen. Wählen Sie auf Base Sepolia Zahlungsbedingungen aus, fordern Sie Signaturen erneut an und prüfen Sie die Abrechnung. Prüfen Sie außerdem erneute Übertragungen und die Voraussetzungen für den Wechsel ins Mainnet.

## Key Points

- Bereiten Sie die Empfängeradresse und eine Wallet für Testzahlungen vor und installieren Sie das offizielle x402 SDK.
- Binden Sie die Zahlungs-Middleware für Base Sepolia ein und prüfen Sie die 402-Antwort auf eine Anfrage ohne Zahlung.
- Wählen Sie nur Zahlungsbedingungen aus, die den clientseitig erlaubten Werten für Chain, Token, Betrag und Empfänger entsprechen, und signieren Sie diese.
- Rufen Sie anhand des Transaktionshashs aus der Abrechnungsantwort die USDC Transfer-Ereignisse ab.
- Testen Sie das Blockieren bei Fehlern und die Wiederherstellung nach doppelten Anfragen, bevor Sie die Mainnet-Einstellungen prüfen.

x402-Zahlungen werden implementiert, indem die Zahlungsbedingungen in der 402-Antwort der API übermittelt werden. Bereiten Sie Node.js und eine Test-Wallet vor. Prüfen Sie zunächst Signaturen und Abwicklung für v2 auf Base Sepolia. Konfigurieren Sie die kostenpflichtige Antwort so, dass sie erst nach erfolgreicher Abwicklung ausgeliefert wird.

Die Angaben zu Beträgen und Chains beruhen auf den als Quellen verlinkten offiziellen Dokumentationen von x402, Base und Circle.

## Vorbereitung und Installation

Bereiten Sie eine Entwicklungsumgebung vor, in der Sie die API ändern können, sowie eine Test-Wallet. Das Beispiel basiert auf Node.js 22 und x402 SDK 2.28.0. Der Installationsaufbau folgt dem [offiziellen Verkäuferleitfaden](https://docs.x402.org/getting-started/quickstart-for-sellers).

1. Halten Sie eine EVM-Wallet-Adresse für den Zahlungsempfang bereit.
2. Bereiten Sie eine separate Test-Wallet für Zahlungen vor.
3. Beschaffen Sie Base Sepolia Test-USDC für die Zahlungs-Wallet.
4. Erstellen Sie das Übungsprojekt mit den folgenden Befehlen.
5. Speichern Sie die nachfolgenden TypeScript-Dateien im selben Ordner.

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

Der empfangende Server benötigt den privaten Schlüssel der Empfänger-Wallet nicht. Konfigurieren Sie den privaten Zahlungsschlüssel so, dass er nur vom Client-Prozess gelesen wird. Das Signaturverfahren der Wallet richtet sich nach dem [offiziellen Käuferleitfaden](https://docs.x402.org/getting-started/quickstart-for-buyers).

Dieses Beispiel wurde durch Typprüfung und einen simulierten Zahlungsablauf geprüft. Eine tatsächliche Überweisung im Testnetz wurde damit noch nicht abgeschlossen. Prüfen Sie die Onchain-Ergebnisse bei der unten beschriebenen Ausführung selbst.

## Vergleich von x402 v1 und v2

Bei der Implementierung von v2 müssen Header und Felder im Body aufeinander abgestimmt sein. Wenn Sie nur die Header-Namen ändern, passt die Datenstruktur nicht. Die folgende Tabelle basiert auf dem [offiziellen Migrationsleitfaden](https://docs.x402.org/guides/migration-v1-to-v2).

| Merkmal | v1 | v2 |
|---|---|---|
| Protokollversion | `x402Version: 1` | `x402Version: 2` |
| Anfängliche Zahlungsbedingungen | JSON-Body der 402-Antwort | Antwortheader `PAYMENT-REQUIRED` |
| Signierte Zahlungsdaten | Anfrageheader `X-PAYMENT` | Anfrageheader `PAYMENT-SIGNATURE` |
| Abwicklungsergebnis | Antwortheader `X-PAYMENT-RESPONSE` | Antwortheader `PAYMENT-RESPONSE` |
| Kennung für Base Mainnet | `base` | `eip155:8453` |
| Kennung für Base Sepolia | `base-sepolia` | `eip155:84532` |
| Betragsfeld der Zahlungsbedingungen | `maxAmountRequired` | `amount` |
| Ressourcenbeschreibung | `resource` usw. innerhalb der Zahlungsbedingungen | `resource`-Objekt auf oberster Ebene |
| Bedingungen in der Zahlungs-Payload | `scheme`, `network` usw. auf oberster Ebene | `accepted`-Objekt mit den ausgewählten Bedingungen |
| Beispiel für ein TypeScript-Paket | `x402-express` | `@x402/express` |

Wo v1 die Zahlungsbedingungen übermittelt, ist in der [HTTP-v1-Spezifikation](https://github.com/x402-foundation/x402/blob/main/specs/transports-v1/http.md) festgelegt. Bei v2 ist der Header `PAYMENT-REQUIRED` der standardmäßige Übermittlungsort. Eine Implementierung kann zusätzlich einen Body zurückgeben; richten Sie die Verarbeitung jedoch nach dem Header aus.

Die [HTTP-v2-Spezifikation](https://github.com/x402-foundation/x402/blob/main/specs/transports-v2/http.md) beschreibt den Statuscode wie folgt.

> Der Server zeigt mit dem HTTP-Statuscode 402 „Payment Required“ an, dass eine Zahlung erforderlich ist.
>
> Quelle: x402 HTTP-v2-Spezifikation

Die Zahlungsheader von v2 enthalten Base64-kodiertes JSON. Base64 ist kein Verschlüsselungsverfahren. Verwenden Sie HTTPS für extern zugängliche Dienste.

## HTTP-402-Anfrage und Zahlungsablauf

Diese Übung verwendet den grundlegenden Autorisierungsablauf des EVM-Verfahrens `exact`. Bei `exact` wird ein festgelegter Betrag bezahlt. Der Ablauf folgt der [Kernspezifikation von x402 v2](https://github.com/x402-foundation/x402/blob/main/specs/x402-specification-v2.md).

1. Der Client ruft die kostenpflichtige API ohne Zahlungsinformationen auf.
2. Der Server gibt HTTP 402 und `PAYMENT-REQUIRED` zurück.
3. Der Client wählt zulässige Bedingungen aus `accepts` aus.
4. Das SDK signiert eine Zahlungsautorisierung für die ausgewählten Bedingungen.
5. Der Client wiederholt die Anfrage mit `PAYMENT-SIGNATURE`.
6. Der Server prüft die Autorisierung über `/verify` des Facilitators.
7. Nach erfolgreicher Prüfung führt der Server die Ressourcenverarbeitung aus.
8. Der Server fordert über `/settle` die Abwicklung an.
9. Nach erfolgreicher Abwicklung liefert er den kostenpflichtigen Body und `PAYMENT-RESPONSE` aus.

Diese Reihenfolge ist kein festgelegter Ablauf für alle Zahlungsverfahren. v2 definiert auch Abläufe mit einem anderen Abwicklungszeitpunkt. Der folgende Code lässt nur den grundlegenden Ablauf `authorization` zu.

### Rollen von Ressourcenserver und Facilitator

Der Ressourcenserver legt Preise und Zugangsbedingungen für Inhalte fest. Der Facilitator übernimmt die Zahlungsprüfung und Abwicklung. Die Rollenverteilung richtet sich nach der [offiziellen Facilitator-Dokumentation](https://github.com/x402-foundation/x402/blob/main/docs/core-concepts/facilitator.md).

| Komponente | Aufgabe | Zustand, der nicht als Erfolg gelten darf |
|---|---|---|
| Client | Bedingungen auswählen und Zahlungsautorisierung signieren | Nur die Signatur wurde erstellt |
| Ressourcenserver | Preis angeben und kostenpflichtige Antworten steuern | Der Client behauptet, die Zahlung sei erfolgreich |
| Facilitator `/verify` | Gültigkeit von Signatur und Zahlungsbedingungen prüfen | Es wurde lediglich `isValid: true` empfangen |
| Facilitator `/settle` | In dieser Übung die Onchain-Zahlung ausführen und das Ergebnis zurückgeben | Die Transaktion wurde gesendet, das Ergebnis aber noch nicht bestätigt |

`/verify` ist eine Prüfung, die den Onchain-Zustand nicht verändert. Eine erfolgreiche Prüfung bedeutet daher nicht, dass der Zahlungseingang abgeschlossen ist. Guthaben oder Autorisierungsstatus können sich auch nach der Prüfung noch ändern.

Sperren Sie den kostenpflichtigen Body, wenn Prüfung oder Abwicklung fehlschlagen. Ein Vorgehen, das den Zugriff sperrt, solange kein Erfolg bestätigt ist, wird als fail-closed bezeichnet. Dieses Verhalten lässt sich auch in der [offiziellen Express-Implementierung](https://github.com/x402-foundation/x402/blob/main/typescript/packages/http/express/src/index.ts) nachvollziehen.

## Vergleich von Base Mainnet und Testnetz

Verwenden Sie beim ersten Durchlauf ausschließlich Base Sepolia. Circle stellt ausdrücklich fest, dass USDC im Testnetz keinen finanziellen Wert haben. Die Adressen stammen aus der [Liste der USDC-Contract-Adressen von Circle](https://developers.circle.com/stablecoins/usdc-contract-addresses).

| Merkmal | Base Mainnet | Base Sepolia Testnetz |
|---|---|---|
| Zweck | Zahlungen mit realen Vermögenswerten | Implementierung und Fehlerbehandlung testen |
| Chain ID | `8453` | `84532` |
| Netzwerk für x402 v2 | `eip155:8453` | `eip155:84532` |
| USDC-Contract | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | `0x036CbD53842c5426634e7929541eC2318f3dCF7e` |
| Öffentlicher RPC | `https://mainnet.base.org` | `https://sepolia.base.org` |
| Finanzieller Wert des Tokens | Vermögenswert mit realem finanziellem Wert | Kein finanzieller Wert |

Prüfen Sie Chain ID und RPC in der [Base-Netzwerkdokumentation](https://docs.base.org/get-started/connect-to-base). Auch bei derselben Wallet-Adresse sind die Guthaben auf unterschiedlichen Chains getrennt. Ein Erfolg im Testnetz darf nicht als tatsächlicher Umsatz verbucht werden.

Test-USDC können Sie beim [Circle Testnet Faucet](https://faucet.circle.com/) anfordern. Wählen Sie Base Sepolia als Netzwerk. Geben Sie als Empfängeradresse die Adresse der Test-Wallet für Zahlungen ein.

## Kostenpflichtige API mit Node.js implementieren

Schalten Sie `paymentMiddleware` vor die kostenpflichtige Route. Das folgende Beispiel verlangt **0.001 USDC** pro Aufruf. Der Betrag entspricht dem Beispielpreis aus dem offiziellen Verkäuferleitfaden. (Geprüfter Wert: 0.001 USDC pro Aufruf · Quelle: docs.x402.org · geprüft am 2026-10-28)

### Serverdatei

Speichern Sie den folgenden Code als `server.ts`. Der Server nimmt Anfragen nur über die lokale Schnittstelle an. Die Empfängeradresse wird aus der Umgebungsvariablen `PAY_TO` gelesen.

```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` ist die Testadresse aus dem offiziellen Leitfaden. In diesem Beispiel wird sie für die Abwicklung auf Base Sepolia verwendet. Informationen zur Auswahl eines Facilitators für den Produktivbetrieb finden Sie im [Mainnet-Verfahren des Verkäuferleitfadens](https://docs.x402.org/getting-started/quickstart-for-sellers#running-on-mainnet).

### Beispiel zur Preisberechnung

Der Beispielpreis entspricht `1000` kleinsten USDC-Einheiten. USDC hat 6 Nachkommastellen. Die Preisumrechnung des SDK richtet sich nach der [EVM-Serverimplementierung](https://github.com/x402-foundation/x402/blob/main/typescript/packages/mechanisms/evm/src/exact/server/scheme.ts).

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

| Zu prüfender Wert | Erwarteter Wert in diesem Beispiel |
|---|---|
| `price` in der Serverkonfiguration | `"$0.001"` |
| `amount` in den Zahlungsbedingungen der 402-Antwort | `"1000"` |
| `asset` in den Zahlungsbedingungen | USDC-Contract auf Base Sepolia |
| `payTo` in den Zahlungsbedingungen | Konfigurierte Empfängeradresse |
| `network` in den Zahlungsbedingungen | `eip155:84532` |

`price` ist ein Konfigurationswert des SDK. In den tatsächlichen Zahlungsbedingungen von v2 wird `amount` übermittelt. Vergleichen Sie ganzzahlige Beträge als Zeichenfolgen oder `bigint`.

### Server starten und 402 prüfen

Starten Sie den Server im ersten Bash-Terminal. Der eingegebene Wert ist die öffentliche Empfängeradresse, nicht der private Schlüssel. Lassen Sie dieses Terminal während der Ausführung geöffnet.

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

Senden Sie aus einem zweiten Terminal eine Anfrage ohne Zahlung. Der folgende Befehl signiert keine Zahlung. Er gibt den HTTP-Status und die dekodierten Zahlungsbedingungen aus.

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

Die reguläre Antwort ohne Zahlung ist HTTP 402. Vergleichen Sie die ausgegebenen Bedingungen mit der obigen Tabelle. Falls die kostenpflichtigen Inhalte direkt zurückgegeben werden, korrigieren Sie zuerst den Schutz der Route.

## Zahlungsbedingungen auswählen und Client implementieren

Beschränken Sie den Client darauf, nur erlaubte Bedingungen zu signieren. Dieses Beispiel erlaubt ausschließlich den festgelegten Preis in USDC auf Base Sepolia. Der Filter für Zahlungsoptionen verwendet `registerPolicy` aus der [offiziellen x402Client-Implementierung](https://github.com/x402-foundation/x402/blob/main/typescript/packages/core/src/client/x402Client.ts).

1. Speichern Sie den folgenden Code als `client.ts`.
2. Speichern Sie auch `check-transfer.ts` aus dem nächsten Abschnitt.
3. Fahren Sie erst mit der Ausführung fort, wenn beide Dateien vorliegen.

```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` übernimmt die Verarbeitung von 402 und die erneute Anfrage mit Signatur. Die Verwendung folgt dem [offiziellen fetch-Beispiel](https://github.com/x402-foundation/x402/tree/main/examples/typescript/clients/fetch). Wenn keine erlaubten Zahlungsbedingungen vorliegen, wird die Erstellung der Zahlung abgebrochen.

Dieser Client kann auch in KI-Agenten verwendet werden. Eine Preisgrenze pro Aufruf ist jedoch keine Grenze für die Gesamtausgaben. Verwalten Sie das Budget für wiederholte Aufrufe des Agenten separat.

## USDC-Transfer-Ereignisse prüfen

Prüfen Sie die USDC-Transfer-Logs anhand des Transaktionshashs aus dem Abwicklungsergebnis. Ein erfolgreicher Transaktionsstatus allein bestätigt noch nicht den Empfänger. Die Felder von `Transfer` richten sich nach dem [ERC-20-Standard](https://eips.ethereum.org/EIPS/eip-20).

Für die Prüfung werden folgende Angaben benötigt.

| Prüfpunkt | Vergleichswert |
|---|---|
| Chain ID des RPC | Vom Server zugelassene Chain |
| `status` des Transaktionsbelegs | Erfolgsstatus |
| Adresse, die das Ereignis ausgelöst hat | Offizieller USDC-Contract der betreffenden Chain |
| `Transfer.from` | Bestätigter Zahler |
| `Transfer.to` | Vom Server festgelegte Empfängeradresse |
| `Transfer.value` | Vom Server verlangter Betrag in kleinsten Einheiten |

Speichern Sie den folgenden Code als `check-transfer.ts`. Die Abfrage verwendet [getTransactionReceipt](https://viem.sh/docs/actions/public/getTransactionReceipt) von viem. Die Auswertung der Ereignisse richtet sich nach [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(),
  };
}
```

Diese Funktion bestätigt den USDC-Transfer in der betreffenden Transaktion. Ob er einem bestimmten API-Auftrag zugeordnet ist, muss separat geprüft werden. Verwenden Sie auf einem Produktivserver die gespeicherten Auftragsbedingungen als Vergleichswerte.

Vertrauen Sie einer vom Client hochgeladenen Datei `transfer.json` nicht als Nachweis für die Zugangsberechtigung. Der Server dieses Beispiels verwendet die Prüf- und Abwicklungsergebnisse des Facilitators. Soll eine unabhängige Abfrage Voraussetzung für den Zugriff sein, muss sie auf dem Server ausgeführt werden.

Eine fehlgeschlagene Belegabfrage bedeutet nicht automatisch, dass die Zahlung fehlgeschlagen ist. Fragen Sie bei einem RPC-Fehler den gespeicherten Transaktionshash erneut ab. Die Anzahl zusätzlicher Bestätigungen und der Umgang mit Chain-Reorganisationen werden in den Betriebsrichtlinien festgelegt.

## Testzahlung ausführen und Ergebnisse prüfen

Speichern Sie alle Dateien und führen Sie den Test mit der Test-Wallet aus. Die Typprüfung führt weder Signaturen noch Überweisungen aus. Der folgende Befehl verwendet die zuvor installierten TypeScript-Werkzeuge.

1. Prüfen Sie die Typen mit dem folgenden Befehl.
2. Geben Sie im zweiten Terminal dieselbe Empfängeradresse wie auf dem Server ein.
3. Geben Sie den privaten Schlüssel der Test-Zahlungs-Wallet verdeckt ein.
4. Führen Sie den Client einmal aus.
5. Prüfen Sie das gespeicherte Abwicklungsergebnis und die Transfer-Logs.

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

| Ergebnis | Bedeutung | Zu prüfen |
|---|---|---|
| `settlement.json` | Vom Server zurückgegebenes Abwicklungsergebnis | `success`, `network`, `transaction` |
| `transfer.json` | Bei der RPC-Abfrage gefundener Transferdatensatz | Chain, Transaktionshash, Log-Position, Blockinformationen |
| Kostenpflichtiger Body in der Konsole | Daten, die nach der Prüfung durch diesen Client ausgegeben wurden | Prüfen, ob es sich um die angeforderten Inhalte handelt |

Ein erneuter Start des Clients kann eine neue Zahlung auslösen. Dieses Minimalbeispiel enthält keinen auftragsbezogenen Speicher zur Verhinderung von Duplikaten. Ergänzen Sie eine Wiederholungsfunktion erst, wenn die Voraussetzungen des nächsten Abschnitts erfüllt sind.

## Behandlung verschiedener Prüfungsfehler

Prüfen Sie bei Fehlertests, dass der kostenpflichtige Body nicht offengelegt wird. Wenn Sie nur den HTTP-Status prüfen, können Sie eine fehlende Zugriffssperre übersehen. Als Referenz für das Verhalten dient die [offizielle Express-Middleware](https://github.com/x402-foundation/x402/blob/main/typescript/packages/http/express/src/index.ts).

| Testbedingung | Erwartetes Verhalten | Zusätzliche Prüfung |
|---|---|---|
| Zahlungsheader fehlt | 402 und Zahlungsbedingungen zurückgeben | Kein kostenpflichtiger Body |
| Anderer Token oder Empfänger angegeben | Durch Client-Richtlinie ablehnen | Keine Signatur erstellen |
| Ungültige Signatur | Wegen fehlgeschlagener Prüfung sperren | Kostenpflichtigen Handler nicht ausführen |
| Unzureichendes Guthaben | Wegen fehlgeschlagener Prüfung oder Abwicklung sperren | Nicht als erfolgreiche Abwicklung verbuchen |
| Abwicklungsergebnis meldet Fehler | Kostenpflichtige Antwort sperren | Auch vorbereiteten Body nicht senden |
| Verzögerte Antwort des Facilitators | Ohne Erfolgsbestätigung im ausstehenden Zustand halten | Keine neue Autorisierung automatisch erstellen |
| RPC-Fehler bei der Belegabfrage | Transaktionshash speichern und erneut abfragen | Nicht vorschnell als Zahlungsfehler einstufen |

Im grundlegenden Autorisierungsablauf wird der Handler vor der Abwicklung ausgeführt. Eine fehlgeschlagene Abwicklung macht externe Vorgänge nicht rückgängig. Beginnen Sie wie in diesem Beispiel mit Abfragen ohne Seiteneffekte.

Der Versand von E-Mails oder das Anlegen externer Aufträge erfordert eine separate Konzeption. Speichern Sie Zahlungs- und Vorgangsstatus gemeinsam. Legen Sie fest, welche Schritte bei einem Fehler erneut ausgeführt werden, um doppelte Vorgänge zu reduzieren.

## Wiederherstellung bei Antwortverlust nach der Abwicklung

Speichern Sie den Abschluss der Zahlung und den Abschluss der Inhaltsauslieferung als getrennte Zustände. Die Zahlung kann bereits abgeschlossen sein, während die Verbindung für die Antwort abbricht. Die Grundlage für den Umgang mit solchen Fällen bildet die [Dokumentation der Payment-Identifier-Erweiterung](https://docs.x402.org/extensions/payment-identifier).

Die Eigenschaft, dass eine erneute Anfrage für denselben Vorgang nicht zu einer doppelten Verarbeitung führt, heißt Idempotenz. `payment-identifier` stellt dafür eine Zahlungskennung bereit. Diese Funktion ist nicht allein durch das Hinzufügen der Kennung vollständig umgesetzt.

### Vergleich von Doppelzahlungen und erneuten Übertragungen

Der Schutz vor Wiederverwendung derselben Signatur muss von der Verhinderung doppelter Aufträge unterschieden werden. EIP-3009 verhindert, dass ein bereits verwendeter Autorisierungs-Nonce erneut genutzt wird. Dieses Verhalten ist in der [ERC-3009-Spezifikation](https://eips.ethereum.org/EIPS/eip-3009) definiert.

| Situation | Aus Sicht der Onchain-Autorisierung | Aus Sicht des API-Betriebs |
|---|---|---|
| Dieselbe Autorisierung erneut abwickeln | Prüfung auf bereits verwendeten Nonce | Bestehendes Ergebnis muss abgefragt werden |
| Neue Autorisierung für denselben Auftrag erstellen | Kann als separate Autorisierung verarbeitet werden | Doppelzahlungen müssen verhindert werden |
| Antwortverlust nach erfolgreicher Abwicklung | Vermögensübertragung kann abgeschlossen sein | Inhalte müssen erneut ausgeliefert werden |
| Zeitüberschreitung nach Abwicklungsanfrage | Ergebnis ist noch unklar | Ausstehender Zustand und Prüfung der Abwicklung erforderlich |

Das folgende Verfahren ist ein Entwurf zur Anbindung der offiziellen Erweiterung an einen Datenspeicher im Produktivbetrieb. Es ist im obigen Minimalcode nicht enthalten. Ergänzen Sie für den Produktivbetrieb einen persistenten Speicher und eine Steuerung gleichzeitiger Anfragen.

1. Deklarieren Sie auf dem Server die Unterstützung der Erweiterung `payment-identifier`.
2. Bewahren Sie auf dem Client die Kennung der logischen Anfrage auf.
3. Verknüpfen Sie die Kennung auf dem Server mit dem Zahler und dem Anfrageinhalt.
4. Speichern Sie den Bearbeitungsstatus atomar, um eine gleichzeitige Ausführung zu verhindern.
5. Speichern Sie nach erfolgreicher Abwicklung den Transaktionsnachweis und das Antwortergebnis.
6. Geben Sie bei einer erneuten Anfrage mit denselben Berechtigungen und Inhalten das gespeicherte Ergebnis zurück.
7. Prüfen Sie bei unklarem Abwicklungsergebnis zuerst die bestehende Autorisierung.

Eine Zahlungskennung ist weder ein Passwort noch ein Zugriffstoken. Geben Sie kostenpflichtige Cache-Inhalte nicht an eine Anfrage zurück, die lediglich die Kennung kennt. Prüfen Sie auch, ob sie von einem anderen Nutzer oder mit einem anderen Anfrage-Body wiederverwendet wird.

Halten Sie in den Betriebsaufzeichnungen Chain, Transaktionshash und Log-Position gemeinsam fest. Verknüpfen Sie diesen Datensatz mit dem Auftrag, um eine Wiederverwendung für andere Aufträge zu verhindern. Eine Übereinstimmung bei `Transfer` allein weist noch keine Auftragszuordnung nach.

## Häufige Fehler bei der Zahlungsimplementierung

Wer Versionsfelder und Erfolgssignale verwechselt, kann den Zahlungsstatus falsch beurteilen. Nutzen Sie die folgende Tabelle für die Prüfung vor der Bereitstellung. Die Versionsunterschiede richten sich nach dem [x402-Migrationsleitfaden](https://docs.x402.org/guides/migration-v1-to-v2).

| Häufiger Fehler | Korrekte Vorgehensweise |
|---|---|
| `extra.version: "2"` als x402-Version interpretieren | Protokollversion anhand von `x402Version` prüfen |
| `maxAmountRequired` in v2 verwenden | Für den Betrag in den Zahlungsbedingungen `amount` verwenden |
| Eigenmächtig einen Header `X-PAYMENT-REQUIRED` erstellen | In v1 den Body, in v2 `PAYMENT-REQUIRED` verwenden |
| `isValid: true` als abgeschlossenen Zahlungseingang behandeln | Ergebnis von `/settle` separat prüfen |
| Das oberste `to`-Feld der Transaktion als USDC-Empfänger behandeln | USDC `Transfer.to` prüfen |
| Annehmen, dass Signierer und Transaktionsabsender identisch sind | Den Zahler der Autorisierung mit `Transfer.from` vergleichen |
| Testnetzeingänge zum Umsatz addieren | Getrennte Bücher für Mainnet und Testnetz führen |
| Bei jeder Zeitüberschreitung eine neue Zahlung erstellen | Zuerst bestehenden Auftrag und Autorisierungsstatus wiederherstellen |
| SDK-Paketversion und Protokollversion gleichsetzen | Paketversion und `x402Version` getrennt verwalten |

Auch die Domain-Informationen einer USDC-Signatur enthalten eine Versionszeichenfolge. Dieser Wert erfüllt einen anderen Zweck als die x402-Protokollversion. Die Struktur der Signatur-Domain finden Sie in der [ERC-3009-Spezifikation](https://eips.ethereum.org/EIPS/eip-3009).

## Sicherheitsprüfung und Vertrauensgrenzen externer Dienste

Steuern Sie die Beurteilung des Zahlungserfolgs auf dem Server. Auch der Antwort eines externen Facilitators wird ausdrücklich Vertrauen entgegengebracht. Die Architektur, die auch einen Eigenbetrieb ermöglicht, ist in der [Facilitator-Dokumentation](https://github.com/x402-foundation/x402/blob/main/docs/core-concepts/facilitator.md) beschrieben.

- Geben Sie Inhalte nicht aufgrund einer Erfolgsmeldung des Clients frei.
- Vergleichen Sie Chain, Token, Betrag und Empfänger mit den Angaben des Servers.
- Schreiben Sie private Schlüssel und Seed-Phrasen nicht in Logs.
- Schließen Sie auch vollständige Autorisierungssignaturen aus allgemeinen Zugriffslogs aus.
- Begrenzen Sie die Größe der Zahlungsheader und die Bearbeitungszeit von Anfragen.
- Prüfen Sie, dass kostenpflichtige Antworten nicht in gemeinsam genutzten Caches verbleiben.
- Bewahren Sie Testschlüssel und Produktivschlüssel getrennt auf.
- Schaffen Sie bei einem Facilitator-Ausfall keinen Umgehungsweg ohne Zahlung.
- Testen Sie den Ablauf von Autorisierungen und doppelte Anfragen tatsächlich.

Bei den festgeschriebenen Abhängigkeiten dieser Übung bestehen weiterhin Warnungen aus der Sicherheitsprüfung. `npm audit` meldete einen Sicherheitshinweis zu zod. Einzelheiten finden Sie im [GitHub-Sicherheitshinweis](https://github.com/advisories/GHSA-mrhx-c7xc-m3w5).

```bash
npm audit
```

Prüfen Sie vor dem Produktiveinsatz die SDK-Kompatibilität der korrigierten Version. Ein erzwungener Wechsel der Hauptversion kann das Verhalten verändern. Verwenden Sie diese Übung nicht als bereits sicherheitsgeprüfte Bereitstellungskonfiguration.

### Vergleich von eigenem Server und Cloudflare Gateway

Bei Verwendung von Cloudflare Gateway ändert sich das Prüfverfahren des Ursprungsservers. Die Dokumentation vom 30. September 2026 nennt ausdrücklich die Verwendung von x402 v2. Die folgende Gegenüberstellung basiert auf der [Cloudflare-x402-Dokumentation](https://developers.cloudflare.com/monetization-gateway/x402/).

| Merkmal | Express-Verfahren dieses Artikels | Cloudflare Monetization Gateway |
|---|---|---|
| Verarbeitung der Client-Zahlung | Express-Middleware | Gateway |
| Prüfpunkt des Ursprungsservers | Anbindung an den ausgewählten Facilitator | Prüfung des JWT in `PAYMENT-CONTEXT` |
| Übermittlung des Abwicklungsergebnisses | `PAYMENT-RESPONSE` der Middleware | Gateway erstellt den Abwicklungsbeleg |
| Zusätzlich zu prüfen | Unterstützte Chains und Authentifizierung des Facilitators | JWT-Signaturprüfung und Schutz des Ursprungszugriffs |

`PAYMENT-CONTEXT` ist ein Header zwischen Gateway und Ursprungsserver. Er ist nicht der Signaturheader eines gewöhnlichen x402-Clients. Richten Sie die Prüfung auf dem Ursprungsserver nach der [Cloudflare-Dokumentation zu Payment validation](https://developers.cloudflare.com/monetization-gateway/configuration/payment-validation/) aus.

Auch hinter dem Gateway darf das JWT nicht nur dekodiert werden. Prüfen Sie die Signatur mit dem in der Dokumentation angegebenen Schlüssel. Sperren Sie kostenpflichtige Inhalte, wenn der Header fehlt oder die Prüfung fehlschlägt.

## Tatsächliche Nutzung und Abwicklungsaufzeichnungen unterscheiden

Die Anzahl der Onchain-Überweisungen allein belegt nicht den Konsum von Inhalten. Verknüpfen Sie für Betriebskennzahlen die Abwicklung mit der Auslieferung der Antwort. Dies ist ein Gestaltungsvorschlag auf Grundlage des Zahlungsablaufs und des Verhaltens bei erneuter Übertragung.

| Aufzeichnung | Welche Frage sie beantwortet | Zusätzlich benötigte Aufzeichnung |
|---|---|---|
| 402-Antwort | Wie oft Zahlungsbedingungen angefordert wurden | Ob tatsächlich gezahlt wurde |
| Erfolgreiche Prüfung | Ob die Autorisierung gültig war | Abwicklungsergebnis |
| USDC-Transfer | Ob Vermögenswerte übertragen wurden | Auftragszuordnung |
| Abgeschlossene Abwicklung pro Auftrag | Ob eine kostenpflichtige Anfrage bezahlt wurde | Auslieferungsstatus der Antwort |
| Aufzeichnung der erneuten Auslieferung | Ob eine bereits bezahlte Anfrage wiederhergestellt wurde | Kennung zur Unterscheidung von neuen Zahlungen |

Kennzeichnen Sie Testanfragen getrennt von der tatsächlichen Nutzung. Markieren Sie auch Wiederholungen desselben Auftrags gesondert. Das Transaktionsvolumen allein darf nicht als API-Nachfrage oder Umsatzgarantie dargestellt werden.

## Umstellung auf Base Mainnet

Ziehen Sie das Mainnet erst in Betracht, nachdem Sie die Erfolgs- und Fehlerabläufe im Testnetz geprüft haben. Die Umstellung ist nicht mit dem Ändern der Netzwerkzeichenfolge abgeschlossen. Das grundlegende Verfahren folgt dem [offiziellen Verkäuferleitfaden](https://docs.x402.org/getting-started/quickstart-for-sellers#running-on-mainnet).

1. Prüfen Sie, ob der ausgewählte Facilitator Base Mainnet unterstützt.
2. Prüfen Sie unter `/supported` die Unterstützung von v2, `exact` und `eip155:8453`.
3. Richten Sie die vom Anbieter verlangte Authentifizierung und die Nutzungsbedingungen ein.
4. Ändern Sie das Netzwerk auf Server und Client gemeinsam.
5. Ändern Sie die erlaubte USDC-Adresse des Clients auf die Mainnet-Adresse.
6. Gleichen Sie den Betrag der 402-Antwort und die tatsächliche Empfängeradresse erneut ab.
7. Binden Sie den Speicher für doppelte Anfragen und die Verfahren zur Fehlerwiederherstellung an.
8. Schließen Sie die Sicherheitsprüfung der Produktivabhängigkeiten ab.
9. Prüfen Sie mit dem festgelegten kleinen Betrag die tatsächliche Übertragung und Inhaltsauslieferung.

Multi-Chain-Unterstützung bedeutet nicht, dass alle Kombinationen unterstützt werden. Prüfen Sie den Unterstützungsumfang von SDK und Facilitator gemeinsam. Maßgeblich ist die [Dokumentation zur Netzwerk- und Token-Unterstützung](https://docs.x402.org/core-concepts/network-and-token-support).

## FAQ

### Worin unterscheidet sich x402 von der üblichen Überprüfung eines USDC-Zahlungseingangs?
Im Rahmen einer HTTP-Anfrage werden die Zahlungsbedingungen übermittelt, und die Anfrage wird mit einer signierten Zahlungsautorisierung erneut gesendet. Anders als beim nachträglichen Abgleich von Zahlungseingängen wird der Zahlungsvorgang mit der Anforderung kostenpflichtiger Ressourcen verknüpft.

### Welche Zahlungsheader verwendet x402 v2?
Die Zahlungsbedingungen werden über PAYMENT-REQUIRED und die Zahlungs-Payload über PAYMENT-SIGNATURE übermittelt. Das Ergebnis der Zahlungsabwicklung wird über PAYMENT-RESPONSE übermittelt.

### Gibt es in v1 den Header X-PAYMENT-REQUIRED?
Laut der offiziellen HTTP-v1-Spezifikation werden die anfänglichen Zahlungsbedingungen im JSON-Antworttext übermittelt. Für die Zahlungs-Payload und das Ergebnis der Zahlungsabwicklung werden X-PAYMENT bzw. X-PAYMENT-RESPONSE verwendet.

### Ist die Zahlung abgeschlossen, wenn /verify erfolgreich ist?
Ein erfolgreicher Aufruf von /verify bedeutet, dass die Zahlungsautorisierung gültig ist. In dieser Übung muss das erfolgreiche Ergebnis von /settle gesondert geprüft werden.

### Lässt sich Test-USDC auf Base Sepolia als tatsächliche Einnahme betrachten?
Circle weist ausdrücklich darauf hin, dass Testnet-USDC keinen finanziellen Wert hat. Erfassen Sie Zahlungsabwicklungen im Testnet getrennt von tatsächlichen Umsätzen.

### Muss auf dem Empfängerserver ein privater Schlüssel hinterlegt werden?
Auf dem Empfängerserver dieses Beispiels wird nur die öffentliche Empfängeradresse konfiguriert. Der private Schlüssel für die Zahlungsautorisierung wird vom Zahlungsclient eingelesen.

### Welchen Wert hat amount für 0.001 USDC?
Berücksichtigt man die 6 Nachkommastellen von USDC, ergibt sich in der kleinsten Einheit der Wert 1000. In den Zahlungsbedingungen von v2 wird die Zeichenfolge "1000" verwendet.

### Ist der USDC-Eingang ebenfalls bestätigt, wenn der Transaktionsbeleg einen Erfolg ausweist?
Der Erfolgsstatus der Transaktion allein reicht nicht aus. Gleichen Sie Zahler, Empfänger und Betrag anhand des Transfer-Ereignisses des offiziellen USDC-Smart-Contracts ab.

### Kann dieselbe Zahlungsanfrage gefahrlos erneut gesendet werden?
Die Verhinderung der Wiederverwendung derselben Autorisierungs-Nonce und die Vermeidung doppelter Bestellungen sind zwei verschiedene Dinge. Prüfen Sie vor einem erneuten Versuch den Status der bestehenden Zahlung und implementieren Sie eine idempotente Verarbeitung pro Bestellung.

### Kann ich einfach erneut bezahlen, wenn PAYMENT-RESPONSE fehlt?
Bei einer verloren gegangenen Antwort oder einer Zeitüberschreitung kann das Ergebnis der Zahlungsabwicklung unklar sein. Erstellen Sie nicht gleich eine neue Autorisierung, sondern prüfen Sie den Abwicklungsstatus der bestehenden Anfrage.

### Muss bei x402 der Facilitator eines bestimmten Unternehmens verwendet werden?
Die offizielle Architektur erlaubt sowohl die Nutzung eines externen Facilitators als auch den Eigenbetrieb. Prüfen Sie, ob die gewählte Implementierung die benötigte Protokollversion, Zahlungsmethode und Blockchain unterstützt.

### Werden auch die Ausgaben eines KI-Agenten automatisch begrenzt?
Dieses Beispiel begrenzt nur die Zahlungsbedingungen pro Anfrage. Verwalten Sie die durch wiederholte Aufrufe entstehenden kumulierten Ausgaben mit einer separaten Budgetrichtlinie.

### Ist Cloudflare PAYMENT-CONTEXT ein Standardheader für Zahlungssignaturen?
PAYMENT-CONTEXT ist ein JWT, das vom Gateway an den Ursprungsserver übermittelt wird. Es dient einem anderen Zweck als die PAYMENT-SIGNATURE des Clients.

### Kann ich das Beispiel direkt im Mainnet bereitstellen?
Dieser Code ist eine Minimalkonfiguration für Testzwecke. Prüfen Sie vor der Bereitstellung in der Produktionsumgebung die Sicherheitswarnungen zu Abhängigkeiten, die Verarbeitung doppelter Anfragen, die Authentifizierung des Facilitators und die tatsächliche Abrechnung.

## Sources

- [x402-Protokollspezifikation v2](https://github.com/x402-foundation/x402/blob/main/specs/x402-specification-v2.md)
- [x402 HTTP-Transport v1](https://github.com/x402-foundation/x402/blob/main/specs/transports-v1/http.md)
- [x402 HTTP-Transport v2](https://github.com/x402-foundation/x402/blob/main/specs/transports-v2/http.md)
- [x402-Migrationsleitfaden: Von V1 zu V2](https://docs.x402.org/guides/migration-v1-to-v2)
- [x402 Facilitator: Rolle und Verantwortlichkeiten](https://github.com/x402-foundation/x402/blob/main/docs/core-concepts/facilitator.md)
- [x402-Schnellstart für Verkäufer](https://docs.x402.org/getting-started/quickstart-for-sellers)
- [x402-Schnellstart für Käufer](https://docs.x402.org/getting-started/quickstart-for-buyers)
- [Offizielles x402-Beispiel für einen TypeScript-Client mit fetch](https://github.com/x402-foundation/x402/tree/main/examples/typescript/clients/fetch)
- [Implementierung einer Express-Middleware für x402](https://github.com/x402-foundation/x402/blob/main/typescript/packages/http/express/src/index.ts)
- [Auswahl von Zahlungsbedingungen und Implementierung von Richtlinien für x402Client](https://github.com/x402-foundation/x402/blob/main/typescript/packages/core/src/client/x402Client.ts)
- [Implementierung der serverseitigen Preisumrechnung für x402 ExactEvmScheme](https://github.com/x402-foundation/x402/blob/main/typescript/packages/mechanisms/evm/src/exact/server/scheme.ts)
- [Contract-Adressen für Circle USDC](https://developers.circle.com/stablecoins/usdc-contract-addresses)
- [Netzwerkinformationen zu Base Mainnet und Base Sepolia](https://docs.base.org/get-started/connect-to-base)
- [Circle Testnet Faucet](https://faucet.circle.com/)
- [viem getTransactionReceipt](https://viem.sh/docs/actions/public/getTransactionReceipt)
- [viem parseEventLogs](https://viem.sh/docs/contract/parseEventLogs)
- [ERC-20-Tokenstandard](https://eips.ethereum.org/EIPS/eip-20)
- [ERC-3009 Übertragung mit Autorisierung](https://eips.ethereum.org/EIPS/eip-3009)
- [x402 Payment-Identifier: Idempotenz-Erweiterung](https://docs.x402.org/extensions/payment-identifier)
- [Cloudflare Monetization Gateway: x402-Protokoll](https://developers.cloudflare.com/monetization-gateway/x402/)
- [Cloudflare Monetization Gateway: Zahlungsvalidierung](https://developers.cloudflare.com/monetization-gateway/configuration/payment-validation/)
- [x402: Unterstützung für Netzwerke und Token](https://docs.x402.org/core-concepts/network-and-token-support)
- [GitHub-Sicherheitshinweis: Erschöpfung des Arbeitsspeichers durch die Validierung großer Sammlungen mit Zod](https://github.com/advisories/GHSA-mrhx-c7xc-m3w5)

## Images

![Ein Mann im dunkelgrauen Pullover prüft ein Tablet auf der Ablage eines Serverracks.](https://injoys.com/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzM4MDcsInB1ciI6ImJsb2JfaWQifX0=--49c502fd8da16158a617c3586dfa81ced4bc95df/ai-f0ae2b5c.webp)
![Eine Frau tippt auf einem flach aufgeklappten Laptop; das Display zeigt eine Liste und zwei zusammenlaufende Pfade.](https://injoys.com/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MzM4MTMsInB1ciI6ImJsb2JfaWQifX0=--4e70727f132519277c68d1c6279d95585a936549/ai-3dbd1c62.webp)