x402 Payments

Auf dieser Seite

Das Paket @emdash-cms/x402 fügt serverseitig gerenderten Astro-Sites Unterstützung für das x402-Zahlungsprotokoll hinzu. Es ist eine eigenständige Astro-Integration, daher setzt die Durchsetzung von Zahlungen EmDash nicht voraus. Wenn die Site außerdem EmDash verwendet, kann ein Inhaltsfeld den Preis für jeden Eintrag liefern.

x402 ist ein HTTP-natives Zahlungsprotokoll. Wenn ein Client eine kostenpflichtige Ressource ohne Zahlung anfordert, antwortet der Server mit 402 Payment Required und maschinenlesbaren Zahlungsanweisungen. Agents und Browser, die x402 verstehen, können die Zahlung automatisch abschließen und die Anfrage wiederholen.

Einen Durchsetzungsmodus wählen

Verwenden Sie die normale Durchsetzung, wenn jede Anfrage an die Route eine gültige Zahlung vorweisen muss. Dieser Modus hängt nicht von Cloudflare-spezifischen Anfragemetadaten ab.

Verwenden Sie den Bot-Only-Modus, wenn die Site auf Cloudflare Workers mit aktiviertem Bot Management läuft und nur Anfragen mit niedrigem Score zahlen sollen. Das Paket liest request.cf.botManagement.score; fehlt dieser Wert, behandelt es die Anfrage als menschlich und überspringt die Durchsetzung. Verwenden Sie den Bot-Only-Modus nicht, wenn fehlende Bot-Daten geschlossen fehlschlagen müssen (fail closed).

hasPayment() bietet ein drittes Verhalten, ausschließlich für die Darstellung. Es meldet, ob die Anfrage einen Zahlungs-Header enthält, überprüft oder begleicht die Zahlung aber nicht.

Das Paket installieren

Installieren Sie das Paket mit Ihrem Paketmanager:

pnpm

pnpm add @emdash-cms/x402

npm

npm install @emdash-cms/x402

yarn

yarn add @emdash-cms/x402

Die Integration konfigurieren

Wählen Sie eine Wallet, ein Netzwerk und einen Facilitator, die zusammenarbeiten. Die Integration unterstützt standardmäßig Ethereum-Virtual-Machine-Netzwerke (EVM), aber der Facilitator muss auch das konfigurierte Netzwerk und Asset unterstützen. Das folgende Beispiel verwendet das Base-Mainnet und erzwingt die Zahlung für jede Anfrage:

import { defineConfig } from "astro/config";
import { x402 } from "@emdash-cms/x402";

export default defineConfig({
	integrations: [
		x402({
			payTo: "0xYourWalletAddress",
			network: "eip155:8453", // Base mainnet
			defaultPrice: "$0.01",
		}),
	],
});

Fügen Sie die Typreferenz hinzu, damit TypeScript Astro.locals.x402 kennt:

/// <reference types="@emdash-cms/x402/locals" />

Zahlung für eine Route erzwingen

Die Integration legt einen Enforcer auf Astro.locals.x402. Rufen Sie enforce() im Frontmatter Ihrer Seite auf, um Inhalte hinter eine Zahlung zu stellen:

---
const { x402 } = Astro.locals;

const result = await x402.enforce(Astro.request, {
  price: "$0.05",
  description: "Premium article",
});

// If the request has no valid payment, enforce() returns a 402 Response.
// Return it directly to send payment instructions to the client.
if (result instanceof Response) return result;

// Payment verified (or skipped in botOnly mode). Apply response headers
// so the client gets settlement proof.
x402.applyHeaders(result, Astro.response);
---

<article>
  <h1>Premium content</h1>
</article>

Die Methode enforce() gibt eines von beidem zurück:

  • Eine Response (402) — der Client muss zahlen. Geben Sie sie direkt zurück.
  • Ein EnforceResult — die Anfrage soll fortgesetzt werden. Der Inhalt wurde bezahlt, oder die Durchsetzung wurde übersprungen (Mensch im botOnly-Modus).

Den Bot-Only-Modus aktivieren

Aktivieren Sie botOnly in der Integrationskonfiguration:

x402({
	payTo: "0xYourWalletAddress",
	network: "eip155:8453",
	defaultPrice: "$0.01",
	botOnly: true,
	botScoreThreshold: 30,
});

Die Integration liest den Wert request.cf.botManagement.score von Cloudflare, um Anfragen einzustufen:

  • Score unter dem Schwellenwert (Standard 30) -> als Bot behandelt, Zahlung erzwungen
  • Score auf oder über dem Schwellenwert -> als Mensch behandelt, Durchsetzung übersprungen
  • Keine Bot-Management-Daten (lokale Entwicklung, Deployment außerhalb von Cloudflare) -> als Mensch behandelt

Das EnforceResult enthält ein skipped-Flag, damit Sie „musste nicht zahlen“ von „hat bezahlt“ unterscheiden können:

---
const result = await x402.enforce(Astro.request, { price: "$0.01" });
if (result instanceof Response) return result;

x402.applyHeaders(result, Astro.response);

// result.paid    — true if payment was verified
// result.skipped — true if enforcement was skipped (human in botOnly mode)
// result.payer   — wallet address of payer (if paid)
---

