Skip to main content
Skip to main content

Payment Processing

Mifty provides comprehensive payment processing capabilities through Stripe integration, supporting one-time payments, subscriptions, marketplace functionality, and advanced payment features with built-in security and compliance.

Stripe Payment Integration

💳payment

Stripe Payment Processing

Complete Stripe integration with support for payments, subscriptions, webhooks, and marketplace features

Installation

npm run adapter install stripe

Environment Variables

STRIPE_PUBLISHABLE_KEYRequired

Stripe publishable key for client-side integration

Example: pk_test_51234567890abcdefghijklmnopqrstuvwxyz
STRIPE_SECRET_KEYRequired

Stripe secret key for server-side operations

Example: sk_test_51234567890abcdefghijklmnopqrstuvwxyz
STRIPE_WEBHOOK_SECRETRequired

Webhook endpoint secret for verifying Stripe events

Example: whsec_1234567890abcdefghijklmnopqrstuvwxyz
STRIPE_SUCCESS_URLRequired

URL to redirect after successful payment

Example: https://yourapp.com/payment/success
STRIPE_CANCEL_URLRequired

URL to redirect after cancelled payment

Example: https://yourapp.com/payment/cancel
Complete .env example:
STRIPE_PUBLISHABLE_KEY=pk_test_51234567890abcdefghijklmnopqrstuvwxyz
STRIPE_SECRET_KEY=sk_test_51234567890abcdefghijklmnopqrstuvwxyz
STRIPE_WEBHOOK_SECRET=whsec_1234567890abcdefghijklmnopqrstuvwxyz
STRIPE_SUCCESS_URL=https://yourapp.com/payment/success
STRIPE_CANCEL_URL=https://yourapp.com/payment/cancel

Advanced Payment Features

Marketplace Payments

// Handle marketplace payments with Stripe Connect
const createMarketplacePayment = async (orderData) => {
const paymentIntent = await stripeService.createPaymentIntent({
amount: orderData.totalAmount,
currency: 'usd',
application_fee_amount: orderData.platformFee,
transfer_data: {
destination: orderData.sellerStripeAccountId
},
metadata: {
orderId: orderData.id,
sellerId: orderData.sellerId
}
});

return paymentIntent;
};

Recurring Billing with Usage-Based Pricing

// Set up metered billing
const createUsageBasedSubscription = async (customerId, basePriceId, meteredPriceId) => {
const subscription = await stripeService.createSubscription({
customer: customerId,
items: [
{ price: basePriceId }, // Base monthly fee
{ price: meteredPriceId } // Usage-based pricing
]
});

return subscription;
};

// Report usage
const reportUsage = async (subscriptionItemId, quantity) => {
await stripeService.createUsageRecord(subscriptionItemId, {
quantity: quantity,
timestamp: Math.floor(Date.now() / 1000)
});
};

Payment Security Best Practices

// Implement payment security measures
const securePaymentFlow = {
// 1. Validate payment amounts server-side
validatePayment: (clientAmount, serverAmount) => {
if (clientAmount !== serverAmount) {
throw new Error('Payment amount mismatch');
}
},

// 2. Implement rate limiting
rateLimiter: rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // Limit each IP to 5 payment attempts per windowMs
message: 'Too many payment attempts, please try again later'
}),

// 3. Log all payment activities
logPaymentActivity: (userId, action, details) => {
console.log({
timestamp: new Date().toISOString(),
userId,
action,
details,
ip: req.ip
});
}
};

Testing Payments

Test Card Numbers

Use Stripe's test card numbers for development:

# Successful payments
4242424242424242 # Visa
4000056655665556 # Visa (debit)
5555555555554444 # Mastercard

# Declined payments
4000000000000002 # Generic decline
4000000000009995 # Insufficient funds
4000000000009987 # Lost card

# 3D Secure authentication
4000002760003184 # Requires authentication
4000002500003155 # Authentication fails

Webhook Testing

# Install Stripe CLI for local webhook testing
stripe login
stripe listen --forward-to localhost:3000/api/stripe/webhook

# Trigger test events
stripe trigger payment_intent.succeeded
stripe trigger customer.subscription.created

Compliance and Security

PCI Compliance

  • Never store card details on your servers
  • Use Stripe Elements for secure card input
  • Implement proper HTTPS everywhere
  • Regular security audits and updates

GDPR Compliance

// Handle data deletion requests
const deleteCustomerData = async (customerId) => {
// Delete customer from Stripe
await stripeService.deleteCustomer(customerId);

// Remove from your database
await db.query('DELETE FROM customers WHERE stripe_id = ?', [customerId]);
};

Monitoring and Analytics

Payment Analytics

// Track payment metrics
const paymentAnalytics = {
successRate: async (timeframe) => {
const stats = await db.query(`
SELECT
COUNT(*) as total,
SUM(CASE WHEN status = 'succeeded' THEN 1 ELSE 0 END) as successful
FROM payments
WHERE created_at >= ?
`, [timeframe]);

return (stats.successful / stats.total) * 100;
},

averageOrderValue: async (timeframe) => {
const result = await db.query(`
SELECT AVG(amount) as aov
FROM payments
WHERE status = 'succeeded' AND created_at >= ?
`, [timeframe]);

return result.aov;
}
};

Next Steps

After setting up payment processing, you might want to: