// Braintree — Visa, Mastercard e PayPal con un unico SDK
Perché Braintree e non Visa/Mastercard diretto: non esiste integrazione diretta con i circuiti card
per siti web — servono acquirer bancari e certificazione PCI-DSS. Tutti i siti usano un gateway.
Braintree (di PayPal) supporta Visa, Mastercard, Amex e PayPal nativo con un unico SDK.
Il flusso di sicurezza: (1) frontend chiede un client token al backend, (2) Braintree Drop-in UI
raccoglie i dati carta (non toccano mai il tuo server), (3) Drop-in restituisce un nonce usa-e-getta,
(4) il frontend invia il nonce al backend, (5) il backend crea la transazione.
giorno78
Braintree — setup account e SDK
- Crea account Braintree Sandbox (gratuito). Ottieni le 3 credenziali: merchantId, publicKey, privateKey
- Studia (2h): flusso Client Token → Drop-in UI → Nonce → Transaction. Differenza tra authorization e settlement
- Installa braintree Node.js SDK nel backend e configura il gateway nel PaymentsModule
- Endpoint GET /payments/client-token: genera e restituisce il token per inizializzare il Drop-in
giorno79
Drop-in UI in Angular
- Installa braintree-web-drop-in nel frontend Angular
- Componente CheckoutComponent: al mount chiama il backend per il client token, poi inizializza il Drop-in
- Il Drop-in mostra automaticamente i campi carta E il pulsante PayPal in un unico widget
- Al click su "Paga", chiama dropin.requestPaymentMethod() per ottenere il nonce
giorno80
Acquisto singolo corso — backend
- Endpoint POST /payments/checkout: riceve nonce + courseId, verifica che l'utente non sia già iscritto
- Crea la transazione Braintree: gateway.transaction.sale({ amount, paymentMethodNonce })
- Se success: crea il record Payment nel DB, triggera il job email di conferma, crea l'Enrollment
- Gestisci gli errori Braintree: carta rifiutata, CVV errato, fondi insufficienti — errori specifici al frontend
giorno81
Acquisto singolo corso — frontend
- Alla risposta success dal backend: redirect alla pagina del corso con messaggio di benvenuto
- Alla risposta error: mostra il messaggio di errore specifico nel componente checkout (non una generica "errore pagamento")
- Aggiungi loading state durante il pagamento per evitare doppi click
- Testa con le carte di test Braintree: 4111 1111 1111 1111 (Visa OK), 4000 1111 1111 1115 (rifiutata)
giorno82
PayPal — configurazione nel Drop-in
- Il Drop-in mostra già PayPal automaticamente — configura l'opzione paypal: { flow: "checkout" }
- Il flusso è identico a quello carta: l'utente clicca PayPal → popup → ottieni il nonce → stesso endpoint backend
- Testa il flusso PayPal con account sandbox Braintree (non serve un account PayPal reale)
- Verifica che il record Payment salvi correttamente il tipo di metodo usato (card vs paypal)
giorno83
Abbonamento mensile — Braintree Subscription
- Crea un Plan su Braintree Dashboard: prezzo mensile, nome "SynapsisForge Pro"
- Endpoint POST /payments/subscribe: crea un Customer Braintree con Vault del metodo di pagamento, avvia la Subscription
- Salva il subscriptionId Braintree nel record User — serve per gestire rinnovi e cancellazioni
- Aggiorna il campo plan dell'utente (free/pro) in base allo stato della subscription
giorno84
Webhook Braintree
- Endpoint POST /payments/webhook: riceve notifiche Braintree per rinnovi, fallimenti, cancellazioni
- Verifica sempre la firma del webhook: gateway.webhookNotification.parse(signature, payload)
- Gestisci subscription_charged_successfully: rinnova il piano utente, manda email
- Gestisci subscription_charged_unsuccessfully: downgrade a free, manda email di avviso
giorno85
Customer Portal — gestione abbonamento
- Endpoint POST /payments/cancel-subscription: cancella la subscription Braintree e imposta il piano a free
- Endpoint GET /payments/subscription-status: restituisce stato attuale, prossimo rinnovo, metodo di pagamento
- Componente Angular "Gestione Abbonamento": mostra lo stato, il metodo salvato (last4 carta o email PayPal), bottone cancellazione
- Testa il flusso completo: subscribe → rinnovo simulato → cancellazione → downgrade a free
giorno86
Idempotenza e test edge case
- Verifica idempotenza: un webhook doppio non deve creare due Enrollment o due rinnovi
- Salva il gatewayId di ogni transazione — se arriva un webhook già processato, ignoralo
- Testa: acquisto di un corso già acquistato → errore 409. Iscrizione con abbonamento Pro → senza pagamento aggiuntivo
- Revisiona la tabella Payment nel DB: tutti i campi sono popolati correttamente?
giorno87
Storico pagamenti e ricevute
- Endpoint GET /payments/history: lista paginata dei pagamenti dell'utente corrente
- Ogni pagamento include: data, importo, metodo, corso acquistato, link ricevuta
- Job BullMQ generate-receipt-pdf: genera PDF ricevuta con PdfKit e manda via email
- Componente Angular "Storico Pagamenti" nella dashboard studente
giorno88
Pagamenti review
- Testa l'intero flusso di pagamento in sandbox con ogni scenario: carta OK, carta rifiutata, PayPal, abbonamento, cancellazione
- Verifica che nessuna informazione sensibile della carta sia mai loggata (né in console né nel DB)
- Aggiungi le transazioni di test al seed script per avere dati nella dashboard
- Scrivi test di integrazione per l'endpoint /payments/checkout
🎯 Milestone: sistema di pagamento completo. Visa, Mastercard e PayPal via Braintree, con abbonamenti e webhook.