Einen Preis aus EmDash lesen

Wenn Sie EmDash verwenden, fügen Sie Ihrer Collection ein reguläres number-Feld für seitenspezifische Preise hinzu und lesen Sie es zur Anfragezeit:

---
import { getEmDashEntry } from "emdash";

const { slug } = Astro.params;
const { entry } = await getEmDashEntry("posts", slug);

if (!entry) return Astro.rewrite("/404");

const { x402 } = Astro.locals;

// Use the price from the CMS, falling back only when it is absent.
const result = await x402.enforce(Astro.request, {
  price: entry.data.price ?? "$0.01",
  description: entry.data.title,
});
if (result instanceof Response) return result;

x402.applyHeaders(result, Astro.response);
---

<article>
  <h1>{entry.data.title}</h1>
</article>

Auf einen Zahlungs-Header prüfen, ohne durchzusetzen

Verwenden Sie hasPayment(), um zu prüfen, ob eine Anfrage einen Zahlungs-Header enthält, ohne ihn zu überprüfen oder durchzusetzen. Das kann einen Hinweistext oder eine Anmeldemeldung ändern, darf aber niemals geschützte Inhalte freischalten:

---
const { x402 } = Astro.locals;

const hasPaymentHeader = x402.hasPayment(Astro.request);
---

{hasPaymentHeader ? (
  <p>Payment supplied. Verification is still required.</p>
) : (
  <p>This page requires payment.</p>
)}

Konfigurationsreferenz

OptionTypStandardBeschreibung
payTostringerforderlichWallet-Adresse des Empfängers
networkstringerforderlichCAIP-2-Netzwerkkennung (z. B. eip155:8453)
defaultPricePrice—Standardpreis, pro Seite überschreibbar
facilitatorUrlstringhttps://x402.org/facilitatorURL des Zahlungs-Facilitators
schemestring"exact"Zahlungsschema
maxTimeoutSecondsnumber60Maximales Timeout für Zahlungssignaturen
evmbooleantrueUnterstützung für Ethereum-Virtual-Machine-Netzwerke aktivieren
svmbooleanfalseUnterstützung für Solana Virtual Machine aktivieren (erfordert @x402/svm)
botOnlybooleanfalseZahlung nur für Bots erzwingen
botScoreThresholdnumber30Schwellenwert für den Bot-Score (1–99, niedriger = wahrscheinlicher ein Bot)

Preisformat

Preise können in mehreren Formaten angegeben werden:

  • Dollar-String — "$0.10" (das Präfix $ wird entfernt, der Wert unverändert übergeben)
  • Numerischer String — "0.10"
  • Zahl — 0.10
  • Objekt — { amount: "100000", asset: "0x...", extra: {} } für explizites Asset und Betrag

Netzwerkkennungen

CAIP-2 vergibt eindeutige Kennungen für Blockchain-Netzwerke, etwa eip155:8453 für das Base-Mainnet. Verwenden Sie genau die Kennung, die der Facilitator ausweist. Das Paket akzeptiert die Familie eip155:*, wenn die EVM-Unterstützung aktiviert ist, und die Familie solana:*, wenn die Unterstützung für die Solana Virtual Machine (SVM) aktiviert ist; das garantiert nicht, dass ein Facilitator jedes Netzwerk dieser Familie akzeptiert.

Eine einzelne Anfrage überschreiben

Überschreiben Sie die Konfigurationsstandards für eine bestimmte Seite:

await x402.enforce(Astro.request, {
	price: "$0.25", // Override price
	payTo: "0xDifferentWallet", // Override wallet
	network: "eip155:1", // Override network
	description: "Article: How x402 Works", // Resource description
	mimeType: "text/html", // MIME type hint
});

Solana-Unterstützung aktivieren

Solana ist optional. Installieren Sie @x402/svm und aktivieren Sie es in der Konfiguration:

pnpm add @x402/svm

Setzen Sie svm: true, verwenden Sie die vom Facilitator unterstützte CAIP-2-Kennung für Solana und deaktivieren Sie EVM, wenn die Site nur Solana-Zahlungen akzeptiert. Die Solana-Mainnet-Kennung, die @x402/svm 2.8 verwendet, lautet zum Beispiel solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:

x402({
	payTo: "YourSolanaAddress",
	network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
	svm: true,
	evm: false, // Disable EVM if only using Solana
});

Ablauf einer Anfrage

  1. Die Integration legt den Zahlungs-Enforcer auf Astro.locals.x402, bevor die Seite ausgeführt wird.
  2. enforce() prüft auf einen payment-signature-Header.
  3. Ohne Zahlungs-Header gibt enforce() eine Antwort 402 Payment Required zurück, deren Body und PAYMENT-REQUIRED-Header die akzeptierte Zahlung beschreiben.
  4. Bei einer passenden Zahlung überprüft und begleicht der konfigurierte Facilitator sie.
  5. enforce() gibt den Zahlenden und das Abwicklungsergebnis zurück. Rufen Sie applyHeaders() auf, damit die Seitenantwort den PAYMENT-RESPONSE-Nachweis des Facilitators enthält.