paybridge
v0.1.3
Published
One API, every payment provider. Unified payment SDK for Node.js — SoftyComp, Yoco, Ozow, and more.
Maintainers
Readme
PayBridge
One API. Every payment provider. 🌍
Unified payment SDK for Node.js that works with multiple payment providers through a single, consistent API. Focus on South African providers first, with support for international gateways.
WaSP is to WhatsApp what PayBridge is to payments — one SDK, multiple backends, zero friction.
Features
- Unified API — Same code works across all providers
- TypeScript-first — Full type safety and autocomplete
- South African focus — SoftyComp, Yoco, Ozow, PayFast ready
- International support — Stripe, PayStack, Peach Payments (coming soon)
- Production-ready — Webhooks, refunds, subscriptions, retries
- Zero lock-in — Switch providers by changing 1 config line
Installation
npm install paybridgeInteractive Playground
Want to see PayBridge in action before writing code? Try our Stripe-style interactive playground:
cd playground
npm install
npm startThen open http://localhost:4020 in your browser.
The playground lets you:
- Create real payments against SoftyComp sandbox
- Watch webhooks arrive in real-time
- Generate code snippets (TypeScript/JavaScript)
- Compare PayBridge vs raw API complexity
- Test all payment operations with a beautiful UI
Perfect for demos, learning, and rapid prototyping. See playground/README.md for details.
Quick Start
One-time Payment
import { PayBridge } from 'paybridge';
// Initialize with your provider
const pay = new PayBridge({
provider: 'softycomp',
credentials: {
apiKey: process.env.SOFTYCOMP_API_KEY,
secretKey: process.env.SOFTYCOMP_SECRET_KEY
},
sandbox: true
});
// Create payment — same API regardless of provider
const payment = await pay.createPayment({
amount: 299.00, // Always in major currency unit (rands)
currency: 'ZAR',
reference: 'INV-001',
customer: {
name: 'John Doe',
email: '[email protected]',
phone: '0825551234'
},
urls: {
success: 'https://myapp.com/success',
cancel: 'https://myapp.com/cancel',
webhook: 'https://myapp.com/webhook'
}
});
// Redirect customer to payment page
console.log(payment.checkoutUrl);
// Payment details
console.log(payment.id); // Provider payment ID
console.log(payment.status); // 'pending' | 'completed' | 'failed' | 'cancelled'
console.log(payment.provider); // 'softycomp'Recurring Subscription
const subscription = await pay.createSubscription({
amount: 299.00,
currency: 'ZAR',
interval: 'monthly', // 'weekly' | 'monthly' | 'yearly'
reference: 'SUB-001',
customer: {
name: 'Jane Smith',
email: '[email protected]'
},
urls: {
success: 'https://myapp.com/success',
cancel: 'https://myapp.com/cancel',
webhook: 'https://myapp.com/webhook'
},
startDate: '2026-04-01', // Must be future date
billingDay: 1 // Day of month (1-28)
});Refund
// Full refund
const refund = await pay.refund({
paymentId: 'pay_123'
});
// Partial refund
const refund = await pay.refund({
paymentId: 'pay_123',
amount: 100.00,
reason: 'Customer request'
});Check Payment Status
const payment = await pay.getPayment('pay_123');
if (payment.status === 'completed') {
console.log('Payment received!');
}Webhooks
import express from 'express';
const app = express();
// IMPORTANT: Use express.raw() for signature verification
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
// Verify webhook signature
if (!pay.verifyWebhook(req.body, req.headers)) {
return res.status(400).send('Invalid signature');
}
// Parse webhook event
const event = pay.parseWebhook(req.body, req.headers);
switch (event.type) {
case 'payment.completed':
console.log('Payment completed:', event.payment);
// Fulfill order, activate subscription, etc.
break;
case 'payment.failed':
console.log('Payment failed:', event.payment);
// Notify customer
break;
case 'payment.cancelled':
console.log('Payment cancelled:', event.payment);
break;
case 'refund.completed':
console.log('Refund completed:', event.refund);
break;
}
res.sendStatus(200);
});Supported Providers
| Provider | One-time | Subscriptions | Refunds | Webhooks | Status | |----------|----------|---------------|---------|----------|--------| | SoftyComp | ✅ | ✅ | ✅ | ✅ | Production | | Yoco | 🚧 | 🚧 | 🚧 | 🚧 | Coming soon | | Ozow | 🚧 | 🚧 | 🚧 | 🚧 | Coming soon | | PayFast | 📋 | 📋 | 📋 | 📋 | Planned | | PayStack | 📋 | 📋 | 📋 | 📋 | Planned | | Stripe | 📋 | 📋 | 📋 | 📋 | Planned | | Peach Payments | 📋 | 📋 | 📋 | 📋 | Planned |
Legend: ✅ Production ready | 🚧 In development | 📋 Planned
Provider Configuration
SoftyComp
const pay = new PayBridge({
provider: 'softycomp',
credentials: {
apiKey: 'your_api_key',
secretKey: 'your_secret_key'
},
sandbox: true,
webhookSecret: 'optional_webhook_secret'
});Docs: SoftyComp API
Yoco (Coming Soon)
const pay = new PayBridge({
provider: 'yoco',
credentials: {
apiKey: 'sk_test_...' // Secret key
},
sandbox: true,
webhookSecret: 'whsec_...'
});Docs: Yoco Developer
Ozow (Coming Soon)
const pay = new PayBridge({
provider: 'ozow',
credentials: {
apiKey: 'your_api_key',
siteCode: 'your_site_code',
privateKey: 'your_private_key'
},
sandbox: true
});Docs: Ozow Hub
Switch Providers in 1 Line
// Using SoftyComp
const pay1 = new PayBridge({ provider: 'softycomp', credentials: { ... } });
// Switch to Yoco — SAME API!
const pay2 = new PayBridge({ provider: 'yoco', credentials: { ... } });
// Switch to Ozow — SAME API!
const pay3 = new PayBridge({ provider: 'ozow', credentials: { ... } });
// All methods work identically
const payment = await pay1.createPayment({ ... }); // SoftyComp
const payment = await pay2.createPayment({ ... }); // Yoco
const payment = await pay3.createPayment({ ... }); // OzowWhy PayBridge?
South Africa's payment landscape is fragmented. Different providers for different use cases:
- SoftyComp — Debit orders and bill presentment
- Yoco — Card payments for SMEs
- Ozow — Instant EFT
- PayFast — Online payments
Each has its own SDK, quirks, and integration patterns. PayBridge unifies them all.
Before PayBridge
// SoftyComp
const softycomp = new SoftyComp({ ... });
const bill = await softycomp.createBill({ amount: 299.00, frequency: 'once-off', ... });
// Yoco
const yoco = new Yoco({ ... });
const checkout = await yoco.checkouts.create({ amountInCents: 29900, ... });
// Ozow
const ozow = new Ozow({ ... });
const payment = await ozow.initiatePayment({ Amount: '299.00', HashCheck: '...', ... });Different APIs, different amount formats, different field names.
With PayBridge
// ONE API for all providers
const payment = await pay.createPayment({
amount: 299.00,
currency: 'ZAR',
reference: 'INV-001',
customer: { ... },
urls: { ... }
});Same code. Every provider.
API Reference
PayBridge
Constructor
new PayBridge(config: PayBridgeConfig)Methods
createPayment(params: CreatePaymentParams): Promise<PaymentResult>createSubscription(params: CreateSubscriptionParams): Promise<SubscriptionResult>getPayment(id: string): Promise<PaymentResult>refund(params: RefundParams): Promise<RefundResult>parseWebhook(body: any, headers?: any): WebhookEventverifyWebhook(body: any, headers?: any): booleangetProviderName(): stringgetSupportedCurrencies(): string[]
Types
See src/types.ts for full type definitions.
Currency Handling
PayBridge always uses major currency units (rands, dollars) in the API:
// ✅ Correct
{ amount: 299.00, currency: 'ZAR' }
// ❌ Wrong (don't use cents)
{ amount: 29900, currency: 'ZAR' }PayBridge handles provider-specific conversions internally:
- SoftyComp uses rands → no conversion
- Yoco uses cents → converts to cents
- Ozow uses rands → no conversion
Error Handling
try {
const payment = await pay.createPayment({ ... });
} catch (error) {
console.error('Payment failed:', error.message);
// Handle error (invalid credentials, network error, etc.)
}Webhook Security
Always verify webhook signatures in production:
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
// Verify signature
if (!pay.verifyWebhook(req.body, req.headers)) {
return res.status(401).send('Unauthorized');
}
// Signature valid — process event
const event = pay.parseWebhook(req.body, req.headers);
// ...
});Roadmap
- [x] v0.1 — Core API + SoftyComp provider
- [ ] v0.2 — Yoco provider
- [ ] v0.3 — Ozow provider
- [ ] v0.4 — PayFast provider
- [ ] v0.5 — PayStack provider (Nigeria)
- [ ] v0.6 — Stripe provider (international)
- [ ] v0.7 — Peach Payments provider
- [ ] v1.0 — Production-ready with all SA providers
Contributing
We welcome contributions! To add a new payment provider:
- Create
src/providers/yourprovider.tsextendingPaymentProvider - Implement all abstract methods
- Add provider to
src/index.tsfactory - Update README with provider details
- Submit PR
See src/providers/softycomp.ts for reference implementation.
License
MIT © Kobie Wentzel
Related Projects
- WaSP — Unified WhatsApp API (Baileys, Cloud API, Twilio)
- softycomp-node — Official SoftyComp SDK
Built with ❤️ in South Africa
