Skip to main content

Integration Guide

This comprehensive guide covers different integration patterns and best practices for implementing InPayCheckout in your application.

Integration Patterns

1. Server-Side Integration

The most secure approach where payment processing happens on your server.

// Server-side payment processing
app.post('/api/payments', async (req, res) => {
try {
const { amount, currency, customer, paymentMethod } = req.body;

const payment = await inpaycheckout.payments.create({
amount,
currency,
customer,
payment_method: paymentMethod,
description: `Payment for order #${req.body.orderId}`
});

res.json({ success: true, paymentId: payment.id });
} catch (error) {
res.status(400).json({ error: error.message });
}
});

2. Client-Side Integration

For better user experience, collect payment details on the client and send to your server.

// Client-side form handling
const form = document.getElementById('payment-form');

form.addEventListener('submit', async (e) => {
e.preventDefault();

const formData = new FormData(form);
const paymentData = {
amount: formData.get('amount'),
currency: formData.get('currency'),
customer: {
email: formData.get('email'),
name: formData.get('name')
},
payment_method: {
type: 'card',
card: {
number: formData.get('cardNumber'),
exp_month: formData.get('expMonth'),
exp_year: formData.get('expYear'),
cvc: formData.get('cvc')
}
}
};

try {
const response = await fetch('/api/payments', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(paymentData)
});

const result = await response.json();

if (result.success) {
// Redirect to success page
window.location.href = '/payment-success';
} else {
// Show error message
showError(result.error);
}
} catch (error) {
showError('Payment failed. Please try again.');
}
});

3. Mobile App Integration

For mobile applications using React Native, Flutter, or native development.

React Native

import InPayCheckout from 'inpaycheckout-react-native';

const PaymentScreen = () => {
const processPayment = async () => {
try {
const payment = await InPayCheckout.createPayment({
amount: 2999,
currency: 'USD',
customer: {
email: 'customer@example.com'
}
});

console.log('Payment successful:', payment.id);
} catch (error) {
console.error('Payment failed:', error);
}
};

return (
<View>
<Button title="Pay Now" onPress={processPayment} />
</View>
);
};

Flutter

import 'package:inpaycheckout_flutter/inpaycheckout_flutter.dart';

class PaymentScreen extends StatefulWidget {
@override
_PaymentScreenState createState() => _PaymentScreenState();
}

class _PaymentScreenState extends State<PaymentScreen> {
Future<void> processPayment() async {
try {
final payment = await InPayCheckout.createPayment(
amount: 2999,
currency: 'USD',
customer: {
'email': 'customer@example.com',
},
);

print('Payment successful: ${payment.id}');
} catch (error) {
print('Payment failed: $error');
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: processPayment,
child: Text('Pay Now'),
),
),
);
}
}

Payment Flows

1. One-Time Payment

Simple payment for a single purchase.

sequenceDiagram
participant C as Customer
participant F as Frontend
participant B as Backend
participant I as InPayCheckout

C->>F: Enter payment details
F->>B: Send payment request
B->>I: Create payment
I->>B: Return payment result
B->>F: Return success/error
F->>C: Show result

2. Subscription Payment

Recurring payments for subscriptions.

// Create subscription
const subscription = await inpaycheckout.subscriptions.create({
customer: 'cus_1234567890',
price: 'price_1234567890',
payment_method: 'pm_1234567890',
billing_cycle_anchor: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60, // 30 days from now
});

// Handle subscription events via webhooks
app.post('/webhook', (req, res) => {
const event = req.body;

switch (event.type) {
case 'subscription.created':
// Handle new subscription
break;
case 'subscription.updated':
// Handle subscription changes
break;
case 'subscription.canceled':
// Handle subscription cancellation
break;
}
});

3. Marketplace Payments

For platforms that facilitate payments between multiple parties.

// Create connected account for seller
const account = await inpaycheckout.accounts.create({
type: 'express',
country: 'US',
email: 'seller@example.com'
});

// Create payment with application fee
const payment = await inpaycheckout.payments.create({
amount: 10000,
currency: 'USD',
customer: 'cus_1234567890',
payment_method: 'pm_1234567890',
application_fee_amount: 300, // 3% fee
transfer_data: {
destination: account.id
}
});

Security Best Practices

1. API Key Security

  • Never expose secret keys in client-side code
  • Use environment variables for API keys
  • Rotate keys regularly
  • Use different keys for different environments
