Das Paket @emdash-cms/x402 fügt Unterstützung für das x402-Zahlungsprotokoll zu jeder Astro-Site auf Cloudflare hinzu. Es läuft als eigenständige Astro-Integration und lässt sich mit EmDash’s CMS-Feldern für seitenbasierte Preisgestaltung kombinieren, wenn Sie EmDash verwenden.
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.
Wann dies zu verwenden ist
Der häufigste Anwendungsfall ist der Bot-Only-Modus: Berechnen Sie KI-Agenten und Scrapern den Zugriff auf Inhalte, während menschliche Besucher kostenlos lesen können. Dies nutzt Cloudflare Bot Management, um Bots von Menschen zu unterscheiden.
Sie können auch Zahlungen für alle Besucher erzwingen oder auf Zahlungsheader prüfen, ohne sie zu erzwingen (bedingte Darstellung).
Installation
Installieren Sie das Paket mit Ihrem Package Manager:
pnpm
pnpm add @emdash-cms/x402 npm
npm install @emdash-cms/x402 yarn
yarn add @emdash-cms/x402 Einrichtung
Fügen Sie die Integration zu Ihrer Astro-Konfiguration hinzu:
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",
botOnly: true,
botScoreThreshold: 30,
}),
],
});
Fügen Sie die Typreferenz hinzu, damit TypeScript über Astro.locals.x402 Bescheid weiß:
/// <reference types="@emdash-cms/x402/locals" />
Grundlegende Verwendung
Die Integration platziert einen Enforcer auf Astro.locals.x402. Rufen Sie enforce() in Ihrem Seiten-Frontmatter auf, um Inhalte hinter Zahlungen zu schützen:
---
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 entweder zurück:
- Eine
Response(402) – der Client muss zahlen. Geben Sie sie direkt zurück. - Ein
EnforceResult– die Anfrage sollte fortgesetzt werden. Der Inhalt wurde bezahlt oder die Durchsetzung wurde übersprungen (Mensch im botOnly-Modus).
Bot-Only-Modus
Wenn botOnly auf true gesetzt ist, liest die Integration request.cf.botManagement.score, um Anfragen zu klassifizieren:
- Score unter Schwellenwert (Standard 30) -> als Bot behandelt, Zahlung erzwungen
- Score auf oder über Schwellenwert -> als Mensch behandelt, Durchsetzung übersprungen
- Keine Bot-Management-Daten (lokale Entwicklung, Nicht-CF-Bereitstellung) -> als Mensch behandelt
Das EnforceResult enthält ein skipped-Flag, damit Sie zwischen “musste nicht zahlen” und “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)
---
Seitenbasierte Preisgestaltung mit EmDash
Bei Verwendung von EmDash fügen Sie ein reguläres number-Feld zu Ihrer Sammlung für seitenbasierte Preisgestaltung 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.redirect("/404");
const { x402 } = Astro.locals;
// Use the price from the CMS, falling back to a default
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 Zahlung prüfen ohne Durchsetzung
Verwenden Sie hasPayment(), um zu prüfen, ob eine Anfrage Zahlungsheader enthält, ohne zu verifizieren oder durchzusetzen. Dies ist nützlich für bedingte Darstellung – um zahlenden und nicht zahlenden Besuchern unterschiedliche Inhalte zu zeigen:
---
const { x402 } = Astro.locals;
const hasPaid = x402.hasPayment(Astro.request);
---
{hasPaid ? (
<p>Full premium content here.</p>
) : (
<p>Subscribe for the full article.</p>
)}
Konfigurationsreferenz
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
payTo | string | erforderlich | Ziel-Wallet-Adresse |
network | string | erforderlich | CAIP-2-Netzwerkidentifikator (z.B. eip155:8453) |
defaultPrice | Price | — | Standardpreis, pro Seite überschreibbar |
facilitatorUrl | string | https://x402.org/facilitator | Zahlungsvermittler-URL |
scheme | string | "exact" | Zahlungsschema |
maxTimeoutSeconds | number | 60 | Maximales Timeout für Zahlungssignaturen |
evm | boolean | true | EVM-Chain-Unterstützung aktivieren |
svm | boolean | false | Solana-Chain-Unterstützung aktivieren (erfordert @x402/svm) |
botOnly | boolean | false | Zahlung nur für Bots erzwingen |
botScoreThreshold | number | 30 | Bot-Score-Schwellenwert (1-99, niedriger = wahrscheinlicher Bot) |
Preisformat
Preise können in mehreren Formaten angegeben werden:
- Dollar-String —
"$0.10"(das$-Präfix wird entfernt, Wert wird unverändert übergeben) - Numerischer String —
"0.10" - Zahl —
0.10 - Objekt —
{ amount: "100000", asset: "0x...", extra: {} }für explizite Asset/Amount-Angabe
Netzwerkidentifikatoren
Netzwerke verwenden das CAIP-2-Format:
| Netzwerk | Identifikator |
|---|---|
| Base mainnet | eip155:8453 |
| Base Sepolia | eip155:84532 |
| Ethereum | eip155:1 |
| Solana | solana:mainnet |
Enforce-Optionen
Überschreiben Sie 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
Solana ist opt-in. Installieren Sie @x402/svm und aktivieren Sie es in der Konfiguration:
pnpm add @x402/svm
Setzen Sie das Netzwerk auf einen Solana-Identifikator und deaktivieren Sie EVM, wenn Sie nur Solana verwenden:
x402({
payTo: "YourSolanaAddress",
network: "solana:mainnet",
svm: true,
evm: false, // Disable EVM if only using Solana
});
Wie es funktioniert
- Die
x402()-Integration registriert Middleware, die einen Enforcer erstellt und aufAstro.locals.x402platziert - Die Konfiguration wird über ein Vite-Virtual-Modul (
virtual:x402/config) an die Middleware übergeben - Wenn
enforce()aufgerufen wird, prüft es auf einenpayment-signature-Header in der Anfrage - Wenn kein Zahlungsheader vorhanden ist, wird eine
402 Payment Required-Antwort mit Zahlungsanweisungen imPAYMENT-REQUIRED-Header zurückgegeben - Wenn ein Zahlungsheader vorhanden ist, wird er über den Vermittlerdienst verifiziert und abgewickelt
- Nach der Abwicklung werden
PAYMENT-RESPONSE-Header überapplyHeaders()in der Antwort gesetzt
Der Ressourcen-Server wird beim ersten Request lazy initialisiert und für die Worker-Lebensdauer zwischengespeichert.