Files
Kordant/docs/STRIPE_INTEGRATION.md

354 lines
8.1 KiB
Markdown

# Stripe Integration Guide
## Overview
This guide covers the Stripe live API integration for ShieldAI subscription management. The implementation includes webhook handlers, subscription management endpoints, and tier-based feature gating.
## Environment Variables
Add the following to your `.env` file:
```bash
# Stripe Configuration
STRIPE_API_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_FREE_TIER_PRICE_ID=price_...
STRIPE_BASIC_TIER_PRICE_ID=price_...
STRIPE_PLUS_TIER_PRICE_ID=price_...
STRIPE_PREMIUM_TIER_PRICE_ID=price_...
```
## Getting Stripe Live API Keys
### 1. Get Live API Key
1. Go to [Stripe Dashboard](https://dashboard.stripe.com/)
2. Navigate to **Developers****API keys**
3. Toggle **Live mode** (top right corner)
4. Copy the **Secret key** (starts with `sk_live_`)
### 2. Get Webhook Signing Secret
1. In Stripe Dashboard, go to **Developers****Webhooks**
2. Click **Add endpoint**
3. Add your webhook URL: `https://your-api-domain.com/api/v1/billing/webhooks/stripe`
4. Select these events to listen for:
- `customer.subscription.created`
- `customer.subscription.updated`
- `customer.subscription.deleted`
- `invoice.payment_succeeded`
- `invoice.payment_failed`
5. Click **Add endpoint**
6. Copy the **Signing secret** (starts with `whsec_`)
### 3. Create Price IDs for Subscription Tiers
1. Go to **Products** in Stripe Dashboard
2. Create products for each tier:
- Free Tier ( $0/month)
- Basic Tier ($9.99/month)
- Plus Tier ($19.99/month)
- Premium Tier ($49.99/month)
3. For each product, create a recurring price
4. Copy the Price IDs (start with `price_`)
## API Endpoints
### Subscription Management
#### Get Current Subscription
```http
GET /api/v1/billing/subscription
Authorization: Bearer <JWT_TOKEN>
```
Response:
```json
{
"subscription": {
"id": "sub_123",
"status": "active",
"currentPeriodStart": "2026-05-01T00:00:00.000Z",
"currentPeriodEnd": "2026-06-01T00:00:00.000Z",
"cancelAtPeriodEnd": false
},
"customer": {
"id": "cus_123"
}
}
```
#### Create Subscription
```http
POST /api/v1/billing/subscription/create
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
{
"tier": "basic",
"customerId": "cus_123"
}
```
#### Update Subscription Tier
```http
PUT /api/v1/billing/subscription/:subscriptionId/tier
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
{
"tier": "plus"
}
```
#### Cancel Subscription
```http
DELETE /api/v1/billing/subscription/:subscriptionId
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
{
"cancelAtPeriodEnd": true
}
```
#### Get User Tier
```http
GET /api/v1/billing/user/tier
Authorization: Bearer <JWT_TOKEN>
```
Response:
```json
{
"tier": "basic",
"limits": {
"callMinutesLimit": 500,
"smsCountLimit": 2000,
"darkWebScans": 12
}
}
```
#### Create Customer Portal Session
```http
POST /api/v1/billing/customer/portal
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
{
"customerId": "cus_123",
"returnUrl": "https://yourapp.com/billing"
}
```
Response:
```json
{
"url": "https://billing.stripe.com/p/login/...",
"expiresAt": "2026-05-14T14:00:00.000Z"
}
```
#### Get Invoice History
```http
GET /api/v1/billing/invoices?customerId=cus_123
Authorization: Bearer <JWT_TOKEN>
```
### Webhook Handler
#### Stripe Webhook
```http
POST /api/v1/billing/webhooks/stripe
Stripe-Signature: <SIGNATURE>
Content-Type: application/json
<Raw Stripe Event Body>
```
## Webhook Events Handled
### customer.subscription.created
Triggered when a new subscription is created.
### customer.subscription.updated
Triggered when subscription details change (tier upgrade/downgrade, payment method update).
### customer.subscription.deleted
Triggered when a subscription is cancelled.
### invoice.payment_succeeded
Triggered when a payment is successfully processed.
### invoice.payment_failed
Triggered when a payment fails.
## Testing
### Test with Stripe CLI
1. Install [Stripe CLI](https://stripe.com/docs/stripe-cli)
2. Login: `stripe login`
3. Forward webhooks: `stripe listen --forward-to localhost:3000/api/v1/billing/webhooks/stripe`
### Test Events
```bash
# Trigger a subscription created event
stripe trigger customer.subscription.created
# Trigger a payment succeeded event
stripe trigger invoice.payment_succeeded
```
## Mobile App Integration
### React Native Example
```javascript
import { API } from '@shieldai/api-client';
// Get current subscription
const getSubscription = async () => {
try {
const response = await API.get('/billing/subscription');
return response.data;
} catch (error) {
console.error('Failed to fetch subscription:', error);
}
};
// Create subscription
const createSubscription = async (tier, customerId) => {
try {
const response = await API.post('/billing/subscription/create', {
tier,
customerId,
});
return response.data;
} catch (error) {
console.error('Failed to create subscription:', error);
}
};
// Upgrade subscription
const upgradeSubscription = async (subscriptionId, newTier) => {
try {
const response = await API.put(
`/billing/subscription/${subscriptionId}/tier`,
{ tier: newTier }
);
return response.data;
} catch (error) {
console.error('Failed to upgrade subscription:', error);
}
};
// Cancel subscription
const cancelSubscription = async (subscriptionId) => {
try {
const response = await API.delete(
`/billing/subscription/${subscriptionId}`,
{ data: { cancelAtPeriodEnd: true } }
);
return response.data;
} catch (error) {
console.error('Failed to cancel subscription:', error);
}
};
```
## Feature Gating
Use the middleware to protect routes based on subscription tier:
```typescript
import { requireTier } from '@shieldai/shared-billing';
import { SubscriptionTier } from '@shieldai/shared-billing';
// Require minimum tier
fastify.get(
'/premium-feature',
{
preHandler: requireTier([SubscriptionTier.BASIC, SubscriptionTier.PLUS, SubscriptionTier.PREMIUM])
},
async (request, reply) => {
// Only accessible to BASIC tier and above
}
);
// Require specific tier
fastify.get(
'/exclusive-feature',
{
preHandler: requireTier([SubscriptionTier.PREMIUM])
},
async (request, reply) => {
// Only accessible to PREMIUM tier
}
);
```
## Deployment Checklist
- [ ] Set `STRIPE_API_KEY` to live key (not test key)
- [ ] Set `STRIPE_WEBHOOK_SECRET` to live webhook secret
- [ ] Configure webhook endpoint in Stripe Dashboard
- [ ] Verify webhook events are being received
- [ ] Test subscription creation flow
- [ ] Test tier upgrade/downgrade flow
- [ ] Test cancellation flow
- [ ] Verify feature gating works correctly
- [ ] Monitor Stripe dashboard for errors
- [ ] Set up alerts for failed payments
## Production Considerations
### Security
1. **Never expose secret keys** in client-side code
2. **Always verify webhook signatures** on the server
3. **Use HTTPS** for all API endpoints in production
4. **Implement rate limiting** on webhook endpoints
### Error Handling
1. **Idempotency**: Webhook events may be delivered multiple times
2. **Retry logic**: Stripe will retry failed webhook deliveries
3. **Logging**: Log all webhook events for debugging
4. **Alerts**: Set up alerts for payment failures
### Compliance
1. **PCI DSS**: Use Stripe Elements for payment collection
2. **GDPR**: Handle customer data according to regulations
3. **Tax**: Consider tax calculation for different regions
## Troubleshooting
### Webhook Signature Verification Fails
- Ensure `STRIPE_WEBHOOK_SECRET` is correctly set
- Verify the webhook URL matches what's configured in Stripe
- Check that raw body is being captured (not parsed JSON)
### Subscription Creation Fails
- Verify `STRIPE_API_KEY` is valid
- Check that price IDs exist and are active
- Ensure customer ID is valid
### Tier Not Updating
- Verify the new tier's price ID exists
- Check for active subscriptions on the customer
- Review Stripe dashboard for error messages
## Support
For issues or questions:
- Stripe Dashboard: https://dashboard.stripe.com/
- Stripe Docs: https://stripe.com/docs
- Stripe Support: https://support.stripe.com/