@reeboot/strapi-payment-plugin
v0.0.13
Published
Handle payments
Downloads
881
Readme
Strapi Payment Plugin
A comprehensive Stripe integration plugin for Strapi v5 that provides complete payment processing capabilities, customer management, order handling, subscription management, and webhook processing for modern e-commerce applications.
Features
Core Payment Processing
- Payment Intent Creation & Management - Secure payment processing with Stripe Payment Intents
- Customer Management - Create and manage Stripe customers with automatic Strapi synchronization
- Order Processing - Complete order lifecycle management with payment integration
- Refund Processing - Full and partial refund capabilities with audit trails
- Subscription Management - Create, update, and cancel recurring subscriptions via Stripe Billing
- Webhook Handling - Automatic webhook processing with signature verification
Advanced Features
- Real-time Payment Tracking - Live payment status updates via webhooks
- Admin Dashboard - Comprehensive admin interface for payment management
- Analytics & Reporting - Payment analytics, revenue tracking, and customer insights
- Multi-currency Support - Support for multiple currencies and payment methods
- Security First - PCI-compliant payment handling with encrypted data storage
Developer Experience
- TypeScript Support - Full TypeScript typing for all operations
- RESTful API - Clean, documented API endpoints following REST conventions
- Rate Limiting - Built-in rate limiting for sensitive operations
- Error Handling - Comprehensive error handling with detailed logging
- Admin Interface - Modern React-based admin panel with responsive design
Prerequisites
- Strapi v5.33.1+ - Latest Strapi v5 version
- Node.js 20+ - Node.js runtime environment
- Stripe Account - Active Stripe account with API keys
- Database - PostgreSQL, MySQL, or SQLite database
Installation
Method 1: NPM Package (Recommended)
Install the plugin directly from npm:
npm install @reeboot/strapi-payment-plugin
# or
yarn add @reeboot/strapi-payment-pluginThen configure the plugin in config/plugins.ts:
export default () => ({
'payment-plugin': {
enabled: true,
config: {
stripe: {
apiVersion: '2026-03-25.dahlia',
},
payment: {
defaultCurrency: 'usd',
},
},
},
});Method 2: Copy Plugin to Project
Copy the
payment-pluginfolder to your Strapi project's plugins directory:cp -r payment-plugin /path/to/your/strapi-project/src/plugins/Install dependencies:
npm installConfigure the plugin in
config/plugins.ts:export default () => ({ 'payment-plugin': { enabled: true, resolve: './src/plugins/payment-plugin', config: { stripe: { apiVersion: '2026-03-25.dahlia', }, payment: { defaultCurrency: 'usd', }, }, }, });
Method 3: Development Setup
Navigate to the plugin directory:
cd src/plugins/payment-pluginInstall dependencies:
npm installBuild the plugin:
npm run build
Configuration
Environment Variables
Add these to your .env file:
# Stripe API Configuration
STRIPE_API_KEY=sk_test_... # Your Stripe secret key
STRIPE_WEBHOOK_SECRET=whsec_... # Your Stripe webhook endpoint secret
# Alternative configuration
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...Plugin Configuration
Update config/plugins.ts with your settings:
export default () => ({
'payment-plugin': {
enabled: true,
resolve: './src/plugins/payment-plugin',
config: {
stripe: {
apiVersion: '2026-03-25.dahlia',
apiKey: process.env.STRIPE_API_KEY,
webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
},
payment: {
defaultCurrency: 'usd',
},
logging: {
level: 'info',
enableWebhookLogging: true,
enableDebugLogging: false,
},
},
},
});Webhook Raw Body Support (CRITICAL)
For Stripe webhook signature verification to work, you must configure Strapi's body parser middleware to preserve the raw request body.
Update config/middlewares.ts in your Strapi project:
export default [
// ... other middlewares
{
name: 'strapi::body',
config: {
includeUnparsed: true,
},
},
// ... other middlewares
];Without includeUnparsed: true, the webhook verification will fail with an error: "No signatures found matching the expected signature for payload".
Quick Start
1. Create a Customer
const customerData = {
email: '[email protected]',
firstName: 'John',
lastName: 'Doe',
phone: '+1234567890',
address: {
line1: '123 Main St',
city: 'New York',
postal_code: '10001'
}
};
const response = await fetch('/api/payment-plugin/customers', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_JWT_TOKEN'
},
body: JSON.stringify(customerData)
});2. Create a Payment Intent
const paymentData = {
amount: 2500, // $25.00 in cents
currency: 'usd',
customerId: 1, // Optional: Strapi customer ID
orderId: 1, // Optional: Strapi order ID
metadata: {
product_id: 'prod_123',
subscription_type: 'premium'
}
};
const response = await fetch('/api/payment-plugin/payments/create-intent', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_JWT_TOKEN'
},
body: JSON.stringify(paymentData)
});
const result = await response.json();
console.log(result.data.client_secret); // Use this for Stripe Elements3. Handle Payment on Frontend
import { loadStripe } from '@stripe/stripe-js';
const stripe = await loadStripe('pk_test_...');
const { error } = await stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: cardElement,
billing_details: {
name: 'John Doe',
email: '[email protected]'
}
}
});
if (error) {
console.error('Payment failed:', error);
} else {
console.log('Payment succeeded!');
}4. Create a Subscription
const subscriptionData = {
customerId: 1, // Strapi customer ID
priceId: 'price_1234567890', // Stripe Price ID
metadata: {
plan: 'premium'
}
};
const response = await fetch('/api/payment-plugin/subscriptions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_JWT_TOKEN'
},
body: JSON.stringify(subscriptionData)
});5. Process a Refund
const paymentId = 1; // Strapi payment ID
const refundData = {
amount: 500, // Optional: partial refund in cents (omit for full refund)
reason: 'requested_by_customer',
metadata: {
reason: 'customer_request'
}
};
const response = await fetch(`/api/payment-plugin/payments/${paymentId}/refund`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_JWT_TOKEN'
},
body: JSON.stringify(refundData)
});API Documentation
The plugin provides comprehensive REST API endpoints:
Content API Routes
Payments
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | /api/payment-plugin/payments/create-intent | Create a payment intent |
| POST | /api/payment-plugin/payments/confirm/:paymentIntentId | Confirm a payment |
| GET | /api/payment-plugin/payments/:id | Get payment details |
| GET | /api/payment-plugin/payments | List payments (supports page, pageSize, status, customer, order filters) |
| POST | /api/payment-plugin/payments/:id/refund | Process a refund |
Customers
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | /api/payment-plugin/customers | Create a customer |
| GET | /api/payment-plugin/customers/:id | Get customer details |
| GET | /api/payment-plugin/customers | List customers (supports page, pageSize, email filters) |
Orders
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | /api/payment-plugin/orders | Create an order |
| GET | /api/payment-plugin/orders/:id | Get order details |
| GET | /api/payment-plugin/orders | List orders (supports page, pageSize, status, customer filters) |
Subscriptions
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | /api/payment-plugin/subscriptions | Create a subscription |
| GET | /api/payment-plugin/subscriptions | List subscriptions |
| GET | /api/payment-plugin/subscriptions/:id | Get subscription details |
| PUT | /api/payment-plugin/subscriptions/:id | Update a subscription |
| POST | /api/payment-plugin/subscriptions/:id/cancel | Cancel a subscription |
Webhooks
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | /api/payment-plugin/webhook | Handle Stripe webhooks (no auth required) |
Admin API Routes
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /admin/api/payment-plugin/admin/dashboard | Dashboard data |
| GET | /admin/api/payment-plugin/admin/reports | Payment reports |
| GET | /admin/api/payment-plugin/admin/analytics | Analytics data |
| GET | /admin/api/payment-plugin/admin/config | Get plugin configuration |
| PUT | /admin/api/payment-plugin/admin/config | Update plugin configuration |
| GET | /admin/api/payment-plugin/admin/payments | List all payments |
| POST | /admin/api/payment-plugin/admin/payments/:id/refund | Admin refund |
| GET | /admin/api/payment-plugin/admin/customers | List all customers |
| GET | /admin/api/payment-plugin/admin/orders | List all orders |
| GET | /admin/api/payment-plugin/admin/subscriptions | List all subscriptions |
| POST | /admin/api/payment-plugin/admin/subscriptions/:id/cancel | Cancel a subscription |
| POST | /admin/api/payment-plugin/admin/test-webhook | Test webhook processing |
| POST | /admin/api/payment-plugin/admin/initialize-payment | Initialize a payment flow |
| POST | /admin/api/payment-plugin/admin/create-sample-payment | Create a sample payment |
For detailed API documentation with request/response examples, see PAYMENT_ROUTES_DOCUMENTATION.md.
Content Types
The plugin registers the following content types:
Payment
| Field | Type | Description |
|-------|------|-------------|
| stripe_payment_intent_id | string (unique, required) | Links to Stripe payment intent |
| amount | decimal (min: 0) | Payment amount in cents |
| currency | string (default: "usd") | Currency code |
| payment_status | enum | pending, succeeded, failed, canceled, refunded |
| payment_method | string | Payment method used |
| metadata | json | Additional data |
| customer | relation (manyToOne) | Relation to Customer |
| order | relation (manyToOne) | Relation to Order |
Customer
| Field | Type | Description |
|-------|------|-------------|
| email | email (unique, required) | Customer email |
| stripe_customer_id | string (unique, required) | Links to Stripe customer |
| first_name | string (required) | First name |
| last_name | string (required) | Last name |
| phone | string | Phone number |
| address | json | Address information |
| metadata | json | Additional data |
Order
| Field | Type | Description |
|-------|------|-------------|
| order_number | string (unique, required) | Unique order identifier |
| total_amount | decimal (min: 0) | Order total in cents |
| currency | string (default: "usd") | Currency code |
| order_status | enum | pending, processing, completed, failed, refunded |
| payment_status | enum | unpaid, paid, partially_paid, refunded |
| customer | relation (manyToOne) | Relation to Customer |
| items | json (required) | Order line items |
| metadata | json | Additional data |
Subscription
| Field | Type | Description |
|-------|------|-------------|
| stripe_subscription_id | string (unique, required) | Links to Stripe subscription |
| stripe_customer_id | string (required) | Stripe customer ID |
| stripe_price_id | string (required) | Stripe price ID |
| stripe_product_id | string | Stripe product ID |
| status | enum | active, canceled, incomplete, incomplete_expired, past_due, paused, trialing, unpaid |
| current_period_start | datetime | Start of current billing period |
| current_period_end | datetime | End of current billing period |
| cancel_at_period_end | boolean (default: false) | Cancel at period end |
| canceled_at | datetime | Cancellation timestamp |
| trial_start | datetime | Trial start date |
| trial_end | datetime | Trial end date |
| latest_invoice_id | string | Latest Stripe invoice ID |
| metadata | json | Additional data |
| customer | relation (manyToOne) | Relation to Customer |
Webhook Events
The plugin processes these Stripe webhook events automatically:
| Event | Description |
|-------|-------------|
| payment_intent.succeeded | Payment completed successfully |
| payment_intent.processing | Payment is processing |
| payment_intent.payment_failed | Payment failed |
| payment_intent.canceled | Payment was canceled |
| charge.refunded | Charge was refunded |
| customer.created | New Stripe customer created |
| customer.subscription.created | Subscription created |
| customer.subscription.updated | Subscription updated |
| customer.subscription.deleted | Subscription canceled/deleted |
| invoice.payment_succeeded | Invoice payment succeeded |
| invoice.payment_failed | Invoice payment failed |
Security
Payment Security
- PCI Compliance - Stripe handles all sensitive payment data
- Webhook Verification - All webhooks are cryptographically verified using Stripe signatures
- Audit Logging - All payment operations are logged for compliance
Access Control
- JWT Authentication - All content API endpoints require valid authentication
- Admin Authentication - Admin routes require authenticated admin users
- Rate Limiting - 10 requests per minute per IP for sensitive operations
- Input Sanitization - Built-in XSS protection and input validation
Development
Project Structure
src/plugins/payment-plugin/
├── admin/ # Admin panel React components
│ └── src/
│ ├── components/ # UI components
│ ├── pages/ # Admin pages (Dashboard, Payments, Customers,
│ │ # Orders, Subscriptions, Analytics, Settings)
│ ├── types/ # TypeScript definitions
│ └── utils/ # Helper utilities
├── server/ # Server-side code
│ └── src/
│ ├── controllers/ # API controllers
│ ├── services/ # Business logic (Stripe service)
│ ├── routes/ # API route definitions
│ ├── content-types/ # Database schemas
│ ├── middlewares/ # Webhook validator, rate limiter, input sanitizer
│ ├── policies/ # Access control policies
│ └── types/ # Plugin configuration types
├── docs/ # Documentation
├── package.json # Plugin dependencies
└── README.md # This fileBuilding and Development
# Install dependencies
npm install
# Build for production
npm run build
# Watch for changes during development
npm run watch
# Verify plugin structure
npm run verify
# Type checking
npm run test:ts:front # Frontend TypeScript
npm run test:ts:back # Backend TypeScriptTroubleshooting
Common Issues
"Stripe API key not found"
- Ensure
STRIPE_API_KEYorSTRIPE_SECRET_KEYis set in your environment variables - Check that the key starts with
sk_test_(test) orsk_live_(live) - Verify the key has the correct permissions
"Webhook signature verification fails"
- Ensure
STRIPE_WEBHOOK_SECRETis configured - Verify
includeUnparsed: trueis set inconfig/middlewares.tsfor thestrapi::bodymiddleware - Check that the webhook endpoint URL matches Stripe Dashboard configuration
- Ensure your webhook endpoint is publicly accessible
"Failed to create Strapi payment record"
- Ensure content types are properly registered
- Check database permissions and connectivity
- Verify all required fields are provided
Debug Mode
Enable detailed logging:
// config/plugins.ts
'payment-plugin': {
config: {
logging: {
level: 'debug',
enableWebhookLogging: true,
enableDebugLogging: true,
},
},
},Documentation
Additional documentation is available in the docs/ directory:
See also:
- Stripe Service Documentation - Detailed service-level documentation
- Payment Routes Documentation - Complete API endpoint documentation
- Changelog - Version history
- Strapi v5 Migration Guide
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Submit a pull request
Development Guidelines
- Follow TypeScript best practices
- Include unit tests for new features
- Update documentation for any API changes
- Follow the existing code style and formatting
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Strapi - The Headless CMS
- Stripe - Payment processing
- Stripe Elements - Payment UI components
