Stripe Payment Integration Guide
Overview
This guide explains how to integrate Stripe payment processing into the Elite Events application. The integration uses Stripe's Payment Intent API for secure payment handling.
Prerequisites
- A Stripe account (sign up at https://stripe.com)
- Stripe API keys (Secret and Publishable keys)
- Node.js and npm installed
- The application running locally or on a server
Setup Instructions
1. Get Your Stripe Keys
- Go to https://dashboard.stripe.com/apikeys
- Find your Publishable key (starts with
pk_) - Find your Secret key (starts with
sk_) - Use test keys initially (they have
_test_in them)
2. Configure Environment Variables
Add your Stripe keys to .env:
STRIPE_SECRET_KEY="sk_test_YOUR_KEY_HERE"
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_YOUR_KEY_HERE"
Important:
- Keep
STRIPE_SECRET_KEYprivate (server-side only) NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYis safe to expose (used in browser)- Never commit
.envfile to version control
3. Install Dependencies
The required packages are already installed:
stripe: Stripe server SDK@stripe/react-stripe-js: React library for Stripe@stripe/stripe-js: Stripe.js library for payment handling
Architecture
Components
-
StripeProvider (
src/components/providers/StripeProvider.tsx)- Wraps payment components with Stripe Elements context
- Initializes Stripe.js with publishable key
-
StripePaymentForm (
src/components/features/checkout/StripePaymentForm.tsx)- Client component for collecting payment details
- Uses CardElement for secure card input
- Validates and confirms payment with Stripe
-
PaymentForm (
src/components/features/checkout/PaymentForm.tsx)- Legacy payment form with local validation
- Supports multiple payment methods
- Can be used as fallback or alternative
API Routes
-
POST /api/payments/create-intent
- Creates a Stripe PaymentIntent
- Returns
clientSecretfor payment confirmation - Required:
orderId,amount - Authenticated: Yes (requires user session)
- Rate limited: 20 requests per minute per IP
-
POST /api/payments
- Processes payment confirmation
- Updates order status to "SHIPPED"
- Validates payment intent from Stripe
- Authenticated: Yes (requires user session)
- Rate limited: 10 requests per minute per IP
Implementation Guide
Using Stripe in Checkout
// 1. Wrap checkout with StripeProvider in parent layout
import { StripeProvider } from "@/components/providers/StripeProvider";
<StripeProvider>
<Checkout />
</StripeProvider>
// 2. In checkout component, create payment intent
const response = await fetch("/api/payments/create-intent", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
orderId: order.id,
amount: order.total,
}),
});
const { clientSecret } = await response.json();
// 3. Use StripePaymentForm to collect and process payment
<StripePaymentForm
orderId={order.id}
amount={order.total}
clientSecret={clientSecret}
onSuccess={() => router.push(`/order-confirmation/${order.id}`)}
onError={(error) => toast.error(error)}
/>
Testing
Test Card Numbers
Stripe provides test card numbers for different scenarios:
Successful Payment:
- Number:
4242 4242 4242 4242 - Expiry: Any future date (e.g., 12/25)
- CVC: Any 3 digits (e.g., 123)
Insufficient Funds:
- Number:
4000 0000 0000 0002 - Expiry: Any future date
- CVC: Any 3 digits
Declined Card:
- Number:
4000 0000 0000 0069 - Expiry: Any future date
- CVC: Any 3 digits
3D Secure Required:
- Number:
4000 0025 0000 3155 - Expiry: Any future date
- CVC: Any 3 digits
- Then follow the 3DS authentication flow
Testing the Flow
- Create a test order in the checkout
- On the payment form, use a test card number above
- Click "Pay" to process payment
- Check Stripe dashboard for payment intent
- Verify order status updates to "SHIPPED"
Security Considerations
Best Practices
-
Never transmit card data to your server
- Stripe.js handles card tokenization
- Your server only receives payment intents/tokens
-
Use HTTPS in production
- Stripe requires secure connections
- Never use Stripe in development over HTTP
-
Validate on both client and server
- Client-side: Better UX, catches obvious errors
- Server-side: Essential for security
-
Store PaymentIntent IDs
- Save
paymentIntentIdin your database - Use for reconciliation and support
- Save
-
Implement webhooks (optional but recommended)
- Listen for
payment_intent.succeededevents - Handle asynchronous payment confirmations
- Update order status reliably
- Listen for
PCI Compliance
The integration is PCI Level 1 compliant because:
- Card data never touches your server
- Stripe handles tokenization securely
- You never process raw card data
Environment Variables Reference
# Stripe API Keys (from https://dashboard.stripe.com/apikeys)
STRIPE_SECRET_KEY=sk_test_... # Server-side only
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_... # Browser-safe
Troubleshooting
Common Issues
"Stripe not loaded"
- Ensure
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYis set - Check browser console for loading errors
- Verify StripeProvider wraps payment components
"Invalid API Key"
- Check key format (starts with
sk_orpk_) - Ensure no extra spaces in
.env - Restart development server after env changes
"Payment intent creation failed"
- Verify user is authenticated
- Check order exists and belongs to user
- Review rate limiting (20 req/min)
- Check API logs for details
"CardElement not working"
- Ensure component wrapped with
<Elements> - Check Stripe.js loaded successfully
- Verify card element has proper CSS styling
Debug Mode
Enable Stripe debug logging:
// In StripePaymentForm.tsx
const handleSubmit = async (e) => {
console.log("Starting payment...");
console.log("Stripe loaded:", !!stripe);
console.log("Elements ready:", !!elements);
// ... rest of code
};
Check Stripe dashboard:
- Go to https://dashboard.stripe.com/test/logs
- Look for payment intent creation errors
- Review API request/response details
Migration from Mock Payments
If you were using mock payments before:
-
Remove mock payment handler
- Delete
simulatePaymentfunction if using old implementation
- Delete
-
Update checkout flow
- Call
/api/payments/create-intentfirst - Get
clientSecretbefore showing payment form - Show
StripePaymentFormwith client secret
- Call
-
Update order status
- No longer update status manually
- Stripe confirmation triggers
/api/payments - Server updates status automatically
Next Steps
Optional Enhancements
-
Webhook Integration
- Set up Stripe webhooks for async confirmations
- Handle
payment_intent.succeededevents
-
Save Payment Methods
- Allow customers to save cards
- Use
setup_intentfor future payments
-
Subscription Billing
- Create recurring charges
- Manage subscription plans
-
Apple Pay / Google Pay
- Add mobile payment support
- Use
PaymentRequestButtonelement
-
Refund Management
- Process refunds through Stripe dashboard
- Or implement refund API endpoint
Resources
- Stripe Documentation: https://stripe.com/docs
- Stripe React Integration: https://stripe.com/docs/stripe-js/react
- Payment Intent API: https://stripe.com/docs/payments/payment-intents
- Stripe Test Cards: https://stripe.com/docs/testing
Support
For issues or questions:
- Check Stripe Dashboard logs
- Review browser console for errors
- Contact Stripe Support: https://support.stripe.com
- Check application logs for API errors