// Good: Server-side only
const inpaycheckout = require('inpaycheckout')(process.env.INPAYCHECKOUT_SECRET_KEY);

// Bad: Never do this
const inpaycheckout = require('inpaycheckout')('sk_live_1234567890abcdef');

2. Webhook Security

Always verify webhook signatures to ensure requests are from InPayCheckout.

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}

app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['inpaycheckout-signature'];
const payload = req.body;

if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(400).send('Invalid signature');
}

// Process webhook
const event = JSON.parse(payload);
// ... handle event
});

3. PCI Compliance

  • Never store card details on your servers
  • Use tokenization for sensitive data
  • Implement proper access controls
  • Regular security audits

Error Handling

1. API Errors

Handle different types of API errors appropriately.

try {
const payment = await inpaycheckout.payments.create(paymentData);
} catch (error) {
switch (error.type) {
case 'card_error':
// Card was declined
showError('Your card was declined. Please try a different card.');
break;
case 'validation_error':
// Invalid request parameters
showError('Please check your payment information.');
break;
case 'api_error':
// API error
showError('Payment service temporarily unavailable. Please try again.');
break;
default:
showError('An unexpected error occurred.');
}
}

2. Network Errors

Implement retry logic for network failures.

async function createPaymentWithRetry(paymentData, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await inpaycheckout.payments.create(paymentData);
} catch (error) {
if (error.type === 'api_error' && i < maxRetries - 1) {
// Wait before retry (exponential backoff)
await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
continue;
}
throw error;
}
}
}

Testing

1. Unit Tests

Test your payment integration logic.

// Jest example
describe('Payment Service', () => {
it('should create payment successfully', async () => {
const mockPayment = {
id: 'pay_1234567890',
status: 'succeeded',
amount: 2999
};

// Mock the API call
jest.spyOn(inpaycheckout.payments, 'create').mockResolvedValue(mockPayment);

const result = await paymentService.createPayment({
amount: 2999,
currency: 'USD',
customer: { email: 'test@example.com' }
});

expect(result).toEqual(mockPayment);
});
});

2. Integration Tests

Test the complete payment flow.

describe('Payment Integration', () => {
it('should process payment end-to-end', async () => {
const response = await request(app)
.post('/api/payments')
.send({
amount: 2999,
currency: 'USD',
customer: { email: 'test@example.com' },
payment_method: {
type: 'card',
card: {
number: '4242424242424242',
exp_month: 12,
exp_year: 2025,
cvc: '123'
}
}
})
.expect(200);

expect(response.body.success).toBe(true);
expect(response.body.paymentId).toBeDefined();
});
});

Performance Optimization

1. Caching

Cache frequently accessed data like customer information.

const redis = require('redis');
const client = redis.createClient();

async function getCustomer(customerId) {
// Try cache first
const cached = await client.get(`customer:${customerId}`);
if (cached) {
return JSON.parse(cached);
}

// Fetch from API
const customer = await inpaycheckout.customers.retrieve(customerId);

// Cache for 1 hour
await client.setex(`customer:${customerId}`, 3600, JSON.stringify(customer));

return customer;
}

2. Async Processing

Process non-critical operations asynchronously.

// Process payment synchronously
const payment = await inpaycheckout.payments.create(paymentData);

// Send confirmation email asynchronously
setImmediate(() => {
emailService.sendConfirmation(payment.customer.email, payment.id);
});

// Update analytics asynchronously
setImmediate(() => {
analytics.track('payment_completed', {
paymentId: payment.id,
amount: payment.amount,
currency: payment.currency
});
});

Monitoring and Analytics

1. Payment Metrics

Track key payment metrics.

// Track payment success rate
const trackPaymentSuccess = (payment) => {
analytics.track('payment_success', {
payment_id: payment.id,
amount: payment.amount,
currency: payment.currency,
payment_method: payment.payment_method.type
});
};

// Track payment failures
const trackPaymentFailure = (error) => {
analytics.track('payment_failure', {
error_type: error.type,
error_code: error.code,
error_message: error.message
});
};

2. Real-time Monitoring

Set up alerts for payment issues.

// Webhook for monitoring
app.post('/webhook', (req, res) => {
const event = req.body;

if (event.type === 'payment.failed') {
// Send alert for failed payments
alerting.sendAlert({
type: 'payment_failed',
paymentId: event.data.id,
amount: event.data.amount,
error: event.data.failure_reason
});
}
});

Next Steps