Security Best Practices
Implementing robust security measures is crucial when handling payments. Follow these best practices to ensure secure integration with lomi.
API Authentication
API Key Security
-
Environment Variables
// Don't hardcode API keys const lomi = new LomiSDK({ apiKey: process.env.LOMI_API_KEY });
-
Key Rotation
- Rotate API keys periodically
- Use different keys for development and production
- Revoke compromised keys immediately
-
Access Control
- Limit API key access to necessary services
- Use test keys for development and testing
- Monitor API key usage for suspicious activity
Request Security
TLS Requirements
All API requests must use HTTPS/TLS:
const api = axios.create({
baseURL: 'https://api.lomi.africa',
headers: {
'x-api-key': process.env.LOMI_API_KEY
}
});
Request Validation
-
Input Sanitization
function sanitizeAmount(amount: number): number { return Math.floor(Math.abs(amount)); } function sanitizePhoneNumber(phone: string): string { return phone.replace(/[^\d+]/g, ''); }
-
Schema Validation
import { z } from 'zod'; const PaymentSchema = z.object({ amount: z.number().positive(), currency: z.enum(['XOF']), provider_codes: z.array(z.string()), merchant_id: z.string() }); function validatePaymentRequest(data: unknown) { return PaymentSchema.parse(data); }
Webhook Security
Signature Verification
Always verify webhook signatures:
import crypto from 'crypto';
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const hmac = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(hmac)
);
}
// Express middleware
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['lomi-signature'];
if (!signature || !verifyWebhookSignature(
req.body,
signature as string,
process.env.WEBHOOK_SECRET
)) {
return res.status(400).json({ error: 'Invalid signature' });
}
// Process webhook
});
Webhook Endpoints
-
Access Control
- Use HTTPS endpoints only
- Implement IP whitelisting
- Rate limit webhook endpoints
-
Error Handling
app.post('/webhook', async (req, res) => { try { // Process webhook res.status(200).send('OK'); } catch (error) { // Log error details securely console.error('Webhook processing error:', error); // Return generic error to caller res.status(500).json({ error: 'Internal server error' }); } });
Data Security
Sensitive Data Handling
-
Data Minimization
// Only collect necessary data const session = await lomi.checkoutSessions.create({ merchant_id: merchantId, amount: amount, currency: 'XOF', provider_codes: ['ORANGE_MONEY'], metadata: { orderId: order.id // Don't include sensitive customer data } });
-
Secure Storage
- Never store full payment details
- Encrypt sensitive data at rest
- Implement proper access controls
Error Logging
// Avoid logging sensitive data
function logError(error: Error, context: object) {
const sanitizedContext = {
...context,
apiKey: '[REDACTED]',
customerPhone: '[REDACTED]'
};
console.error('Error:', {
message: error.message,
stack: error.stack,
context: sanitizedContext
});
}
Network Security
Rate Limiting
Implement rate limiting for your endpoints:
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.use('/api/', limiter);
Timeouts
Set appropriate timeouts:
const api = axios.create({
timeout: 10000, // 10 seconds
headers: {
'x-api-key': process.env.LOMI_API_KEY
}
});
Monitoring and Alerts
-
Activity Monitoring
function monitorAPIUsage(event: APIEvent) { if (event.amount > 1000000) { // Large transaction alertTeam('Large transaction detected', event); } if (event.errorCount > 10) { // Multiple failures alertTeam('Multiple API errors detected', event); } }
-
Suspicious Activity
- Monitor for unusual patterns
- Track failed authentication attempts
- Alert on unexpected volume spikes
Development Practices
-
Code Security
- Keep dependencies updated
- Use security linters
- Conduct regular security reviews
-
Environment Separation
const config = { development: { apiUrl: 'https://sandbox.lomi.africa', webhookSecret: process.env.DEV_WEBHOOK_SECRET }, production: { apiUrl: 'https://api.lomi.africa', webhookSecret: process.env.PROD_WEBHOOK_SECRET } }[process.env.NODE_ENV || 'development'];