IT
Lezione 3.6

Stripe parte 2: webhook, proration, coupon ed Embedded Checkout

Rendere la fatturazione affidabile con webhook verificati e idempotenza, gestire la proration sugli upgrade a meta ciclo, far girare coupon e pubblicare l'Embedded Checkout

32 minLo stack applicativo moderno - Auth, dati e pagamentiDisponibile

Cosa impari

  • Cosa sono i webhook, perche il polling e l'istinto sbagliato e come verificare le firme di webhook
  • L'idempotenza, la proration sugli upgrade a meta ciclo e coupon contro promotion code
  • L'Embedded Checkout e le trappole di webhook che colgono ogni principiante

Panoramica

Nella parte 1, hai incassato un pagamento. Ma ecco la verita scomoda: dopo aver rediretto un cliente verso il checkout, la tua app non sa davvero cosa gli e successo. Ha pagato? La carta ha fallito piu tardi? Ha annullato il mese seguente? Indovinare e cosi che le persone offrono il prodotto gratis per sbaglio o continuano a fatturare clienti annullati. La risposta sono i webhook: Stripe chiama la tua app ogni volta che succede qualcosa, perche la tua app reagisca alla realta invece di indovinare. Questa lezione rende la tua fatturazione degna di fiducia: webhook verificati, idempotenza, proration, coupon, Embedded Checkout e le trappole che mordono tutti la prima volta.

Cosa imparerai

Imparerai cos'e un webhook e perche fare polling su Stripe e l'istinto sbagliato, come verificare una firma di webhook perche gli attaccanti non possano falsificare event, come l'idempotenza ti impedisce di trattare un event duplicato due volte, come la proration gestisce equamente un cambio di piano a meta ciclo, la differenza tra coupon e promotion code, come funziona l'Embedded Checkout e le trappole di webhook che causano il classico fallimento "funzionava in test ma si e rotto in produzione".

Prerequisiti

Stripe parte 1 e un subscription checkout funzionante, piu un backend che puo ricevere richieste HTTP (le tue action Convex o le route server del tuo framework), perche un webhook e solo Stripe che invia una richiesta al tuo backend. La lezione sui segreti anche, perche il webhook signing secret e un'altra chiave da custodire.

Il problema

L'istinto naif dopo il checkout e fare polling: chiedere a Stripe ogni pochi secondi "hanno gia pagato?". E sbagliato su tutti gli assi. Spreca richieste, e lento, manca gli event che arrivano piu tardi (un rinnovo il mese prossimo, una carta che fallisce tra 30 giorni, una cancellazione) e non scala. Peggio, appoggiarsi solo alla redirezione dell'URL di successo e inaffidabile - un cliente puo pagare poi chiudere la scheda prima che la redirezione scatti, e ora ha pagato ma la tua app non l'ha mai registrato. Il modello giusto e invertito: non chiedere, fatti dire. Stripe spinge un event al tuo backend nell'istante in cui qualcosa arriva, e la tua app reagisce. E un webhook, e farlo bene e cio che rende la fatturazione degna di fiducia.

Cosa sono i webhook e verificare le firme

Un webhook e Stripe che fa una richiesta HTTP verso un URL che ti appartiene, ogni volta che un event sopravviene: un pagamento e riuscito, una subscription e stata rinnovata, una carta ha fallito, una subscription e stata annullata. Il tuo backend ascolta a questo URL e aggiorna il tuo database in reazione. Ma c'e una trappola: chiunque su internet potrebbe inviare una falsa richiesta a questo URL fingendosi Stripe, e cercare di ingannare la tua app perche accordi accesso gratuito. Quindi devi verificare che ogni richiesta venga davvero da Stripe. Stripe firma ogni webhook con un segreto (il webhook signing secret, che comincia con whsec_), e tu verifichi questa firma a ogni richiesta. Se la verifica fallisce, rifiuti la richiesta. Non fidarti mai di un webhook non verificato. Ecco la verifica che non e negoziabile.

