Panacea Fatturazione, Chiavi API e Misurazione del Credito¶
Questa ricetta spiega come Panacea misura l'uso, autentica i chiamanti API e trasforma gli abbonamenti Stripe in un saldo di credito spendibile.
Cosa imparerai¶
- I tre modi in cui una richiesta può autenticarsi: JWT, token di sessione o chiave API a lungo termine
- Come i crediti vengono controllati e dedotti per richiesta, e come l'uso viene registrato
- Come un checkout di abbonamento Stripe fluisce verso un saldo di credito aggiornato
- Come gli utenti generano, elencano e revocano le proprie chiavi API
- Le protezioni contro gli abusi che regolano nuovi/variati abbonamenti
Perché è importante¶
Panacea non è solo una demo RAG — è un prodotto misurato con veri livelli di abbonamento. Ogni caricamento di documento, completamento di chat o chiamata di valutazione costa crediti, e i crediti vengono ripristinati da un abbonamento Stripe attivo. Questa ricetta attraversa l'intero ciclo: come un chiamante prova chi è, come quella identità viene valutata e come il denaro (tramite Stripe) si trasforma di nuovo in crediti utilizzabili.
File chiave di Panacea¶
| File | Perché è importante |
|---|---|
Panacea/backend/database/db_auth.py |
extractUserEmailFromRequest() prova JWT → token di sessione → chiave API in sequenza; user_has_credits(), api_key_user_has_credits(), deduct_credits_from_api_key_user(); protezioni contro gli abusi in verifyAuthForNewSubscriptipns() |
Panacea/backend/database/usage.py |
log_api_usage() scrive una riga per richiesta in api_usage; get_usage_summary() / get_usage_rows() alimentano la reportistica dell'uso |
Panacea/backend/api_endpoints/payments/handler.py |
CreateCheckoutSessionHandler, CreatePortalSessionHandler, StripeWebhookHandler |
Panacea/backend/api_endpoints/generate_api_key/handler.py, get_api_keys/handler.py, delete_api_key/handler.py, refresh_credits/handler.py |
Genera, elenca, revoca chiavi API; aggiorna manualmente i crediti |
Panacea/backend/stripe_config/portal_config.py |
Configurazione del Portale di Fatturazione Stripe per livello |
Come funziona¶
- Autenticazione. Ogni percorso protetto chiama
extractUserEmailFromRequest(request), che legge l'intestazioneAuthorization: Bearer <token>e prova, in ordine: decodificare come JWT, cercare come token di sessione (user_email_for_session_token), quindi cercare come chiave API (user_email_for_api_key). Quello che riesce per primo risolve l'email del chiamante. - Controlla i crediti. Prima di servire una richiesta, il backend chiama
user_has_credits(user_email)(chiamanti JWT/sessione) oapi_key_user_has_credits(api_key)(chiamanti chiave API) per confermare che la colonnacreditsdell'utente inuserssia almeno 1. - Deduzione e registrazione. Al termine,
deduct_credits_from_api_key_user()decrementa il saldo elog_api_usage()inserisce una riga inapi_usagecon l'endpoint, il modello, i conteggi dei token e i crediti spesi — questo alimentaGET /v1/usageeGET /v1/account. - Aggiornamento tramite Stripe. Il frontend chiama
POST /createCheckoutSession, che colpisceCreateCheckoutSessionHandler: risolve l'utente, mappa ilproduct_hashrichiesto a un ID prezzo Stripe e crea unastripe.checkout.Sessionin modalitàsubscription(applicando facoltativamente un codice di prova gratuito di 30 giorni). - Webhook completa il ciclo. Stripe richiama
POST /stripeWebhooksucheckout.session.completed;StripeWebhookHandlerregistra il nuovo abbonamento tramiteadd_subscription()e chiamarefresh_credits(user_email)per ricaricare il saldo dell'utente. Gli eventicustomer.subscription.updated(cancellazione) e.deletedvengono gestiti simmetricamente. - Gestisci l'abbonamento.
POST /createPortalSession(CreatePortalSessionHandler) apre una sessione del Portale di Fatturazione Stripe limitata al livello attuale dell'utente tramiteconfig_for_payment_tiers(), quindi gli aggiornamenti/declassamenti/cancellazioni avvengono attraverso l'interfaccia ospitata di Stripe. - Chiavi API.
POST /generateAPIKeyrichiede almeno 1 credito e chiamagenerate_api_key();GET /getAPIKeysePOST /deleteAPIKeyelencano/revocano chiavi, ciascuna tracciata con un timestamplast_used(touch_api_key_last_used).
Protezioni contro gli abusi¶
verifyAuthForNewSubscriptipns() in db_auth.py limita i nuovi abbonamenti per livello al giorno (ad esempio, 25/giorno per Premium, 5/giorno per Enterprise), invia un avviso interno via email a soglie definite (5, 10, 50, 100, 200, 500 nuovi abbonamenti/giorno) e blocca un utente dal cambiare piano più di una volta in un mese mobile.
Esegui localmente¶
Dalla radice del workspace (anote/panacea):
bash
cd Panacea
cp backend/.env.example backend/.env
docker compose up --build
Imposta questi in backend/.env per esercitare il flusso di fatturazione:
bash
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLIC_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
FRONTEND_URL=http://localhost:3000
JWT_SECRET_KEY=some-dev-secret
Inoltra i webhook di Stripe al tuo backend locale con Stripe CLI:
bash
stripe listen --forward-to localhost:5000/stripeWebhook
Provalo¶
```bash
Genera una chiave API (richiede un JWT/sessione autenticata, e >=1 credito)¶
curl -X POST http://localhost:5000/generateAPIKey \
-H "Authorization: Bearer
Controlla l'uso con la nuova chiave API¶
curl http://localhost:5000/v1/usage \
-H "Authorization: Bearer
Note per il ricettario¶
Abbina questo con la ricetta 07 (Gateway API compatibile con OpenAI) — le stesse chiavi API generate qui sono quelle che autenticano le chiamate a AnoteOpenAI. Vale la pena segnalare il refuso verifyAuthForNewSubscriptipns nel nome della funzione come una stranezza nota se un lettore va a cercarlo nel codice.