What You'll Learn
Why Payment Security Matters
When handling financial transactions, security isn't optional—it's fundamental. A single security breach can result in data theft, financial losses, regulatory violations, and irreparable damage to your business reputation.
SWIFT-WALLET implements multiple layers of security, but it's your responsibility to secure your integration properly. This guide covers essential security practices to protect your API keys, validate webhooks, and prevent common vulnerabilities.
Security Breach Consequences
- Financial losses from fraudulent transactions
- Customer data exposure and privacy violations
- Regulatory penalties and compliance issues
- Loss of customer trust and business reputation
- Potential legal liabilities
API Key Management Best Practices
Your API key is the single most important credential for SWIFT-WALLET integration. Treat it like a password to your bank account.
Never Expose API Keys
API keys should never appear in:
- Client-side code (JavaScript, mobile apps)
- Public repositories (GitHub, GitLab, etc.)
- Version control commit history
- Screenshots or documentation
- Email communications
- Log files or error messages
Use Environment Variables
// BAD - Never hardcode API keys
$apiKey = 'sk_live_abc123xyz789';
// GOOD - Use environment variables
$apiKey = getenv('SWIFT_WALLET_API_KEY');
// or
$apiKey = $_ENV['SWIFT_WALLET_API_KEY'];
.env File Protection
# .env file (Add to .gitignore!)
SWIFT_WALLET_API_KEY=sk_live_abc123xyz789
# .gitignore (Create if doesn't exist)
.env
.env.local
.env.production
*.key
*.pem
API Key Rotation
Regularly rotate your API keys to minimize the impact of potential leaks:
- Generate a new API key in your dashboard
- Update your environment variables with the new key
- Test your integration with the new key
- Revoke the old key after confirming everything works
Rotation Schedule
Rotate your API keys at least every 90 days, or immediately if you suspect a compromise.
Securing Callback URLs
Callback URLs must be publicly accessible, but that doesn't mean they should be vulnerable. Implement proper security measures.
Use HTTPS Only
Always use HTTPS for callback URLs. HTTP connections are unencrypted and vulnerable to man-in-the-middle attacks.
Critical
SWIFT-WALLET will not send callbacks to HTTP endpoints. You must use HTTPS with a valid SSL certificate.
Implement IP Whitelisting (Optional)
Restrict callback requests to specific IP addresses. Contact support to get SWIFT-WALLET's server IPs for whitelisting.
// PHP: IP Whitelist Check
function isAllowedIP($ip) {
$allowedIPs = [
'192.0.2.1',
'198.51.100.1',
// Add more SWIFT-WALLET server IPs
];
return in_array($ip, $allowedIPs);
}
// Check before processing
if (!isAllowedIP($_SERVER['REMOTE_ADDR'])) {
http_response_code(403);
exit('Forbidden');
}
Validate Request Method
Only accept POST requests for callbacks:
// PHP: Validate request method
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('Method not allowed');
}
Validating Webhook Signatures
SWIFT-WALLET signs every webhook with a secret signature. Always verify this signature to ensure the callback is legitimate.
Why Signature Verification Matters
- Prevents malicious requests from reaching your system
- Ensures callbacks are actually from SWIFT-WALLET
- Protects against replay attacks
- Provides data integrity verification
Signature Verification (PHP)
function verifyWebhookSignature($payload, $signature, $secret) {
// Get the raw request body
$expectedSignature = hash_hmac('sha256', $payload, $secret);
// Use constant-time comparison to prevent timing attacks
return hash_equals($expectedSignature, $signature);
}
// Usage in callback handler
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_SWIFT_SIGNATURE'] ?? '';
// Get secret from environment
$secret = getenv('SWIFT_WALLET_WEBHOOK_SECRET');
if (!verifyWebhookSignature($payload, $signature, $secret)) {
http_response_code(401);
exit('Invalid signature');
}
// Process the callback
$data = json_decode($payload, true);
// ... rest of callback processing
Signature Verification (JavaScript)
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
// Use constant-time comparison
return crypto.timingSafeEqual(
Buffer.from(expectedSignature),
Buffer.from(signature)
);
}
// Express.js example
app.post('/callback', (req, res) => {
const payload = JSON.stringify(req.body);
const signature = req.headers['x-swift-signature'];
const secret = process.env.SWIFT_WALLET_WEBHOOK_SECRET;
if (!verifyWebhookSignature(payload, signature, secret)) {
return res.status(401).send('Invalid signature');
}
// Process callback
processCallback(req.body);
res.status(200).send('OK');
});
HTTPS and SSL Requirements
All communications with SWIFT-WALLET API and callback endpoints must use HTTPS with valid SSL certificates.
SSL Certificate Requirements
- Certificate must be valid and not expired
- Certificate must be issued by a trusted CA
- Certificate must match your domain name
- Use TLS 1.2 or higher
Preventing SSL Certificate Issues
- Monitor certificate expiration dates
- Set up auto-renewal (Let's Encrypt, etc.)
- Use certificate monitoring services
- Keep server SSL libraries updated
Free SSL Certificates
Use Let's Encrypt for free SSL certificates that renew automatically. Most hosting providers offer one-click SSL certificate installation.
Rate Limiting and DDoS Protection
Protect your callback endpoints from abuse with rate limiting.
Implement Rate Limiting
// PHP: Simple rate limiting using Redis
function checkRateLimit($ip, $maxRequests = 100, $window = 3600) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$key = "rate_limit:$ip";
$requests = $redis->incr($key);
if ($requests === 1) {
$redis->expire($key, $window);
}
return $requests <= $maxRequests;
}
// Usage
if (!checkRateLimit($_SERVER['REMOTE_ADDR'])) {
http_response_code(429);
exit('Too many requests');
}
Use Cloud Protection Services
Consider using services like:
- Cloudflare for DDoS protection
- AWS WAF for web application firewall
- Nginx rate limiting module
- Fail2ban for brute force protection
Logging and Monitoring
Comprehensive logging helps detect security issues and troubleshoot problems.
What to Log
- All API requests with timestamps
- Callback requests and responses
- Failed authentication attempts
- Rate limit violations
- Unusual activity patterns
- Error messages and stack traces
Secure Logging Practices
// PHP: Secure logging (sanitize sensitive data)
function logCallback($data) {
// Remove sensitive fields before logging
$sanitized = $data;
unset($sanitized['mpesa_receipt']);
unset($sanitized['customer_id']);
error_log(json_encode([
'timestamp' => date('Y-m-d H:i:s'),
'event' => 'callback_received',
'transaction_id' => $data['transaction_id'],
'status' => $data['status'],
// ... sanitized data
]));
}
// Always use file permissions
chmod('/var/log/app.log', 0600); // Read/write for owner only
Set Up Alerts
Configure alerts for:
- Multiple failed authentication attempts
- Unexpected callback activity
- API key usage from unknown IPs
- Unusual transaction patterns
- SSL certificate expiration
Environment Variables and Secrets Management
Never store secrets in code. Use environment variables or secret management services.
.env File Setup (PHP)
# Load .env file (use vlucas/phpdotenv package)
require __DIR__ . '/vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
# Now access securely
$apiKey = $_ENV['SWIFT_WALLET_API_KEY'];
$webhookSecret = $_ENV['SWIFT_WALLET_WEBHOOK_SECRET'];
Using Secrets Manager
For production environments, use dedicated secrets management services:
- AWS Secrets Manager: For AWS-hosted applications
- HashiCorp Vault: Enterprise-grade secret management
- Azure Key Vault: For Azure-hosted applications
- Google Secret Manager: For GCP-hosted applications
Common Security Mistakes to Avoid
1. Exposing API Keys in Source Code
Anti-Pattern
const API_KEY = 'sk_live_abc123'; // NEVER DO THIS
2. Skipping Signature Verification
Always verify webhook signatures. Accepting unverified callbacks is like accepting cash without checking if it's counterfeit.
3. Using HTTP Instead of HTTPS
Even in development, use HTTPS to catch configuration issues early.
4. Not Implementing Rate Limiting
Without rate limiting, attackers can flood your callback endpoints, causing denial of service.
5. Logging Sensitive Information
// BAD - Logs sensitive data
error_log("Payment received from: " . $data['phone_number']);
// GOOD - Sanitize before logging
error_log("Payment received from: " . maskPhoneNumber($data['phone_number']));
6. Not Updating Dependencies
Outdated libraries often contain known vulnerabilities. Keep your dependencies updated.
7. Using Default Credentials
Never use default usernames, passwords, or API key formats. Generate strong, unique credentials.
Security Checklist
- ✅ API keys stored in environment variables
- ✅ .env file in .gitignore
- ✅ Callback URLs use HTTPS only
- ✅ Webhook signatures verified
- ✅ Rate limiting implemented
- ✅ Sensitive data not logged
- ✅ Dependencies kept updated
- ✅ Monitoring and alerts configured