// Webhook handler (backend). Verifica la firma PRIMA di fidarti di qualsiasi cosa.
import Stripe from 'stripe'

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET! // whsec_xxx

export async function handleStripeWebhook(req: Request) {
  const signature = req.headers.get('stripe-signature')!
  const rawBody = await req.text() // DEVE essere il body grezzo, non JSON parsato

  let event: Stripe.Event
  try {
    // Lancia un errore se la firma e invalida o se il body e stato alterato.
    event = await stripe.webhooks.constructEventAsync(rawBody, signature, webhookSecret)
  } catch {
    return new Response('Invalid signature', { status: 400 })
  }

  switch (event.type) {
    case 'checkout.session.completed':
      // Accordare l'accesso / marcare l'utente come abbonato nel tuo database.
      break
    case 'customer.subscription.deleted':
      // Togliere l'accesso - hanno annullato.
      break
    case 'invoice.payment_failed':
      // Avvertire l'utente / avviare un flusso di recupero.
      break
  }
  return new Response('ok', { status: 200 })
}
Verifica sempre la firma con il body grezzo prima di fidarti di un webhook. Un webhook non verificato e una porta aperta.

Un dettaglio che rompe le persone: devi verificare contro il body grezzo della richiesta, esattamente come Stripe l'ha inviato. Se il tuo framework parsa il body in JSON prima che tu verifichi, la firma non corrisponde e ogni webhook fallisce. Leggi prima il body grezzo, verifica, poi parsa.

Idempotenza: gestire i doppioni in sicurezza

Stripe garantisce che consegna ogni event almeno una volta, il che vuol dire che potrebbe consegnare lo stesso event piu di una volta - durante un nuovo tentativo dopo un timeout o un singhiozzo di rete. Se il tuo handler accorda un mese di crediti gratuiti o invia una e-mail di benvenuto ogni volta che vede checkout.session.completed, una doppia consegna accorda o invia in doppio. Il fix e l'idempotenza: progetta il tuo handler perche trattare lo stesso event due volte abbia lo stesso effetto che trattarlo una volta. L'approccio affidabile piu semplice e registrare ogni ID di event che hai trattato e saltarlo se lo rivedi. Stripe raccomanda anche di rispondere in fretta con un 200 e fare il lavoro lento dopo, perche Stripe non vada in timeout e non riconsegni inutilmente.

  • Stripe consegna ogni event almeno una volta, quindi i doppioni arrivano - progetta per questo.
  • Memorizza gli ID di event trattati; se ne hai gia visto uno, dagli acknowledge e salta il lavoro.
  • Rendi le azioni sicure da ripetere: "porre subscribed = true" e naturalmente idempotente; "aggiungere un mese" non lo e.
  • Rispondi in fretta con 200; se sei lento o hai un errore, Stripe ritenta, il che causa piu doppioni.

Proration sugli upgrade a meta ciclo

Un cliente sul piano mensile fa upgrade verso il piano annuale, o passa da un livello meno caro a uno piu caro, nel bel mezzo del suo periodo di fatturazione. Cosa deve pagare? La proration e Stripe che calcola l'importo giusto: accredita la porzione inutilizzata di cio che ha gia pagato e fattura la differenza per il nuovo piano sul resto del periodo. Non calcoli questo da solo - dici a Stripe di aggiornare la subscription verso il nuovo prezzo, e Stripe determina l'addebito o accredito proratizzato. Il tuo job e decidere il comportamento (fatturare la differenza subito o applicarla alla prossima fattura) e aggiornare l'accesso nella tua app quando il webhook conferma il cambiamento. L'errore da evitare e calcolare gli importi proratizzati a mano; lascia Stripe fare l'aritmetica e reagisci agli event risultanti.

  • Upgrade a meta ciclo: Stripe accredita il tempo inutilizzato e fattura la differenza proratizzata.
  • Tu aggiorni la subscription verso il nuovo ID di prezzo; Stripe calcola il denaro.
  • Scegli se la proration e fatturata ora o aggiunta alla prossima fattura.
  • Reagisci al webhook (subscription aggiornata, fattura pagata) per sincronizzare l'accesso nella tua app.

