Skip to content

Commit 4cc9ca6

Browse files
committed
feat: Improve Stripe integration skill description and setup workflow
1 parent 320dc83 commit 4cc9ca6

File tree

2 files changed

+179
-142
lines changed

2 files changed

+179
-142
lines changed
Lines changed: 178 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -1,213 +1,251 @@
11
---
22
name: riligar-dev-stripe
3-
type: development
4-
description: 'Complete guide for Stripe payment integration in RiLiGar applications. Use when implementing: (1) Checkout flows (hosted or embedded), (2) Subscription management, (3) Webhook handlers, (4) Customer portal, (5) One-time payments, (6) Database schema for billing.'
3+
description: 'Interactive Stripe setup wizard. Use when implementing payments. The agent will ask for keys, products, and configure everything automatically.'
54
---
65

7-
# Stripe Integration Skill
6+
# Stripe Setup Wizard
87

9-
This skill provides a complete workflow for integrating Stripe payments using Elysia (backend) and React (frontend).
10-
11-
## Mandatory Guidelines
12-
13-
> [!IMPORTANT]
14-
> All work in this skill MUST adhere to:
15-
>
16-
> - @[.agent/skills/riligar-dev-backend] (Elysia API Standards)
17-
> - @[.agent/skills/riligar-dev-frontend] (React Patterns)
18-
> - @[.agent/skills/riligar-dev-clean-code] (Clean Code Standards)
8+
Esta skill configura a integração completa do Stripe no seu projeto. O agente vai guiar você através de um setup interativo.
199

2010
---
2111

22-
## Quick Reference
12+
## Setup Workflow
2313

24-
```
25-
Stripe Flow:
26-
┌─────────────────────────────────────────────────────────────────────┐
27-
│ Frontend (React) │ Backend (Elysia) │
28-
├────────────────────────────────┼────────────────────────────────────┤
29-
│ 1. User clicks "Subscribe" │ │
30-
│ 2. Call POST /checkout │ → 3. Create checkout session │
31-
│ 4. Redirect to Stripe │ │
32-
│ │ 5. Webhook: checkout.completed │
33-
│ │ 6. Update database │
34-
│ 7. Redirect to success_url │ │
35-
└────────────────────────────────┴────────────────────────────────────┘
36-
```
37-
38-
---
14+
Quando o usuário solicitar configurar o Stripe, siga este fluxo **OBRIGATÓRIO**:
3915

40-
## Core Integration Workflow
16+
### Step 1: Coletar Chaves
4117

42-
### 1. Installation
18+
Pergunte ao usuário:
4319

44-
```bash
45-
# Backend (Elysia)
46-
bun add stripe
47-
48-
# Frontend (React)
49-
bun add @stripe/stripe-js @stripe/react-stripe-js
50-
```
20+
> Para configurar o Stripe, preciso das suas chaves da API.
21+
> Você pode encontrá-las em: https://dashboard.stripe.com/apikeys
22+
>
23+
> Por favor, me forneça:
24+
> 1. **Publishable Key** (pk_live_... ou pk_test_...)
25+
> 2. **Secret Key** (sk_live_... ou sk_test_...)
5126
52-
### 2. Environment Variables
27+
Aguarde as chaves antes de prosseguir.
5328

54-
```bash
55-
# Backend .env
56-
STRIPE_SECRET_KEY=sk_live_...
57-
STRIPE_WEBHOOK_SECRET=whsec_...
29+
### Step 2: Identificar Produtos
5830

59-
# Frontend .env.local
60-
VITE_STRIPE_PUBLISHABLE_KEY=pk_live_...
61-
```
31+
Após receber as chaves, pergunte:
6232

63-
> [!CAUTION]
64-
> **STRIPE_SECRET_KEY** is for backend only. Never expose it in frontend code.
33+
> Agora preciso entender seus produtos. Me diga:
34+
>
35+
> 1. **Tipo de cobrança**: Assinatura (recorrente) ou pagamento único?
36+
> 2. **Quais planos/produtos** você quer oferecer?
37+
>
38+
> Exemplo de resposta:
39+
> - Assinatura mensal
40+
> - Plano Starter: R$ 29/mês (5 projetos, suporte email)
41+
> - Plano Pro: R$ 99/mês (ilimitado, suporte prioritário)
42+
> - Plano Enterprise: R$ 299/mês (tudo + SLA)
6543
66-
### 3. Initialize Stripe
44+
### Step 3: Criar Produtos no Stripe
6745

