@codalmo/angola-payments
v1.0.0
Published
SDK unificado para sistemas de pagamento fintech de Angola - Democratizando pagamentos em Angola
Maintainers
Readme
Codalmo Angola Payments SDK
TL;DR: Accept Payments in 5 Minutes
npm install @codalmo/angola-paymentsimport { AngolaPaymentsClient, Provider } from '@codalmo/angola-payments';
const client = new AngolaPaymentsClient({
provider: Provider.PAY4ALL,
providerConfig: {
notificationToken: 'your-token',
apiKey: 'your-key',
partnerRegistrationNumber: 'your-registration',
environment: 'sandbox'
}
});
const payment = await client.createPayment({
amount: 1000,
referenceCode: 'ORDER_123',
mobileNumber: '+244123456789'
});
console.log('Pay with:', payment.qrCode);Full docs below! ⬇️
Why Codalmo?
Integrate payments faster, launch your app sooner, and grow your business in Angola.
Built by Angola devs, for Angola devs—battle-tested with Pay4All's quirks. We handle the complex API integration so you can focus on building your product.
- ⚡ 5-minute integration vs weeks of manual API work
- 🧪 Complete testing suite that works around Pay4All's limited sandbox
- 🛡️ Production-ready with error handling, retries, and monitoring
- 🌍 Made for Angola with realistic test data and local support
How It Works
sequenceDiagram
participant App as Your App
participant SDK as Codalmo SDK
participant Pay4All as Pay4All API
participant User as Customer
App->>SDK: createPayment(amount, mobileNumber)
SDK->>Pay4All: POST /Ticket/{token}
Pay4All-->>SDK: QR Code + Payment ID
SDK-->>App: PaymentResponse
User->>Pay4All: Scan QR Code & Pay
Pay4All->>SDK: Webhook Notification
SDK->>App: Payment Completed Event
App->>SDK: getPaymentStatus()
SDK->>Pay4All: GET /Ticket/{token}/{mobile}
Pay4All-->>SDK: Payment Status
SDK-->>App: StatusResponseQuick Start
JavaScript/TypeScript
npm install @codalmo/angola-paymentsimport { AngolaPaymentsClient, Provider } from '@codalmo/angola-payments';
const client = new AngolaPaymentsClient({
provider: Provider.PAY4ALL,
providerConfig: {
notificationToken: 'your-notification-token',
apiKey: 'your-api-key',
partnerRegistrationNumber: 'your-partner-registration-number',
environment: 'sandbox' // or 'production'
}
});
// Create a payment ticket
const payment = await client.createPayment({
amount: 1000, // 1000.00 AOA
referenceCode: 'ORDER_123',
mobileNumber: '+244123456789'
});
console.log('E-kwanza Code:', payment.code);
console.log('QR Code:', payment.qrCode);Python (Coming Soon)
pip install codalmo-angola-paymentsPython SDK will be available in v1.1.0 - generated from OpenAPI specification
🧪 Testing Made Simple
Pay4All's sandbox is notoriously patchy (no public docs, manual creds, limited testing). We solve this:
Instant Testing (No Credentials Needed)
const client = new AngolaPaymentsClient({
provider: Provider.PAY4ALL,
providerConfig: {
notificationToken: 'demo-token',
apiKey: 'demo-key',
partnerRegistrationNumber: 'demo-registration',
environment: 'sandbox',
simulation: { enabled: true } // 🎯 This is the magic!
}
});
// All methods work identically, but return realistic test data
const payment = await client.createPayment({
amount: 1000,
referenceCode: 'TEST_123',
mobileNumber: '+244923456789' // Realistic Angolan number
});What You Get
- ✅ Realistic test data - Valid Angolan phone numbers, amounts, codes
- ✅ Complete workflows - Payment → Status → Webhook simulation
- ✅ Error scenarios - Test authentication, network, validation errors
- ✅ No API limits - Test as much as you want, as fast as you want
Advanced Testing Features
import { TestDataGenerator, TestScenarios, TestUtils } from '@codalmo/angola-payments';
// Generate realistic test data
const mobileNumber = TestDataGenerator.generateMobileNumber(); // +244923123456
const referenceCode = TestDataGenerator.generateReferenceCode('ORDER'); // ORDER_123456_789
const amount = TestDataGenerator.generateAmount(100, 1000); // Random amount
// Predefined test scenarios
const happyPath = await TestScenarios.happyPath();
const failure = await TestScenarios.paymentFailure();
const networkError = await TestScenarios.networkError();
// Complete payment flow simulation
const flow = await TestUtils.simulatePaymentFlow({
simulateSuccess: true,
simulateWebhooks: true,
simulateErrors: false
});Features
- ✅ Unified API: Consistent interface across all providers
- ✅ Type Safety: Full TypeScript support with IntelliSense
- ✅ Error Handling: Comprehensive error handling with retry logic
- ✅ Webhooks: Integrated webhook handling and verification
- ✅ Testing: Sandbox environments for safe testing
- ✅ Documentation: Extensive documentation with real-world examples
- ✅ Integrated Logging: Structured logging system for production
- ✅ Monitoring: Request metrics and tracing
- ✅ Automatic Retry: Intelligent retry with exponential backoff
- ✅ CLI Tool: Command-line tool for quick initialization
- ✅ OpenAPI: Automatic documentation and SDK generation
Configuration
Advanced Configuration
import { AngolaPaymentsClient, Provider, createLogger } from '@codalmo/angola-payments';
const client = new AngolaPaymentsClient({
provider: Provider.PAY4ALL,
providerConfig: {
notificationToken: 'your-notification-token',
apiKey: 'your-api-key',
partnerRegistrationNumber: 'your-partner-registration-number',
environment: 'sandbox',
// Monitoring and logging
monitoring: {
enableLogging: true,
logger: createLogger('structured', true),
enableMetrics: true,
enableTracing: true,
customHeaders: {
'X-Client-Version': '1.0.0',
'X-Request-ID': 'req_123'
}
},
// Automatic retry
enableRetry: true,
retryConfig: {
maxRetries: 5,
baseDelay: 1000,
maxDelay: 10000,
backoffMultiplier: 2
}
}
});Environment Variables
# .env
EKWANZA_NOTIFICATION_TOKEN=your-notification-token
EKWANZA_API_KEY=your-api-key
EKWANZA_PARTNER_REGISTRATION=your-partner-registration-number
NODE_ENV=productionCLI Tool (Coming Soon)
Installation
npm install -g @codalmo/cliCLI tool will be available in v1.1.0 for quick project initialization
OpenAPI Documentation
Complete Specification
- 📁
docs/openapi.json- OpenAPI 3.0 specification - ✅ Documented endpoints
- ✅ Request/response schemas
- ✅ Error codes
- ✅ Authentication
SDK Generation (Coming Soon)
# Generate Python SDK (v1.1.0)
openapi-generator-cli generate -i docs/openapi.json -g python -o python-sdk
# Generate Go SDK (v1.2.0)
openapi-generator-cli generate -i docs/openapi.json -g go -o go-sdk
# Generate PHP SDK (v1.2.0)
openapi-generator-cli generate -i docs/openapi.json -g php -o php-sdkMulti-language SDKs will be generated from OpenAPI specification in future releases
API Reference
AngolaPaymentsClient
createPayment(request: PaymentRequest): Promise<PaymentResponse>
Creates a new payment.
Parameters:
amount(number): Value in AOA (decimal)referenceCode(string): Payment reference codemobileNumber(string): Customer phone number
Returns: Promise
getPaymentStatus(mobileNumber: string): Promise<Pay4AllPaymentStatusResponse>
Gets the current status of a payment.
Parameters:
mobileNumber(string): Customer phone number
Returns: Promise
verifyWebhook(payload: string, signature: string, secret: string): WebhookVerificationResult
Verifies webhook signature.
parseWebhook(payload: string): WebhookEvent
Parses webhook payload.
testConnection(): Promise<boolean>
Tests connection to the provider.
Providers
Pay4All (E-kwanza)
Pay4All is Angola's leading mobile payment provider.
Configuration
const pay4AllConfig = {
notificationToken: 'your-pay4all-token',
apiKey: 'your-api-key',
partnerRegistrationNumber: 'your-registration-number',
environment: 'sandbox', // or 'production'
baseUrl: 'https://api.ekwanza.ao' // optional
};Features
- Mobile money payments
- QR code payments
- Webhook notifications
- Payment status tracking
Supported Currencies
- AOA (Angolan Kwanza)
Webhooks
Setting Up Webhooks
- Configure your webhook endpoint in the Pay4All dashboard
- Set up your webhook handler:
app.post('/webhooks/ekwanza', (req, res) => {
const signature = req.headers['x-signature'];
const payload = JSON.stringify(req.body);
const secret = process.env.EKWANZA_API_KEY;
const verification = client.verifyWebhook(payload, signature, secret);
if (verification.valid) {
const event = verification.event;
// Handle the event
handleWebhookEvent(event);
}
res.status(200).json({ received: true });
});Webhook Events
payment.created: Payment was createdpayment.updated: Payment status was updatedpayment.completed: Payment was completedpayment.failed: Payment failedpayment.cancelled: Payment was cancelledpayment.refunded: Payment was refunded
Error Handling
The SDK provides comprehensive error handling:
try {
const payment = await client.createPayment(request);
} catch (error) {
if (error instanceof AngolaFintechError) {
switch (error.type) {
case AngolaFintechErrorType.AUTHENTICATION_ERROR:
// Handle authentication error
break;
case AngolaFintechErrorType.VALIDATION_ERROR:
// Handle validation error
break;
case AngolaFintechErrorType.NETWORK_ERROR:
// Handle network error
break;
case AngolaFintechErrorType.PROVIDER_ERROR:
// Handle provider error
break;
}
}
}Error Types
AUTHENTICATION_ERROR: Invalid API key or authentication failedVALIDATION_ERROR: Invalid request parametersNETWORK_ERROR: Network connectivity issuesPROVIDER_ERROR: Provider service errorRATE_LIMIT_ERROR: Rate limit exceededUNKNOWN_ERROR: Unknown error occurred
Examples
Basic Payment Flow
// 1. Create payment
const payment = await client.createPayment({
amount: 1000,
referenceCode: 'ORDER_123',
mobileNumber: '+244123456789'
});
// 2. Redirect user to payment URL or show QR code
if (payment.paymentUrl) {
window.location.href = payment.paymentUrl;
} else if (payment.qrCode) {
// Display QR code to user
displayQRCode(payment.qrCode);
}
// 3. Handle webhook notifications
// (See webhook example above)Payment Status Polling
async function pollPaymentStatus(mobileNumber: string) {
const maxAttempts = 30; // 5 minutes with 10s intervals
let attempts = 0;
while (attempts < maxAttempts) {
try {
const payment = await client.getPaymentStatus(mobileNumber);
if (payment.status === 1) { // Processed
console.log('Payment completed!');
return payment;
} else if (payment.status === 2) { // Expired
console.log('Payment expired');
return payment;
}
// Wait 10 seconds before next check
await new Promise(resolve => setTimeout(resolve, 10000));
attempts++;
} catch (error) {
console.error('Error checking payment status:', error);
attempts++;
}
}
throw new Error('Payment status polling timeout');
}Best Practices
Security
- Never expose API keys in client code
- Use environment variables for sensitive data
- Verify webhook signatures
- Use HTTPS for all webhook endpoints
- Implement proper error handling
Performance
- Use webhooks instead of polling when possible
- Implement proper retry logic
- Cache payment status when appropriate
- Use connection pooling for high-volume applications
Error Handling
- Always handle errors gracefully
- Log errors for debugging
- Provide user-friendly error messages
- Implement fallback mechanisms
Testing
- Use sandbox environment for testing
- Test all error scenarios
- Verify webhook handling
- Test with different currencies and amounts
🌟 Join the Community
Join 100+ Angola devs building fintech with Codalmo!
- 💬 Discord Community - Get help, share projects, network
- 📚 Documentation - Complete guides and examples
- 🐛 Report Issues - Help us improve
- 💡 Feature Requests - Shape the roadmap
Built by the community, for the community.
🚀 Roadmap & Pricing
Current (Free Forever)
- ✅ Complete Pay4All integration
- ✅ Advanced testing & simulation
- ✅ TypeScript/JavaScript SDK
- ✅ Community support
Coming Soon (Premium)
- 🎯 Hosted Dashboard - Visual payment analytics and management
- 🎯 Premium Support - Priority support and integration assistance
- 🎯 Multi-provider - UnitelMoney, Banco BIC, and more
- 🎯 Enterprise Features - Custom webhooks, advanced monitoring
Early adopters get lifetime access to premium features!
Support
- 📧 Email: [email protected]
- 💬 Discord: Join our community
- 📖 Documentation: docs.codalmo.com
- 🐛 Issues: GitHub Issues
License
MIT License - see LICENSE for details.
Contributing
Contributions are welcome! Please see our Contributing Guide for details.
Codalmo - Democratizing fintech payments in Angola! 🇦🇴💳
