This guide explains best practices for handling errors in your Stripe integration.
Error Handling Strategy
-
Validate Early
- Check inputs before API calls
- Verify required fields
- Validate formats
-
Handle Gracefully
- Show user-friendly messages
- Log errors for debugging
- Provide recovery options
-
Recover Automatically
- Refresh expired keys
- Retry failed operations
- Fall back gracefully
Implementation Examples
Basic Error Handler
class StripeErrorHandler {
static async handle(error: any) {
// 1. Convert to standard format
const standardError = this.standardizeError(error);
// 2. Log error
this.logError(standardError);
// 3. Try recovery
await this.attemptRecovery(standardError);
// 4. Show user message
return this.getUserMessage(standardError);
}
static standardizeError(error: any): ErrorResponse {
if (error.code) return error;
return {
status: error.status || 500,
code: error.code || 6778099,
message: error.message || 'Unknown error'
};
}
}
Checkout Error Handling
async function handleCheckout() {
try {
// 1. Validate inputs
validateCheckoutData(data);
// 2. Create checkout
const response = await iaptic.createStripeCheckout(data);
// 3. Store access key
localStorage.setItem('stripe_access_key', response.accessKey);
// 4. Redirect
window.location.href = response.url;
}
catch (error) {
const message = await StripeErrorHandler.handle(error);
showErrorToUser(message);
}
}
Webhook Error Handling
async function handleWebhook(req: Request, res: Response) {
try {
// 1. Verify signature
const event = verifyWebhookSignature(req);
// 2. Process event
await processStripeEvent(event);
// 3. Return success
res.json({ ok: true });
}
catch (error) {
// Log error details
logger.error('Webhook error:', {
error,
body: req.body,
headers: req.headers
});
// Return appropriate status
const status = error.code === 6778005 ? 401 : 500;
res.status(status).json({
error: error.message
});
}
}
Common Error Scenarios
1. Invalid Access Key
try {
await iaptic.getPurchases();
} catch (error) {
if (error.code === 6778003) {
// Clear invalid key
localStorage.removeItem('stripe_access_key');
// Redirect to login
window.location.href = '/login';
}
}
2. Configuration Error
try {
await iaptic.createStripeCheckout(data);
} catch (error) {
if (error.code === 6778030) {
// Show admin message
showAdminAlert('Stripe configuration missing');
// Log details
logger.error('Stripe config error:', error);
}
}
3. Network Error
class RetryHandler {
static async withRetry<T>(
operation: () => Promise<T>,
maxRetries = 3
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await operation();
} catch (error) {
if (!this.isRetryable(error) || i === maxRetries - 1) {
throw error;
}
await this.delay(Math.pow(2, i) * 1000);
}
}
throw new Error('Max retries exceeded');
}
}
Best Practices
-
Error Logging
- Log with context
- Include request details
- Use structured format
- Set appropriate levels
-
User Experience
- Show clear messages
- Provide next steps
- Maintain context
- Enable self-recovery
-
Monitoring
- Track error rates
- Set up alerts
- Monitor recovery
- Analyze patterns
-
Testing
- Test error paths
- Verify recovery
- Check logging
- Validate messages