68-
**Backend (Elysia)**
46+
Com as informações coletadas, gere o script para criar os produtos:
6947

7048
```javascript
49+
// scripts/setup-stripe-products.js
7150
import Stripe from 'stripe'
7251

73-
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY)
74-
```
75-
76-
**Frontend (React)**
52+
const stripe = new Stripe('SK_KEY_AQUI')
53+
54+
async function setupProducts() {
55+
const products = [
56+
// Substituir com os produtos do usuário
57+
{
58+
name: 'Plano Starter',
59+
description: '5 projetos, suporte email',
60+
price: 2900, // R$ 29,00 em centavos
61+
interval: 'month',
62+
features: ['5 projetos', 'Suporte email', '1GB storage']
63+
},
64+
{
65+
name: 'Plano Pro',
66+
description: 'Ilimitado, suporte prioritário',
67+
price: 9900, // R$ 99,00 em centavos
68+
interval: 'month',
69+
features: ['Projetos ilimitados', 'Suporte prioritário', '10GB storage']
70+
}
71+
]
72+
73+
console.log('Criando produtos no Stripe...\n')
74+
75+
for (const product of products) {
76+
const stripeProduct = await stripe.products.create({
77+
name: product.name,
78+
description: product.description,
79+
metadata: { features: JSON.stringify(product.features) }
80+
})
81+
82+
const stripePrice = await stripe.prices.create({
83+
product: stripeProduct.id,
84+
unit_amount: product.price,
85+
currency: 'brl',
86+
recurring: product.interval ? { interval: product.interval } : undefined
87+
})
88+
89+
console.log(`${product.name}`)
90+
console.log(` Product ID: ${stripeProduct.id}`)
91+
console.log(` Price ID: ${stripePrice.id}\n`)
92+
}
7793

78-
```javascript
79-
import { loadStripe } from '@stripe/stripe-js'
94+
console.log('Produtos criados com sucesso!')
95+
}
8096

81-
const stripePromise = loadStripe(import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY)
97+
setupProducts().catch(console.error)
8298
```
8399

84-
For complete setup patterns, see [stripe-server.js](assets/stripe-server.js) and [stripe-client.js](assets/stripe-client.js).
100+
Instrua o usuário a executar: `bun run scripts/setup-stripe-products.js`
85101

86-
---
87-
88-
## Specialized Guides
102+
### Step 4: Coletar Price IDs
89103

90-
| Guide | Content |
91-
| --- | --- |
92-
| [stripe-elysia.md](references/stripe-elysia.md) | Backend routes, checkout, customer management |
93-
| [stripe-react.md](references/stripe-react.md) | Frontend components, Elements, forms |
94-
| [stripe-webhooks.md](references/stripe-webhooks.md) | Event handling, signature verification |
95-
| [stripe-database.md](references/stripe-database.md) | Drizzle schema for billing data |
104+
Após executar o script, peça:
96105

97-
---
106+
> O script gerou os Price IDs. Por favor, me envie os IDs gerados.
107+
> Exemplo: price_1ABC123...
98108
99-
## Core Concepts
109+
### Step 5: Configurar Ambiente
100110

101-
| Concept | Description |
102-
| --- | --- |
103-
| **Customer** | User identity in Stripe (link to your user table) |
104-
| **Product** | What you're selling (Pro Plan, Enterprise) |
105-
| **Price** | Amount and billing cycle (monthly, yearly) |
106-
| **Subscription** | Recurring payment relationship |
107-
| **PaymentIntent** | One-time payment flow |
108-
| **Checkout Session** | Hosted payment page |
109-
| **Customer Portal** | Self-service billing management |
110-
| **Webhook** | Server-to-server event notifications |
111+
Com as chaves e Price IDs, configure os arquivos de ambiente:
111112

112-
---
113+
**Backend: `.env.development` e `.env.production`**
114+
```bash
115+
# .env.development (chaves de teste)
116+
STRIPE_SECRET_KEY=sk_test_...
117+
STRIPE_WEBHOOK_SECRET=whsec_...
113118

114-
## Common Tasks
119+
# .env.production (chaves de produção)
120+
STRIPE_SECRET_KEY=sk_live_...
121+
STRIPE_WEBHOOK_SECRET=whsec_...
122+
```
115123

116-
### Create Checkout Session (Subscription)
124+
**Frontend: `.env.development` e `.env.production`**
125+
```bash
126+
# .env.development
127+
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_...
117128

118-
```javascript
119-
// Backend: POST /api/checkout
120-
const session = await stripe.checkout.sessions.create({
121-
mode: 'subscription',
122-
customer_email: user.email,
123-
line_items: [{ price: priceId, quantity: 1 }],
124-
success_url: `${baseUrl}/success?session_id={CHECKOUT_SESSION_ID}`,
125-
cancel_url: `${baseUrl}/pricing`,
126-
metadata: { userId: user.id }
127-
})
128-
129-
return { url: session.url }
129+
# .env.production
130+
VITE_STRIPE_PUBLISHABLE_KEY=pk_live_...
130131
```
131132

132-
### Redirect to Checkout (React)
133+
### Step 6: Configurar Database
134+
135+
Gere a migration para adicionar campos do Stripe:
133136

134137
```javascript
135-
const handleCheckout = async (priceId) => {
136-
const response = await ky.post('/api/checkout', { json: { priceId } }).json()
137-
window.location.href = response.url
138-
}
138+
// database/schema.js - adicionar aos users
139+
stripeCustomerId: text('stripe_customer_id').unique(),
140+
stripeSubscriptionId: text('stripe_subscription_id').unique(),
141+
plan: text('plan').default('free'),
142+
subscriptionStatus: text('subscription_status'),
143+
currentPeriodEnd: integer('current_period_end', { mode: 'timestamp' }),
139144
```
140145

141-
### Open Customer Portal
146+
### Step 7: Configurar Webhook
142147

143-
```javascript
144-
// Backend: POST /api/portal
145-
const portal = await stripe.billingPortal.sessions.create({
146-
customer: user.stripeCustomerId,
147-
return_url: `${baseUrl}/account`
148-
})
148+
Instrua o usuário:
149149

150-
return { url: portal.url }
151-
```
150+
> Configure o webhook no Stripe Dashboard:
151+
>
152+
> 1. Acesse https://dashboard.stripe.com/webhooks
153+
> 2. Clique em "Add endpoint"
154+
> 3. URL: `https://seu-dominio.com/webhook/stripe`
155+
> 4. Selecione os eventos:
156+
> - `checkout.session.completed`
157+
> - `customer.subscription.updated`
158+
> - `customer.subscription.deleted`
159+
> - `invoice.paid`
160+
> - `invoice.payment_failed`
161+
> 5. Copie o "Signing secret" (whsec_...)
162+
> 6. Adicione ao `.env.development` e `.env.production`
163+
164+
### Step 8: Gerar Código
165+
166+
Gere todos os arquivos necessários usando os templates de [assets/](assets/):
167+
168+
| Arquivo | Baseado em |
169+
| --- | --- |
170+
| `plugins/stripe.js` | stripe-server.js (seção 1) |
171+
| `routes/billing.js` | stripe-server.js (seção 2) |
172+
| `routes/webhook.js` | stripe-server.js (seção 3) |
173+
| `services/billing.js` | stripe-server.js (seção 4) |
174+
| `config/stripe-prices.js` | Price IDs coletados |
175+
| `pages/Pricing.jsx` | stripe-client.js (seção 3) |
176+
| `components/BillingSettings.jsx` | stripe-client.js (seção 4) |
177+
| `hooks/useSubscription.js` | stripe-client.js (seção 2) |
178+
179+
### Step 9: Criar Config de Preços
152180

153-
### Handle Webhook
181+
Gere o arquivo de configuração com os Price IDs:
154182

155183
```javascript
156-
app.post('/webhook/stripe', async ({ request }) => {
157-
const sig = request.headers.get('stripe-signature')
158-
const body = await request.text()
159-
160-
const event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET)
161-
162-
switch (event.type) {
163-
case 'checkout.session.completed':
164-
await handleCheckoutComplete(event.data.object)
165-
break
166-
case 'customer.subscription.updated':
167-
await handleSubscriptionUpdate(event.data.object)
168-
break
184+
// config/stripe-prices.js
185+
export const STRIPE_PRICES = {
186+
starter: {
187+
priceId: 'price_COLETADO_STARTER',
188+
name: 'Starter',
189+
price: 29,
190+
features: ['5 projetos', 'Suporte email', '1GB storage']
191+
},
192+
pro: {
193+
priceId: 'price_COLETADO_PRO',
194+
name: 'Pro',
195+
price: 99,
196+
features: ['Projetos ilimitados', 'Suporte prioritário', '10GB storage']
169197
}
198+
}
170199

171-
return { received: true }
172-
})
200+
export const getPrice = (plan) => STRIPE_PRICES[plan]
201+
export const getPriceId = (plan) => STRIPE_PRICES[plan]?.priceId
173202
```
174203
175204
---
176205
177-
## Security Checklist
206+
## Checklist Final
207+
208+
Ao completar o setup, confirme:
178209
179-
- [ ] Webhook signatures verified with `constructEvent`
180-
- [ ] Secret key only in backend environment
181-
- [ ] Customer ID stored in database
182-
- [ ] Idempotency keys for create operations
183-
- [ ] Prices validated server-side (never trust frontend)
184-
- [ ] Subscription status checked before granting access
210+
- [ ] Dependências instaladas (`bun add stripe @stripe/stripe-js @stripe/react-stripe-js`)
211+
- [ ] Chaves no `.env.development` e `.env.production` (backend e frontend)
212+
- [ ] Produtos criados no Stripe
213+
- [ ] Price IDs configurados em `config/stripe-prices.js`
214+
- [ ] Schema do database atualizado
215+
- [ ] Webhook endpoint configurado no Stripe Dashboard
216+
- [ ] Webhook secret nos arquivos de ambiente
217+
- [ ] Rotas de billing funcionando
218+
- [ ] Página de pricing criada
219+
- [ ] Testado com cartão 4242 4242 4242 4242
185220
186221
---
187222
188-
## Testing
223+
## Testing Local
189224
190225
```bash
191-
# Install Stripe CLI
226+
# Instalar Stripe CLI
192227
brew install stripe/stripe-cli/stripe
193228

194229
# Login
195230
stripe login
196231

197-
# Forward webhooks to local server
232+
# Forward webhooks
198233
stripe listen --forward-to localhost:3000/webhook/stripe
199234

200-
# Trigger test events
235+
# Testar checkout
201236
stripe trigger checkout.session.completed
202237
```
203238

204-
**Test Cards:**
239+
---
240+
241+
## Specialized Guides
205242

206-
| Card | Scenario |
243+
| Guide | Content |
207244
| --- | --- |
208-
| `4242 4242 4242 4242` | Successful payment |
209-
| `4000 0000 0000 3220` | 3D Secure required |
210-
| `4000 0000 0000 9995` | Declined |
245+
| [stripe-elysia.md](references/stripe-elysia.md) | Backend routes completas |
246+
| [stripe-react.md](references/stripe-react.md) | Componentes React/Mantine |
247+
| [stripe-webhooks.md](references/stripe-webhooks.md) | Handlers de eventos |
248+
| [stripe-database.md](references/stripe-database.md) | Schema Drizzle |
211249

212250
---
213251

@@ -216,5 +254,4 @@ stripe trigger checkout.session.completed
216254
- @[.agent/skills/riligar-dev-backend]
217255
- @[.agent/skills/riligar-dev-frontend]
218256
- @[.agent/skills/riligar-dev-auth-elysia]
219-
- @[.agent/skills/riligar-dev-auth-react]
220257
- @[.agent/skills/riligar-tech-stack]

0 commit comments

Comments
 (0)