kotanipay-sdk
Version:
Official Kotani Pay SDK for Node.js and Browser
581 lines (467 loc) • 15 kB
Markdown
# KotaniPay TypeScript/JavaScript SDK
Official TypeScript/JavaScript SDK for the KotaniPay API. Simplify crypto-to-mobile money transactions across Africa.
## Features
- 🚀 **TypeScript Support** - Full type definitions included
- 🔐 **Authentication Management** - Magic link login flow with JWT and API key support
- 📱 **Mobile Money** - Create and manage mobile money customers across 13+ African countries
- 💰 **Wallet Management** - Create and manage fiat wallets for multiple currencies
- 💸 **Deposits** - Handle mobile money deposits with real-time status tracking
- 🔄 **Onramp** - Convert fiat to cryptocurrency through mobile money
- 🏢 **Integrator Management** - Create and manage integrator accounts
- 🛡️ **Error Handling** - Comprehensive error types and validation
- 🌍 **Multi-Environment** - Sandbox and production support
## Installation
```bash
npm install kotanipay-sdk
```
```bash
yarn add kotanipay-sdk
```
## Quick Start
```typescript
import { KotaniPayClient } from 'kotanipay-sdk';
// Initialize client
const client = new KotaniPayClient({
environment: 'sandbox' // or 'production'
});
// Create integrator (no auth required)
const integrator = await client.integrator.create({
organization: 'My Company',
product_name: 'My Product',
first_name: 'John',
last_name: 'Doe',
email: 'john@company.com',
phone: '+1234567890',
country_code: 'US'
});
// Start authentication flow
await client.auth.login('john@company.com');
// User receives magic link in email...
// After user clicks magic link, set session
client.initializeWithSession(sessionData);
// Generate API key
const apiKey = await client.auth.generateApiKey();
client.initializeWithApiKey(apiKey.key);
// Create fiat wallet
const wallet = await client.wallet.create({
name: 'My USD Wallet',
currency: 'USD'
});
// Create mobile money customer
const customer = await client.mobileMoney.createCustomer({
phone_number: '+254700123456',
country_code: 'KEN',
network: 'MPESA',
account_name: 'John Doe'
});
// Create deposit
const deposit = await client.mobileMoneyDeposit.createDeposit({
amount: 100.00,
wallet_id: wallet.data.id,
customer_key: customer.id
});
```
## Authentication Flow
KotaniPay uses a magic link authentication system:
1. **Send Magic Link**: Call `client.auth.login(email)`
2. **User Action**: User clicks verification link in email
3. **Get Session Data**: Copy JSON response from browser
4. **Initialize Session**: Call `client.initializeWithSession(sessionData)`
5. **Generate API Key**: Call `client.auth.generateApiKey()`
6. **Ready**: Use authenticated endpoints
### Example Session Data
When user clicks the magic link, they'll see JSON like this:
```json
{
"success": true,
"message": "ok",
"data": {
"user_id": "66262fda6c7024bcf925636f",
"session_id": "8d1d3429b8075d53993c58a3a1b3bcec",
"token_id": "PrsCEicJ",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
```
Pass the `data` object to `initializeWithSession()`.
## API Reference
### Client Initialization
```typescript
const client = new KotaniPayClient({
environment: 'sandbox' | 'production',
timeout?: number,
apiKey?: string, // Optional: for direct API key usage
baseUrl?: string // Optional: custom base URL
});
// Utility methods
const health = await client.healthCheck();
const config = client.getConfig();
const version = client.getVersion();
const isAuth = client.isAuthenticated();
const authStatus = client.getAuthStatus();
```
### Integrator Management
```typescript
// Create integrator (no auth required)
await client.integrator.create({
organization: string,
product_name: string,
first_name: string,
last_name: string,
email: string,
phone: string,
country_code: string
});
// Get all integrators (requires auth)
// CLIENT HAS TO BE INITIALIZED WITH AN API KEY
await client.integrator.getIntegratorInfo();
// Get integrator by ID (requires auth)
await client.integrator.getById(id);
```
### Authentication
```typescript
// Send magic link
await client.auth.login(email);
// Set session after magic link click
client.initializeWithSession(sessionData);
// Generate API key
await client.auth.generateApiKey();
// Set API key directly
client.initializeWithApiKey(apiKey);
// Refresh JWT token
await client.auth.refreshToken();
// Get current session
client.auth.getSession();
// Get token info
client.auth.getTokenInfo();
// Check authentication status
client.isAuthenticated();
// Logout and clear session
client.auth.logout();
```
### Mobile Money
```typescript
// Create customer (requires auth)
await client.mobileMoney.createCustomer({
phone_number: string,
country_code: 'GHA' | 'KEN' | 'ZAC' | 'CIV' | 'ZMB' | 'CMR' | 'COD' | 'SEN' | 'TZM' | 'MWI' | 'UGA' | 'ETH' | 'GRW',
network?: 'MPESA' | 'MTN' | 'AIRTEL' | 'VODAFONE' | 'TIGO' | 'ORANGE' | 'VODACOM' | 'NOT_SUPPORTED' | 'ZAMTEL' | 'CHECKOUT' | 'BKTRX' | 'CRDTRX' | 'MOOV' | 'TMONEY' | 'FREE' | 'EXPRESSO' | 'HALOPESA',
account_name?: string
});
// Get all customers (requires auth)
await client.mobileMoney.getAllCustomers();
// Get customer by ID (requires auth)
await client.mobileMoney.getCustomerById(customerId);
// Get customers by customer key (requires auth)
await client.mobileMoney.getCustomersByKey(customerKey);
// Get customers by phone number (requires auth)
await client.mobileMoney.getCustomersByPhoneNumber(phoneNumber);
```
### Wallet Management
```typescript
// Create fiat wallet (requires auth)
await client.wallet.create({
name: string,
currency: 'USD' | 'EUR' | 'GBP' | 'GHS' | 'KES' | 'ZAR' | 'NGN' | 'TZS' | 'UGX' | 'RWF' | 'MWK' | 'ZMW'
});
// Get all fiat wallets (requires auth)
await client.wallet.getIntegratorFiatWallets();
// Get wallet by ID (requires auth)
await client.wallet.getIntegratorFiatWalletById(walletId);
// Get wallets by currency (requires auth)
await client.wallet.getIntegratorFiatWalletsByCurrency(currency);
```
### Mobile Money Deposits
```typescript
// Create deposit (requires auth)
await client.mobileMoneyDeposit.createDeposit({
amount: number,
wallet_id: string,
customer_key: string,
callback_url?: string,
reference_id?: string
});
// Get deposit transaction status (requires auth)
await client.mobileMoneyDeposit.getDepositTransactionStatus(reference_id);
```
### Onramp (Fiat to Crypto)
```typescript
// Initiate onramp (requires auth)
await client.onramp.iniatiateOnramp({
mobileMoney: {
phoneNumber: string,
accountName: string,
providerNetwork: string
},
fiatAmount: number,
currency: string,
chain: string,
token: string,
receiverAddress: string,
referenceId: string,
callbackUrl: string,
rateId: string
});
// Get onramp transaction status (requires auth)
await client.onramp.getOnRampTransactionStatus(referenceId);
```
## Supported Countries & Networks
### Countries
- 🇬🇭 Ghana (GHA) - MTN, VODAFONE, AIRTEL
- 🇰🇪 Kenya (KEN) - MPESA, AIRTEL
- 🇿🇦 South Africa (ZAC) - MTN, VODACOM
- 🇨🇮 Ivory Coast (CIV) - MTN, ORANGE, MOOV
- 🇿🇲 Zambia (ZMB) - MTN, AIRTEL, ZAMTEL
- 🇨🇲 Cameroon (CMR) - MTN, ORANGE
- 🇨🇩 Congo DRC (COD) - VODACOM, AIRTEL
- 🇸🇳 Senegal (SEN) - ORANGE, FREE, EXPRESSO
- 🇹🇿 Tanzania (TZM) - VODACOM, AIRTEL, TIGO, HALOPESA
- 🇲🇼 Malawi (MWI) - AIRTEL
- 🇺🇬 Uganda (UGA) - MTN, AIRTEL
- 🇪🇹 Ethiopia (ETH)
- 🇬🇼 Guinea-Bissau (GRW)
### Networks
- M-Pesa
- MTN Mobile Money
- Airtel Money
- Vodafone Cash
- Tigo Pesa
- Orange Money
- And more...
### Supported Currencies
**Fiat Wallets**: USD, EUR, GBP, GHS, KES, ZAR, NGN, TZS, UGX, RWF, MWK, ZMW
### Transaction Statuses
**Deposit/Onramp**: PENDING, INITIATED, SUCCESSFUL, FAILED, EXPIRED, CANCELLED, DECLINED, REVERSED, IN_PROGRESS, DUPLICATE, ERROR_OCCURRED, REQUIRE_REVIEW, SUCCESS, RETRY
## Error Handling
```typescript
import { ValidationException, AuthenticationException, KotaniPayException } from 'kotanipay-sdk';
try {
await client.mobileMoney.createCustomer(customerData);
} catch (error) {
if (error instanceof ValidationException) {
console.log('Validation error:', error.message);
console.log('Details:', error.details);
} else if (error instanceof AuthenticationException) {
console.log('Auth error:', error.message);
} else if (error instanceof KotaniPayException) {
console.log('API error:', error.message);
console.log('Status:', error.status);
console.log('Error code:', error.errorCode);
}
}
```
## Environment Variables
For server-side usage, you can set:
```bash
KOTANIPAY_API_KEY=your-api-key
KOTANIPAY_ENVIRONMENT=sandbox
```
## Examples
### Complete Integration Flow
```typescript
import { KotaniPayClient } from 'kotanipay-sdk';
async function completeFlow() {
const client = new KotaniPayClient({
environment: 'sandbox'
});
try {
// 1. Create integrator
const integrator = await client.integrator.create({
organization: 'My Company',
product_name: 'My App',
first_name: 'John',
last_name: 'Doe',
email: 'john@mycompany.com',
phone: '+1234567890',
country_code: 'US'
});
// 2. Login and authenticate
await client.auth.login('john@mycompany.com');
// User clicks email link, you get session data
client.initializeWithSession(sessionData);
// 3. Generate API key
const apiKey = await client.auth.generateApiKey();
// 4. Create a wallet
const wallet = await client.wallet.create({
name: 'My USD Wallet',
currency: 'USD'
});
// 5. Create mobile money customer
const customer = await client.mobileMoney.createCustomer({
phone_number: '+254712345678',
country_code: 'KEN',
network: 'MPESA'
});
// 6. Create deposit
const deposit = await client.mobileMoneyDeposit.createDeposit({
amount: 100.00,
wallet_id: wallet.data.id,
customer_key: customer.id
});
console.log('Integration flow completed successfully');
} catch (error) {
console.error('Integration flow failed:', error);
}
}
```
### React Integration
```typescript
import React, { useState } from 'react';
import { KotaniPayClient } from 'kotanipay-sdk';
function PaymentComponent() {
const [client] = useState(() => new KotaniPayClient({
environment: 'sandbox'
}));
const [authStatus, setAuthStatus] = useState('idle');
const handleLogin = async (email: string) => {
try {
setAuthStatus('sending');
await client.auth.login(email);
setAuthStatus('waiting'); // Wait for user to click magic link
} catch (error) {
setAuthStatus('error');
}
};
const handleSessionData = async (sessionData: any) => {
try {
client.initializeWithSession(sessionData);
const apiKey = await client.auth.generateApiKey();
client.initializeWithApiKey(apiKey.key);
setAuthStatus('authenticated');
} catch (error) {
setAuthStatus('error');
}
};
const createWalletAndCustomer = async () => {
try {
const wallet = await client.wallet.create({
name: 'Payment Wallet',
currency: 'KES'
});
const customer = await client.mobileMoney.createCustomer({
phone_number: '+254700123456',
country_code: 'KEN',
network: 'MPESA'
});
console.log('Wallet and customer created successfully');
} catch (error) {
console.error('Creation failed:', error);
}
};
return (
<div>
{authStatus === 'idle' && (
<button onClick={() => handleLogin('user@example.com')}>
Login with Email
</button>
)}
{authStatus === 'waiting' && (
<div>
<p>Magic link sent! Check your email.</p>
<textarea
placeholder="Paste session data here..."
onChange={(e) => {
try {
const data = JSON.parse(e.target.value);
handleSessionData(data.data);
} catch {}
}}
/>
</div>
)}
{authStatus === 'authenticated' && (
<div>
<p>Ready to make payments!</p>
<button onClick={createWalletAndCustomer}>
Create Wallet & Customer
</button>
</div>
)}
</div>
);
}
```
### Node.js Integration
```typescript
import { KotaniPayClient } from 'kotanipay-sdk';
const client = new KotaniPayClient({
environment: 'sandbox',
apiKey: process.env.KOTANIPAY_API_KEY // If you already have an API key
});
async function processPayment() {
try {
// Create wallet
const wallet = await client.wallet.create({
name: 'Business Wallet',
currency: 'KES'
});
// Create customer
const customer = await client.mobileMoney.createCustomer({
phone_number: '+254700123456',
country_code: 'KEN',
network: 'MPESA'
});
// Create deposit
const deposit = await client.mobileMoneyDeposit.createDeposit({
amount: 1000,
wallet_id: wallet.data.id,
customer_key: customer.id,
callback_url: 'https://myapp.com/webhook'
});
console.log('Payment initiated:', deposit);
return deposit;
} catch (error) {
console.error('Payment failed:', error);
throw error;
}
}
```
### Onramp Example
```typescript
async function initiateOnramp() {
try {
const onramp = await client.onramp.iniatiateOnramp({
mobileMoney: {
phoneNumber: '+254700123456',
accountName: 'John Doe',
providerNetwork: 'MPESA'
},
fiatAmount: 100,
currency: 'KES',
chain: 'ethereum',
token: 'USDC',
receiverAddress: '0x1234567890123456789012345678901234567890',
referenceId: 'my-ref-' + Date.now(),
callbackUrl: 'https://myapp.com/webhook',
rateId: 'rate-id-from-quote'
});
console.log('Onramp initiated:', onramp);
} catch (error) {
console.error('Onramp failed:', error);
}
}
```
## Contributing
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Support
- 📧 **Email**: support@kotanipay.com
- 📖 **Documentation**: https://docs.kotanipay.com
- 🐛 **Issues**: https://github.com/kotanipay/sdk-typescript/issues
## Changelog
### v1.0.0
- Initial release
- Magic link authentication with JWT and API key support
- Integrator management
- Mobile money customer management across 13+ African countries
- Fiat wallet creation and management
- Mobile money deposit handling with status tracking
- Onramp functionality for fiat-to-crypto conversion
- Comprehensive error handling and validation
- TypeScript supportcd ..