x402 Payments

In questa pagina

Il pacchetto @emdash-cms/x402 aggiunge il supporto per il protocollo di pagamento x402 a qualsiasi sito Astro su Cloudflare. Funziona come un’integrazione Astro standalone e si combina con i campi CMS di EmDash per la tariffazione per pagina quando usi EmDash.

x402 è un protocollo di pagamento nativo HTTP. Quando un client richiede una risorsa a pagamento senza pagamento, il server risponde con 402 Payment Required e istruzioni di pagamento leggibili dalla macchina. Gli agenti e i browser che comprendono x402 possono completare il pagamento automaticamente e riprovare la richiesta.

Quando usare questo

Il caso d’uso più comune è la modalità solo bot: addebita agli agenti IA e ai scraper l’accesso ai contenuti lasciando che i visitatori umani leggano gratuitamente. Questo utilizza Cloudflare Bot Management per distinguere i bot dagli umani.

Puoi anche imporre il pagamento per tutti i visitatori, o verificare gli header di pagamento senza imporre (rendering condizionale).

Installazione

Installa il pacchetto con il tuo gestore di pacchetti:

pnpm

pnpm add @emdash-cms/x402

npm

npm install @emdash-cms/x402

yarn

yarn add @emdash-cms/x402

Configurazione

Aggiungi l’integrazione alla tua configurazione Astro:

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,
		}),
	],
});

Aggiungi il riferimento di tipo in modo che TypeScript conosca Astro.locals.x402:

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

Utilizzo di base

L’integrazione posiziona un enforcer su Astro.locals.x402. Chiama enforce() nel frontmatter della tua pagina per proteggere i contenuti dietro pagamento:

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

Il metodo enforce() restituisce:

  • Una Response (402) — il client deve pagare. Restituiscila direttamente.
  • Un EnforceResult — la richiesta dovrebbe procedere. Il contenuto è stato pagato, o l’applicazione è stata saltata (umano in modalità botOnly).

Modalità solo bot

Quando botOnly è true, l’integrazione legge request.cf.botManagement.score per classificare le richieste:

  • Punteggio sotto la soglia (predefinito 30) -> trattato come bot, pagamento imposto
  • Punteggio sulla soglia o sopra -> trattato come umano, applicazione saltata
  • Nessun dato di gestione bot (sviluppo locale, deployment non-CF) -> trattato come umano

Il EnforceResult include un flag skipped in modo che tu possa distinguere tra “non ha dovuto pagare” e “ha pagato”:

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

Tariffazione per pagina con EmDash

Quando usi EmDash, aggiungi un campo number regolare alla tua collezione per la tariffazione per pagina e leggilo al momento della richiesta:

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

Verificare il pagamento senza imporre

Usa hasPayment() per verificare se una richiesta include header di pagamento senza verificare o imporre. Questo è utile per il rendering condizionale — mostrare contenuti diversi ai visitatori paganti vs non paganti:

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

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

{hasPaid ? (
  <p>Full premium content here.</p>
) : (
  <p>Subscribe for the full article.</p>
)}

Riferimento di configurazione

OpzioneTipoPredefinitoDescrizione
payTostringrichiestoIndirizzo wallet di destinazione
networkstringrichiestoIdentificatore di rete CAIP-2 (es. eip155:8453)
defaultPricePricePrezzo predefinito, sovrascrivibile per pagina
facilitatorUrlstringhttps://x402.org/facilitatorURL del facilitatore di pagamento
schemestring"exact"Schema di pagamento
maxTimeoutSecondsnumber60Timeout massimo per le firme di pagamento
evmbooleantrueAbilita il supporto della chain EVM
svmbooleanfalseAbilita il supporto della chain Solana (richiede @x402/svm)
botOnlybooleanfalseImponi il pagamento solo per i bot
botScoreThresholdnumber30Soglia di punteggio bot (1-99, più basso = più probabile che sia un bot)

Formato del prezzo

I prezzi possono essere specificati in diversi formati:

  • Stringa dollaro"$0.10" (il prefisso $ viene rimosso, il valore viene passato così com’è)
  • Stringa numerica"0.10"
  • Numero0.10
  • Oggetto{ amount: "100000", asset: "0x...", extra: {} } per importo/asset esplicito

Identificatori di rete

Le reti usano il formato CAIP-2:

ReteIdentificatore
Base mainneteip155:8453
Base Sepoliaeip155:84532
Ethereumeip155:1
Solanasolana:mainnet

Opzioni di Enforce

Sovrascrivi i valori predefiniti di configurazione per una pagina specifica:

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
});

Supporto Solana

Solana è opt-in. Installa @x402/svm e abilitalo nella configurazione:

pnpm add @x402/svm

Imposta la rete su un identificatore Solana e disabilita EVM se usi solo Solana:

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

Come funziona

  1. L’integrazione x402() registra un middleware che crea un enforcer e lo posiziona su Astro.locals.x402
  2. La configurazione viene passata al middleware tramite un modulo virtuale Vite (virtual:x402/config)
  3. Quando viene chiamato enforce(), controlla la presenza di un header payment-signature sulla richiesta
  4. Se non è presente alcun header di pagamento, viene restituita una risposta 402 Payment Required con le istruzioni di pagamento nell’header PAYMENT-REQUIRED
  5. Se è presente un header di pagamento, viene verificato attraverso il servizio facilitatore e regolato
  6. Dopo la regolazione, gli header PAYMENT-RESPONSE vengono impostati sulla risposta tramite applyHeaders()

Il server delle risorse viene inizializzato in modo lazy alla prima richiesta e memorizzato nella cache per la durata del worker.