Coupon e promotion code

Questi due sono collegati ma non identici, e la distinzione conta. Un coupon e la regola di sconto sottostante: "20 percento di sconto" o "10 USD di sconto, una volta". Un promotion code e un codice lato cliente (come LAUNCH20) che applica un coupon. Crei un coupon, poi crei uno o piu promotion code che puntano a esso. La ragione dei due strati e la flessibilita: un coupon ("20 percento di sconto") puo portare piu codici con diverse restrizioni (scadenza, limite d'uso, solo nuovi clienti). Nel checkout, puoi attivare un campo promotion code perche i clienti digitino un codice da soli, o puoi applicare un coupon direttamente a una session nel codice per uno sconto automatico. Usa i promotion code per le campagne marketing dove i clienti devono digitare, e l'applicazione diretta di coupon per gli sconti che accordi programmaticamente.

  • Coupon: la regola di sconto stessa (percentuale, importo fisso, durata).
  • Promotion code: un codice lato cliente (LAUNCH20) che applica un coupon.
  • Un coupon puo portare molti promotion code con diversi limiti e scadenze.
  • Attiva il campo promotion code nel checkout per codici digitati dal cliente, o applica un coupon nel codice per sconti automatici.

Embedded Checkout

La parte 1 menzionava l'Embedded Checkout; qui merita il suo posto. L'Embedded Checkout rende il flusso di pagamento sicuro di Stripe all'interno della tua pagina, invece di redirigere verso un URL ospitato da Stripe, cosicche il cliente resta sul tuo dominio per tutto il percorso. Cio aumenta generalmente la conversione (ogni redirezione e un'occasione di perdere qualcuno) e si sente di piu come una parte del tuo prodotto. La meccanica: il tuo backend crea una checkout session in ui_mode embedded e restituisce un client secret, e il tuo frontend monta il componente Embedded di Stripe con quel secret. La carta e sempre interamente raccolta da Stripe, quindi mantieni tutti i vantaggi di sicurezza e conformita possedendo al tempo stesso l'esperienza. Afferra Embedded una volta che il tuo flusso Hosted funziona e vuoi stringere la conversione.

// Backend : creare una checkout session EMBEDDED e restituire il suo client secret.
const session = await stripe.checkout.sessions.create({
  ui_mode: 'embedded', // embedded, nessuna redirezione
  mode: 'subscription',
  line_items: [{ price: priceId, quantity: 1 }],
  return_url: 'https://app.yoursite.com/welcome?session_id={CHECKOUT_SESSION_ID}',
})
// Invia session.client_secret al frontend, che monta l'UI Embedded di Stripe.
L'Embedded Checkout tiene il cliente sul tuo dominio mentre Stripe gestisce sempre la carta.

Trappole di webhook frequenti

Ecco le cose concrete che fanno si che i webhook "funzionino in test ma si rompano in produzione", raccolte perche tu possa evitare ciascuna. La maggior parte dei bug di fatturazione di produzione si riconduce a una di esse.

  • Parsare il body prima di verificare: la verifica di firma ha bisogno del body grezzo. Leggi grezzo prima, verifica, poi parsa.
  • Usare il webhook secret sbagliato: test e live hanno ciascuno un whsec_ diverso, e la Stripe CLI ne da un terzo per il forwarding locale. Adatta il secret all'ambiente.
  • Non gestire i doppioni: senza idempotenza, un event riconsegnato tratta in doppio. Memorizza gli ID di event trattati.
  • Fidarsi della redirezione di successo piuttosto che del webhook: l'utente puo chiudere la scheda prima che la redirezione scatti, quindi accorda l'accesso dal webhook, non dalla redirezione.
  • Handler lenti o falliti: restituisci 200 in fretta. Se metti troppo tempo o hai un errore, Stripe ritenta, il che moltiplica i doppioni.
  • Dimenticare di registrare il webhook endpoint di produzione: l'endpoint di test non si trasferisce in modalita live. Aggiungi l'URL live e il suo secret quando passi in live.
