11---
22name : riligar-dev-stripe
33type : development
4- description : Stripe payment integration patterns . Use when implementing payments, subscriptions, webhooks, checkout flows, or billing in Elysia/Bun applications.
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. '
55---
66
7- # Stripe Integration Patterns
7+ # Stripe Integration Skill
88
9- > Patterns for integrating Stripe payments in RiLiGar applications.
10-
11- ---
9+ This skill provides a complete workflow for integrating Stripe payments using Elysia (backend) and React (frontend).
1210
1311## Mandatory Guidelines
1412
1513> [ !IMPORTANT]
1614> All work in this skill MUST adhere to:
1715>
18- > - @[ .agent/skills/riligar-dev-backend] (API Standards)
16+ > - @[ .agent/skills/riligar-dev-backend] (Elysia API Standards)
17+ > - @[ .agent/skills/riligar-dev-frontend] (React Patterns)
1918> - @[ .agent/skills/riligar-dev-clean-code] (Clean Code Standards)
2019
2120---
2221
23- ## 1. Core Concepts
22+ ## Quick Reference
2423
25- | Concept | Description |
26- | --- | --- |
27- | ** Customer** | User identity in Stripe |
28- | ** Product** | What you're selling |
29- | ** Price** | How much and billing cycle |
30- | ** Subscription** | Recurring payment |
31- | ** PaymentIntent** | One-time payment |
32- | ** Webhook** | Event notifications |
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+ ```
3337
3438---
3539
36- ## 2. Environment Setup
40+ ## Core Integration Workflow
41+
42+ ### 1. Installation
3743
3844``` bash
39- # .env
45+ # Backend (Elysia)
46+ bun add stripe
47+
48+ # Frontend (React)
49+ bun add @stripe/stripe-js @stripe/react-stripe-js
50+ ```
51+
52+ ### 2. Environment Variables
53+
54+ ``` bash
55+ # Backend .env
4056STRIPE_SECRET_KEY=sk_live_...
4157STRIPE_WEBHOOK_SECRET=whsec_...
42- STRIPE_PUBLISHABLE_KEY=pk_live_...
43- ```
4458
45- > [ !IMPORTANT]
46- > Never expose ` STRIPE_SECRET_KEY ` in frontend code.
59+ # Frontend .env.local
60+ VITE_STRIPE_PUBLISHABLE_KEY=pk_live_...
61+ ```
4762
48- ---
63+ > [ !CAUTION]
64+ > ** STRIPE_SECRET_KEY** is for backend only. Never expose it in frontend code.
4965
50- ## 3. Server-Side Patterns (Elysia)
66+ ### 3. Initialize Stripe
5167
52- ### Initialize Stripe
68+ ** Backend (Elysia) **
5369
5470``` javascript
5571import Stripe from ' stripe'
5672
5773const stripe = new Stripe (process .env .STRIPE_SECRET_KEY )
5874```
5975
60- ### Create Checkout Session
76+ ** Frontend (React) **
6177
6278``` javascript
79+ import { loadStripe } from ' @stripe/stripe-js'
80+
81+ const stripePromise = loadStripe (import .meta.env.VITE_STRIPE_PUBLISHABLE_KEY)
82+ ` ` `
83+
84+ For complete setup patterns, see [stripe-server.js](assets/stripe-server.js) and [stripe-client.js](assets/stripe-client.js).
85+
86+ ---
87+
88+ ## Specialized Guides
89+
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 |
96+
97+ ---
98+
99+ ## Core Concepts
100+
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+
112+ ---
113+
114+ ## Common Tasks
115+
116+ ### Create Checkout Session (Subscription)
117+
118+ ` ` ` javascript
119+ // Backend: POST /api/checkout
63120const session = await stripe .checkout .sessions .create ({
64121 mode: ' subscription' ,
65122 customer_email: user .email ,
66123 line_items: [{ price: priceId, quantity: 1 }],
67124 success_url: ` ${ baseUrl} /success?session_id={CHECKOUT_SESSION_ID}` ,
68- cancel_url: ` ${ baseUrl} /cancel` ,
125+ cancel_url: ` ${ baseUrl} /pricing` ,
126+ metadata: { userId: user .id }
127+ })
128+
129+ return { url: session .url }
130+ ` ` `
131+
132+ ### Redirect to Checkout (React)
133+
134+ ` ` ` javascript
135+ const handleCheckout = async (priceId ) => {
136+ const response = await ky .post (' /api/checkout' , { json: { priceId } }).json ()
137+ window .location .href = response .url
138+ }
139+ ` ` `
140+
141+ ### Open Customer Portal
142+
143+ ` ` ` javascript
144+ // Backend: POST /api/portal
145+ const portal = await stripe .billingPortal .sessions .create ({
146+ customer: user .stripeCustomerId ,
147+ return_url: ` ${ baseUrl} /account`
69148})
149+
150+ return { url: portal .url }
70151` ` `
71152
72- ### Webhook Handler
153+ ### Handle Webhook
73154
74155` ` ` javascript
75- app .post (' /webhook/stripe' , async ({ request, set }) => {
156+ app .post (' /webhook/stripe' , async ({ request }) => {
76157 const sig = request .headers .get (' stripe-signature' )
77158 const body = await request .text ()
78159
79- const event = stripe .webhooks .constructEvent (
80- body,
81- sig,
82- process .env .STRIPE_WEBHOOK_SECRET
83- )
160+ const event = stripe .webhooks .constructEvent (body, sig, process .env .STRIPE_WEBHOOK_SECRET )
84161
85162 switch (event .type ) {
86163 case ' checkout.session.completed' :
@@ -89,9 +166,6 @@ app.post('/webhook/stripe', async ({ request, set }) => {
89166 case ' customer.subscription.updated' :
90167 await handleSubscriptionUpdate (event .data .object )
91168 break
92- case ' customer.subscription.deleted' :
93- await handleSubscriptionCancel (event .data .object )
94- break
95169 }
96170
97171 return { received: true }
@@ -100,53 +174,47 @@ app.post('/webhook/stripe', async ({ request, set }) => {
100174
101175---
102176
103- ## 4. Essential Webhooks
104-
105- | Event | When to Handle |
106- | --- | --- |
107- | ` checkout.session.completed ` | Provision access after payment |
108- | ` customer.subscription.updated ` | Plan changes, renewals |
109- | ` customer.subscription.deleted ` | Cancellation |
110- | ` invoice.payment_failed ` | Payment issues |
111- | ` invoice.paid ` | Successful recurring payment |
112-
113- ---
114-
115- ## 5. Customer Portal
116-
117- ``` javascript
118- const portalSession = await stripe .billingPortal .sessions .create ({
119- customer: customerId,
120- return_url: ` ${ baseUrl} /account` ,
121- })
122- ```
123-
124- ---
125-
126- ## 6. Security Checklist
177+ ## Security Checklist
127178
128- - [ ] Verify webhook signatures
129- - [ ] Use idempotency keys for retries
130- - [ ] Store customer ID in database
131- - [ ] Handle edge cases (expired cards, disputes)
132- - [ ] Test with Stripe CLI locally
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
133185
134186---
135187
136- ## 7. Testing
188+ ## Testing
137189
138190` ` ` bash
139191# Install Stripe CLI
140192brew install stripe/ stripe- cli/ stripe
141193
194+ # Login
195+ stripe login
196+
142197# Forward webhooks to local server
143198stripe listen -- forward- to localhost: 3000 / webhook/ stripe
199+
200+ # Trigger test events
201+ stripe trigger checkout .session .completed
144202` ` `
145203
204+ **Test Cards:**
205+
206+ | Card | Scenario |
207+ | --- | --- |
208+ | ` 4242 4242 4242 4242 ` | Successful payment |
209+ | ` 4000 0000 0000 3220 ` | 3D Secure required |
210+ | ` 4000 0000 0000 9995 ` | Declined |
211+
146212---
147213
148214## Related Skills
149215
150216- @[.agent/skills/riligar-dev-backend]
217+ - @[.agent/skills/riligar-dev-frontend]
151218- @[.agent/skills/riligar-dev-auth-elysia]
219+ - @[.agent/skills/riligar-dev-auth-react]
152220- @[.agent/skills/riligar-tech-stack]
0 commit comments