Panacea Faturamento, Chaves de API e Medição de Crédito¶
Esta receita explica como a Panacea mede o uso, autentica os chamadores da API e transforma assinaturas do Stripe em um saldo de crédito utilizável.
O que você aprenderá¶
- As três maneiras de uma solicitação se autenticar: JWT, token de sessão ou chave de API de longa duração
- Como os créditos são verificados e deduzidos por solicitação, e como o uso é registrado
- Como um fluxo de checkout de assinatura do Stripe se transforma em um saldo de crédito atualizado
- Como os usuários geram, listam e revogam suas próprias chaves de API
- As barreiras de abuso que controlam novas/alteradas assinaturas
Por que isso é importante¶
A Panacea não é apenas uma demonstração RAG — é um produto medido com níveis de assinatura reais. Cada upload de documento, conclusão de chat ou chamada de avaliação custa créditos, e os créditos são reabastecidos por uma assinatura ativa do Stripe. Esta receita percorre todo o ciclo: como um chamador prova quem é, como essa identidade é precificada e como o dinheiro (via Stripe) se transforma novamente em créditos utilizáveis.
Principais arquivos do Panacea¶
| Arquivo | Por que é importante |
|---|---|
Panacea/backend/database/db_auth.py |
extractUserEmailFromRequest() tenta JWT → token de sessão → chave de API em sequência; user_has_credits(), api_key_user_has_credits(), deduct_credits_from_api_key_user(); barreiras de abuso em verifyAuthForNewSubscriptipns() |
Panacea/backend/database/usage.py |
log_api_usage() escreve uma linha por solicitação em api_usage; get_usage_summary() / get_usage_rows() alimentam relatórios de 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 |
Criar, listar, revogar chaves de API; atualizar créditos manualmente |
Panacea/backend/stripe_config/portal_config.py |
Configuração do Portal de Faturamento do Stripe por nível |
Como funciona¶
- Autenticar. Cada rota protegida chama
extractUserEmailFromRequest(request), que lê o cabeçalhoAuthorization: Bearer <token>e tenta, na ordem: decodificar como um JWT, procurar como um token de sessão (user_email_for_session_token), e então procurar como uma chave de API (user_email_for_api_key). O que tiver sucesso primeiro resolve o e-mail do chamador. - Verificar créditos. Antes de atender a uma solicitação, o backend chama
user_has_credits(user_email)(chamadores JWT/sessão) ouapi_key_user_has_credits(api_key)(chamadores de chave de API) para confirmar que a colunacreditsdo usuário emusersé pelo menos 1. - Deduzir e registrar. Ao completar,
deduct_credits_from_api_key_user()decrementa o saldo elog_api_usage()insere uma linha emapi_usagecom o endpoint, modelo, contagens de token e créditos gastos — isso é o que alimentaGET /v1/usageeGET /v1/account. - Atualizar via Stripe. O frontend chama
POST /createCheckoutSession, que acionaCreateCheckoutSessionHandler: ele resolve o usuário, mapeia oproduct_hashsolicitado para um ID de preço do Stripe e cria umastripe.checkout.Sessionem modo desubscription(aplicando opcionalmente um código de teste gratuito de 30 dias). - Webhook completa o ciclo. O Stripe chama de volta
POST /stripeWebhookemcheckout.session.completed;StripeWebhookHandlerregistra a nova assinatura viaadd_subscription()e chamarefresh_credits(user_email)para reabastecer o saldo do usuário. Eventoscustomer.subscription.updated(cancelamento) e.deletedsão tratados simetricamente. - Gerenciar a assinatura.
POST /createPortalSession(CreatePortalSessionHandler) abre uma sessão do Portal de Faturamento do Stripe com escopo para o nível atual do usuário viaconfig_for_payment_tiers(), de modo que atualizações/diminuições/cancelamentos ocorram através da interface hospedada do Stripe. - Chaves de API.
POST /generateAPIKeyrequer pelo menos 1 crédito e chamagenerate_api_key();GET /getAPIKeysePOST /deleteAPIKeylistam/revogam chaves, cada uma rastreada com um timestamplast_used(touch_api_key_last_used).
Barreiras de abuso¶
verifyAuthForNewSubscriptipns() em db_auth.py limita novas assinaturas por nível por dia (por exemplo, 25/dia para Premium, 5/dia para Enterprise), envia um alerta interno por e-mail em limites definidos (5, 10, 50, 100, 200, 500 novas assinaturas/dia) e bloqueia um usuário de mudar de plano mais de uma vez em um mês contínuo.
Execute localmente¶
A partir da raiz do workspace (anote/panacea):
bash
cd Panacea
cp backend/.env.example backend/.env
docker compose up --build
Defina estes em backend/.env para exercitar o fluxo de faturamento:
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
Encaminhe webhooks do Stripe para seu backend local com o Stripe CLI:
bash
stripe listen --forward-to localhost:5000/stripeWebhook
Experimente¶
```bash
Gere uma chave de API (requer um JWT/sessão autenticada e >=1 crédito)¶
curl -X POST http://localhost:5000/generateAPIKey \
-H "Authorization: Bearer
Verifique o uso com a nova chave de API¶
curl http://localhost:5000/v1/usage \
-H "Authorization: Bearer
Notas para o livro de receitas¶
Combine isso com a receita 07 (Gateway de API Compatível com OpenAI) — as mesmas chaves de API geradas aqui são o que autentica chamadas do AnoteOpenAI. Vale a pena destacar o erro de digitação verifyAuthForNewSubscriptipns no nome da função como uma peculiaridade conhecida se um leitor for procurá-lo no código.