# Testare i webhook in locale con la Stripe CLI - fa il forwarding degli event live verso la tua macchina
# e da un secret whsec_ per la verifica locale.
stripe login
stripe listen --forward-to localhost:5296/api/stripe/webhook

# In un altro terminale, innescare un falso event per testare il tuo handler :
stripe trigger checkout.session.completed
La Stripe CLI fa il forwarding degli event veri verso localhost e ti lascia innescare event di test - il modo standard di sviluppare webhook.

Errori frequenti

Oltre alla lista delle trappole: fare polling su Stripe invece di usare webhook; fidarsi di un webhook non verificato e lasciare un attaccante falsificare un event "pagamento riuscito" per ottenere un accesso gratuito; calcolare la proration a mano invece di lasciarlo fare a Stripe; confondere coupon e promotion code; e pubblicare l'Embedded Checkout senza prima solidificare il flusso Hosted e i webhook. Il filo conduttore: fatti dire, non chiedere; verifica tutto; lascia Stripe fare i conti di denaro; e tratta i doppioni come inevitabili.

ROI business

Questa lezione e la differenza tra una fatturazione che ti fa perdere denaro in silenzio e una fatturazione di cui puoi fidarti. Senza webhook verificati, o offri un accesso per cui non sei mai stato pagato, o continui a fatturare gente che ha annullato - entrambi sono danni diretti di ricavo e reputazione. L'idempotenza impedisce il doppio addebito o doppio accordare imbarazzante. La proration fatta da Stripe tiene giusti gli upgrade, il che toglie attrito dall'azione piu preziosa che un cliente puo fare: spendere di piu. E l'Embedded Checkout piu i promotion code sono leve di conversione dirette. Dedicare un giorno a fare bene i webhook protegge ogni dollaro che scorre attraverso il tuo prodotto da qui in poi.

Checklist

La tua fatturazione e pronta per la produzione quando tutto questo regge.

  • Verifichi ogni firma di webhook contro il body grezzo prima di reagirvi.
  • Il tuo handler e idempotente - un event duplicato non causa un doppio trattamento.
  • Accordi e togli l'accesso dai webhook, non dalla redirezione di successo.
  • Gli upgrade usano la proration Stripe, e hai un promotion code funzionante e un flusso Embedded o Hosted in live.

Risorse

La documentazione webhook di Stripe, la reference degli event e la Stripe CLI sono i tuoi strumenti chiave qui - la CLI rende soprattutto lo sviluppo locale di webhook indolore. Tieni i tuoi webhook signing secret test e live chiaramente etichettati, per non incrociarli mai. Poi, l'ultima lezione passa tutto lo stack in live: migrazione dev-verso-prod per Clerk e Convex, DNS, Cloudflare, Search Console e performance.

La tua missione

Installa la Stripe CLI, lancia stripe listen per fare il forwarding degli event verso il tuo backend locale, e costruisci un webhook handler che verifica la firma e accorda l'accesso su checkout.session.completed. Innesca un doppione dello stesso event e conferma che il tuo handler non lo tratta due volte. Poi attiva un campo promotion code nel tuo checkout e testa un coupon. Ora hai una fatturazione che reagisce alla realta, invece di indovinare.

Prossima lezione

Il tuo prodotto incassa i pagamenti in modo affidabile. L'ultima lezione del corso passa tutto in live: migrare Clerk e Convex da dev a prod, cablare DNS e Cloudflare, verificare il tuo sito nella Google Search Console e sottomettere il tuo sitemap, e portare i tuoi punteggi Lighthouse al verde, perche il prodotto live sia veloce e trovabile.

Commenti

Caricamento dei commenti.

Pubblica un commento
CommentiAvanti
Prossimo passo

Pronto a far funzionare l'intelligenza artificiale come un vero flusso di lavoro?

Inizia con il corso di base, mantieni i tuoi progressi localmente e sincronizza tutto con il tuo account gratuito quando vuoi.