A plug-and-play Stripe billing feature for Hono apps, supporting subscription checkout, webhook handling, and efficient subscription status caching.
- Stripe Checkout for Subscriptions: Drop-in endpoint for creating Stripe-hosted subscription checkout sessions.
- Webhook Handling: Secure endpoint for Stripe webhooks, supporting all subscription lifecycle events.
- Subscription Status Caching: Fast, Redis-backed cache for checking if a user has an active subscription.
- Modular, TypeScript-friendly: Designed as a Hono feature/router for easy composition.
- Minimal Configuration: Just provide your Stripe API key, price IDs, and Redis client.
npm install easy-stripe-hono stripe honoSet your Stripe secrets in .env:
STRIPE_API_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...import { Hono } from 'hono'
import { easyStripe } from 'easy-stripe-hono'
import Redis from 'ioredis'
const redis = new Redis(process.env.REDIS_URL)
const apiKey = process.env.STRIPE_API_KEY
const priceIds = ['price_123', 'price_456']
const app = new Hono()
app.route('/billing', easyStripe({
apiKey,
priceIds,
redis,
stripeOptions: { /* optional Stripe config */ }
}))
export default appCreates a Stripe Checkout session for a subscription.
Request Body:
{
"email": "user@example.com",
"priceId": "price_123",
"successUrl": "https://yourapp.com/success",
"cancelUrl": "https://yourapp.com/cancel"
}Response:
{
"url": "https://checkout.stripe.com/pay/cs_test_..."
}Receives Stripe webhook events (e.g., payment, subscription changes).
- Set your webhook endpoint in the Stripe Dashboard to
/billing/stripe-webhook. - The handler verifies the signature and processes events like:
invoice.paidinvoice.payment_failedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deleted
Stripe will expect a 2xx response. Your app can add business logic for each event.
The middleware adds a getSubscriptionStatus(customerId) method to the Stripe client, which:
- Checks Redis for a cached status.
- If not cached, fetches all subscriptions for the customer and checks if any are active/trialing for your configured price IDs.
- Caches the result for 15 minutes (
EX 900).
Example:
const stripe = c.get('stripe')
const isActive = await stripe.getSubscriptionStatus('cus_abc123')Note: Redis is required for caching. If not configured,
getSubscriptionStatuswill throw.
- Attaches a configured Stripe client to each request:
c.get('stripe'). - All endpoints in the feature have access to the same Stripe instance and cache.
import { Hono } from 'hono'
import { easyStripe } from 'easy-stripe-hono'
import Redis from 'ioredis'
const redis = new Redis(process.env.REDIS_URL)
const app = new Hono()
app.route('/saas', easyStripe({
apiKey: process.env.STRIPE_API_KEY,
priceIds: ['price_123'],
redis
}))
export default app- Never expose your Stripe secret key to the frontend.
- Always verify webhook signatures.
- Handle all relevant webhook events for accurate subscription state.
- Keep your price IDs in sync with your Stripe Dashboard.
MIT
Built for the Hono community. Stripe® is a trademark of Stripe, Inc. This project is not affiliated with or endorsed by Stripe.