@maxkabechani/mtn-momo-sdk 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +595 -65
- package/lib/cjs/cli.js +0 -0
- package/lib/cjs/collections.d.ts +15 -1
- package/lib/cjs/collections.d.ts.map +1 -1
- package/lib/cjs/collections.js +42 -2
- package/lib/cjs/collections.js.map +1 -1
- package/lib/cjs/common.d.ts +8 -0
- package/lib/cjs/common.d.ts.map +1 -1
- package/lib/cjs/disbursements.d.ts +15 -1
- package/lib/cjs/disbursements.d.ts.map +1 -1
- package/lib/cjs/disbursements.js +35 -0
- package/lib/cjs/disbursements.js.map +1 -1
- package/lib/cjs/index.d.ts +1 -1
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +2 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/remittance.d.ts +30 -1
- package/lib/cjs/remittance.d.ts.map +1 -1
- package/lib/cjs/remittance.js +91 -22
- package/lib/cjs/remittance.js.map +1 -1
- package/lib/esm/cli.js +0 -0
- package/lib/esm/collections.d.ts +15 -1
- package/lib/esm/collections.d.ts.map +1 -1
- package/lib/esm/collections.js +42 -2
- package/lib/esm/collections.js.map +1 -1
- package/lib/esm/common.d.ts +8 -0
- package/lib/esm/common.d.ts.map +1 -1
- package/lib/esm/disbursements.d.ts +15 -1
- package/lib/esm/disbursements.d.ts.map +1 -1
- package/lib/esm/disbursements.js +35 -0
- package/lib/esm/disbursements.js.map +1 -1
- package/lib/esm/index.d.ts +1 -1
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +2 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/remittance.d.ts +30 -1
- package/lib/esm/remittance.d.ts.map +1 -1
- package/lib/esm/remittance.js +92 -23
- package/lib/esm/remittance.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# MTN MoMo Node SDK (@maxkabechani/mtn-momo-sdk)
|
|
2
2
|
|
|
3
|
-
TypeScript-first MTN Mobile Money client for Node.js. Fully compatible with official MoMo API v1.0 and v2.0.
|
|
3
|
+
TypeScript-first MTN Mobile Money client for Node.js. Fully compatible with the official MoMo API v1.0 and v2.0.
|
|
4
4
|
|
|
5
|
-
This SDK provides a type-safe, developer-friendly interface for integrating MTN Mobile Money into your applications. It supports **Collections**, **Disbursements**, and **
|
|
5
|
+
This SDK provides a type-safe, developer-friendly interface for integrating MTN Mobile Money into your applications. It supports **Collections**, **Disbursements**, **Remittance**, and **Sandbox User Provisioning**.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
- **
|
|
12
|
-
- **Comprehensive Coverage**:
|
|
13
|
-
- **TypeScript First**: Full type definitions for all requests and
|
|
14
|
-
- **Bun & Node.js**:
|
|
11
|
+
- **V1 & V2 Coexistence**: Use stable V1 endpoints by default or opt-in to V2 features (`depositV2`, `refundV2`, `requestToWithdrawV2`, `cashTransfer`).
|
|
12
|
+
- **Comprehensive Coverage**: Request-to-pay, transfers, deposits, refunds, withdrawals, BC Authorize, OAuth2 consent, delivery notifications, and more.
|
|
13
|
+
- **TypeScript First**: Full type definitions for all requests, responses, and errors.
|
|
14
|
+
- **Bun & Node.js**: Works with modern runtimes.
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -25,103 +25,637 @@ bun add @maxkabechani/mtn-momo-sdk
|
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
|
-
## Quick Start
|
|
28
|
+
## Quick Start
|
|
29
29
|
|
|
30
30
|
### 1. Initialize the Client
|
|
31
|
+
|
|
31
32
|
```ts
|
|
32
33
|
import { create, Environment } from "@maxkabechani/mtn-momo-sdk";
|
|
33
34
|
|
|
34
35
|
const momo = create({
|
|
35
|
-
callbackHost: "yourdomain.com",
|
|
36
|
-
environment: Environment.SANDBOX,
|
|
36
|
+
callbackHost: "yourdomain.com",
|
|
37
|
+
environment: Environment.SANDBOX, // or Environment.PRODUCTION
|
|
37
38
|
});
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
### 2.
|
|
41
|
-
|
|
41
|
+
### 2. Provision Sandbox Credentials
|
|
42
|
+
|
|
43
|
+
Use the `Users` client to create sandbox API users, or use the CLI tool:
|
|
42
44
|
|
|
43
45
|
```ts
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
});
|
|
46
|
+
const users = momo.Users({ primaryKey: "YOUR_PRIMARY_KEY" });
|
|
47
|
+
|
|
48
|
+
const userId = await users.create("yourdomain.com");
|
|
49
|
+
const { apiKey } = await users.login(userId);
|
|
49
50
|
```
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
If you don't have a `userId` and `userSecret` yet, you can generate them using our CLI tool:
|
|
52
|
+
Or via CLI:
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
55
|
npx momo-sandbox --host yourdomain.com --primary-key YOUR_PRIMARY_KEY
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
### 3. Configure a Product
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
const collections = momo.Collections({
|
|
62
|
+
primaryKey: "your_collections_primary_key",
|
|
63
|
+
userId: userId,
|
|
64
|
+
userSecret: apiKey,
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
58
68
|
---
|
|
59
69
|
|
|
60
70
|
## API Reference
|
|
61
71
|
|
|
72
|
+
### Common Types
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
// Party identifier
|
|
76
|
+
interface Party {
|
|
77
|
+
partyIdType: "MSISDN" | "EMAIL" | "PARTY_CODE";
|
|
78
|
+
partyId: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Account balance
|
|
82
|
+
interface Balance {
|
|
83
|
+
availableBalance: string;
|
|
84
|
+
currency: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Basic user info
|
|
88
|
+
interface BasicUserInfo {
|
|
89
|
+
given_name: string;
|
|
90
|
+
family_name: string;
|
|
91
|
+
birthdate: string;
|
|
92
|
+
locale: string;
|
|
93
|
+
gender: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// OAuth2 consent KYC response
|
|
97
|
+
interface ConsentKycResponse {
|
|
98
|
+
sub: string;
|
|
99
|
+
name: string;
|
|
100
|
+
phone_number: string;
|
|
101
|
+
status: string;
|
|
102
|
+
// ... additional KYC fields
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// BC Authorize request
|
|
106
|
+
interface BcAuthorizeRequest {
|
|
107
|
+
login_hint: string; // e.g. "ID:46733123454/MSISDN"
|
|
108
|
+
scope: string; // e.g. "profile"
|
|
109
|
+
access_type: "online" | "offline";
|
|
110
|
+
consent_valid_in?: number; // Consent validity in seconds
|
|
111
|
+
client_notification_token?: string; // Token for notifications
|
|
112
|
+
scope_instruction?: string; // Custom scope instructions
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// BC Authorize response
|
|
116
|
+
interface BcAuthorizeResponse {
|
|
117
|
+
auth_req_id: string;
|
|
118
|
+
interval: number;
|
|
119
|
+
expires_in: number;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// OAuth2 token request
|
|
123
|
+
interface OAuth2TokenRequest {
|
|
124
|
+
grant_type: string; // e.g. "urn:openid:params:grant-type:ciba"
|
|
125
|
+
auth_req_id: string; // From bcAuthorize response
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// OAuth2 token response
|
|
129
|
+
interface OAuth2TokenResponse {
|
|
130
|
+
access_token: string;
|
|
131
|
+
token_type: string;
|
|
132
|
+
expires_in: number;
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
### Sandbox User Provisioning (`Users`)
|
|
139
|
+
|
|
140
|
+
Manage API users for the sandbox environment.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const users = momo.Users({ primaryKey: "YOUR_PRIMARY_KEY" });
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
#### `create(host: string): Promise<string>`
|
|
147
|
+
|
|
148
|
+
Creates a new sandbox API user.
|
|
149
|
+
|
|
150
|
+
- **Arguments**: `host` — Your callback host domain (e.g. `"yourdomain.com"`)
|
|
151
|
+
- **Returns**: The generated user ID (UUID)
|
|
152
|
+
- **Errors**: `ResourceAlreadyExistError` if user exists
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
const userId = await users.create("yourdomain.com");
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
#### `login(userId: string): Promise<Credentials>`
|
|
159
|
+
|
|
160
|
+
Generates an API key for an existing sandbox user.
|
|
161
|
+
|
|
162
|
+
- **Arguments**: `userId` — The UUID from `create()`
|
|
163
|
+
- **Returns**: `{ apiKey: string }`
|
|
164
|
+
- **Errors**: `ResourceNotFoundError` if user doesn't exist
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
const { apiKey } = await users.login(userId);
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### `getApiUser(referenceId: string): Promise<ApiUserInfo>`
|
|
171
|
+
|
|
172
|
+
Retrieves details of a sandbox API user.
|
|
173
|
+
|
|
174
|
+
- **Arguments**: `referenceId` — The user ID
|
|
175
|
+
- **Returns**: `{ providerCallbackHost: string, targetEnvironment: string }`
|
|
176
|
+
- **Errors**: `ResourceNotFoundError` if user doesn't exist
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
const userInfo = await users.getApiUser(userId);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
62
184
|
### Collections
|
|
63
|
-
Manage incoming payments and withdrawals.
|
|
64
185
|
|
|
65
|
-
|
|
66
|
-
|
|
186
|
+
Manage incoming payments, withdrawals, and account information.
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
const collections = momo.Collections({
|
|
190
|
+
primaryKey: "YOUR_COLLECTIONS_KEY",
|
|
191
|
+
userId: "YOUR_USER_ID",
|
|
192
|
+
userSecret: "YOUR_USER_SECRET",
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### `requestToPay(request: PaymentRequest): Promise<string>`
|
|
197
|
+
|
|
198
|
+
Requests a payment from a consumer (payer).
|
|
199
|
+
|
|
67
200
|
- **Arguments**:
|
|
68
|
-
- `amount`: `string` (e.g., "100.00")
|
|
69
|
-
- `currency`: `string` (e.g., "EUR")
|
|
70
|
-
- `externalId`: `string` (Optional, for reconciliation)
|
|
71
|
-
- `payer`: `{ partyIdType: 'MSISDN' | 'EMAIL' | 'PARTY_CODE', partyId: string }`
|
|
72
|
-
- `payerMessage`: `string` (Optional, shown in payer history)
|
|
73
|
-
- `payeeNote`: `string` (Optional, shown in your history)
|
|
74
|
-
- `callbackUrl`: `string` (Optional, overrides global callback host)
|
|
75
201
|
|
|
76
|
-
|
|
77
|
-
|
|
202
|
+
| Field | Type | Required | Description |
|
|
203
|
+
|-------|------|----------|-------------|
|
|
204
|
+
| `amount` | `string` | ✅ | Amount to collect (e.g. `"500"`) |
|
|
205
|
+
| `currency` | `string` | ✅ | ISO 4217 currency code (e.g. `"EUR"`) |
|
|
206
|
+
| `payer` | `Party` | ✅ | The party being charged |
|
|
207
|
+
| `externalId` | `string` | ❌ | Your internal reference for reconciliation |
|
|
208
|
+
| `payerMessage` | `string` | ❌ | Message shown in payer's transaction history |
|
|
209
|
+
| `payeeNote` | `string` | ❌ | Note shown in your transaction history |
|
|
210
|
+
| `callbackUrl` | `string` | ❌ | Override the global callback URL |
|
|
211
|
+
|
|
212
|
+
- **Returns**: `string` — The reference ID (UUID) for tracking the transaction
|
|
213
|
+
- **Errors**: Validation errors for missing/invalid fields
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
const referenceId = await collections.requestToPay({
|
|
217
|
+
amount: "500",
|
|
218
|
+
currency: "EUR",
|
|
219
|
+
externalId: "order-123",
|
|
220
|
+
payer: { partyIdType: "MSISDN", partyId: "46733123454" },
|
|
221
|
+
payerMessage: "Payment for order #123",
|
|
222
|
+
payeeNote: "Order 123",
|
|
223
|
+
});
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### `getTransaction(referenceId: string): Promise<Payment>`
|
|
227
|
+
|
|
228
|
+
Retrieves the status and details of a payment request.
|
|
229
|
+
|
|
230
|
+
- **Arguments**: `referenceId` — The UUID returned by `requestToPay()`
|
|
231
|
+
- **Returns**:
|
|
232
|
+
|
|
233
|
+
| Field | Type | Description |
|
|
234
|
+
|-------|------|-------------|
|
|
235
|
+
| `financialTransactionId` | `string` | MoMo transaction ID |
|
|
236
|
+
| `externalId` | `string` | Your external reference |
|
|
237
|
+
| `amount` | `string` | Transaction amount |
|
|
238
|
+
| `currency` | `string` | Currency code |
|
|
239
|
+
| `payer` | `Party` | The payer's details |
|
|
240
|
+
| `status` | `"PENDING" \| "SUCCESSFUL" \| "FAILED"` | Payment status |
|
|
241
|
+
| `reason` | `FailureReason` | Failure reason (if `FAILED`) |
|
|
242
|
+
|
|
243
|
+
- **Errors**: Rejects with a typed error if the transaction has `FAILED` status (e.g. `PayerNotFoundError`, `NotEnoughFundsError`)
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
const payment = await collections.getTransaction(referenceId);
|
|
247
|
+
console.log(payment.status); // "SUCCESSFUL"
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### `requestToWithdraw(request: WithdrawalRequest): Promise<string>`
|
|
251
|
+
|
|
252
|
+
Initiates a withdrawal from a payer account (V1).
|
|
253
|
+
|
|
254
|
+
- **Arguments**:
|
|
255
|
+
|
|
256
|
+
| Field | Type | Required | Description |
|
|
257
|
+
|-------|------|----------|-------------|
|
|
258
|
+
| `amount` | `string` | ✅ | Amount to withdraw |
|
|
259
|
+
| `currency` | `string` | ✅ | ISO 4217 currency code |
|
|
260
|
+
| `payee` | `Party` | ✅ | The party receiving the withdrawal |
|
|
261
|
+
| `externalId` | `string` | ❌ | Your internal reference |
|
|
262
|
+
| `payerMessage` | `string` | ❌ | Message for payer |
|
|
263
|
+
| `payeeNote` | `string` | ❌ | Note for payee |
|
|
264
|
+
| `callbackUrl` | `string` | ❌ | Override callback URL |
|
|
265
|
+
|
|
266
|
+
- **Returns**: `string` — The reference ID (UUID)
|
|
267
|
+
- **Errors**: Validation errors for missing/invalid fields
|
|
268
|
+
|
|
269
|
+
#### `requestToWithdrawV2(request: WithdrawalRequest): Promise<string>`
|
|
270
|
+
|
|
271
|
+
Same as `requestToWithdraw` but uses the V2 endpoint.
|
|
272
|
+
|
|
273
|
+
#### `getWithdrawal(referenceId: string): Promise<Withdrawal>`
|
|
274
|
+
|
|
275
|
+
Retrieves the status of a withdrawal request.
|
|
276
|
+
|
|
277
|
+
- **Arguments**: `referenceId` — The UUID from `requestToWithdraw()`
|
|
278
|
+
- **Returns**: Withdrawal details with `status` field
|
|
279
|
+
- **Errors**: Rejects with a typed error if the withdrawal has `FAILED` status
|
|
280
|
+
|
|
281
|
+
#### `sendDeliveryNotification(referenceId: string, notification: DeliveryNotification): Promise<void>`
|
|
282
|
+
|
|
283
|
+
Sends a delivery notification for a completed payment.
|
|
284
|
+
|
|
285
|
+
- **Arguments**:
|
|
286
|
+
|
|
287
|
+
| Field | Type | Required | Description |
|
|
288
|
+
|-------|------|----------|-------------|
|
|
289
|
+
| `referenceId` | `string` | ✅ | The payment reference ID |
|
|
290
|
+
| `notification.notificationMessage` | `string` | ✅ | Notification text (max 160 chars) |
|
|
291
|
+
| `notification.language` | `string` | ❌ | ISO 639-1/639-3 language code |
|
|
292
|
+
|
|
293
|
+
- **Returns**: `void`
|
|
294
|
+
|
|
295
|
+
```ts
|
|
296
|
+
await collections.sendDeliveryNotification(referenceId, {
|
|
297
|
+
notificationMessage: "Your payment has been received!",
|
|
298
|
+
language: "en",
|
|
299
|
+
});
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
#### `getBalance(): Promise<Balance>`
|
|
303
|
+
|
|
304
|
+
Returns the account balance.
|
|
305
|
+
|
|
306
|
+
- **Returns**: `{ availableBalance: string, currency: string }`
|
|
307
|
+
|
|
308
|
+
#### `getBalanceInCurrency(currency: string): Promise<Balance>`
|
|
309
|
+
|
|
310
|
+
Returns the account balance in a specific currency.
|
|
311
|
+
|
|
312
|
+
- **Arguments**: `currency` — ISO 4217 currency code (e.g. `"EUR"`)
|
|
313
|
+
- **Returns**: `{ availableBalance: string, currency: string }`
|
|
314
|
+
|
|
315
|
+
#### `isPayerActive(partyId: string, partyIdType?: PartyIdType): Promise<boolean>`
|
|
316
|
+
|
|
317
|
+
Checks if an account holder is active and can receive payments.
|
|
318
|
+
|
|
319
|
+
- **Arguments**: `partyId` — The party identifier, `partyIdType` — defaults to `"MSISDN"`
|
|
320
|
+
- **Returns**: `true` if active, `false` if not found
|
|
321
|
+
|
|
322
|
+
#### `getBasicUserInfo(partyIdType: PartyIdType, partyId: string): Promise<BasicUserInfo>`
|
|
323
|
+
|
|
324
|
+
Retrieves basic user information for an account holder.
|
|
325
|
+
|
|
326
|
+
- **Returns**: `{ given_name, family_name, birthdate, locale, gender }`
|
|
327
|
+
|
|
328
|
+
#### `bcAuthorize(request: BcAuthorizeRequest): Promise<BcAuthorizeResponse>`
|
|
329
|
+
|
|
330
|
+
Initiates a Biometric Consent (BC) authorization flow.
|
|
331
|
+
|
|
332
|
+
- **Arguments**: See `BcAuthorizeRequest` in Common Types above
|
|
333
|
+
- **Returns**: `{ auth_req_id: string, interval: number, expires_in: number }`
|
|
334
|
+
|
|
335
|
+
```ts
|
|
336
|
+
const authResult = await collections.bcAuthorize({
|
|
337
|
+
login_hint: "ID:46733123454/MSISDN",
|
|
338
|
+
scope: "profile",
|
|
339
|
+
access_type: "online",
|
|
340
|
+
});
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
#### `getUserInfoWithConsent(): Promise<ConsentKycResponse>`
|
|
344
|
+
|
|
345
|
+
Retrieves user information with KYC consent (requires prior OAuth2 authorization).
|
|
346
|
+
|
|
347
|
+
- **Returns**: User info including `sub`, `name`, `phone_number`, `status`
|
|
348
|
+
|
|
349
|
+
#### `getOAuth2Token(request: OAuth2TokenRequest): Promise<OAuth2TokenResponse>`
|
|
78
350
|
|
|
79
|
-
|
|
80
|
-
Returns `{ availableBalance: string, currency: string }`.
|
|
351
|
+
Creates an OAuth2 token for consent-based access.
|
|
81
352
|
|
|
82
|
-
|
|
83
|
-
|
|
353
|
+
- **Arguments**: `{ grant_type: string, auth_req_id: string }`
|
|
354
|
+
- **Returns**: `{ access_token: string, token_type: string, expires_in: number }`
|
|
355
|
+
|
|
356
|
+
```ts
|
|
357
|
+
const token = await collections.getOAuth2Token({
|
|
358
|
+
grant_type: "urn:openid:params:grant-type:ciba",
|
|
359
|
+
auth_req_id: authResult.auth_req_id,
|
|
360
|
+
});
|
|
361
|
+
```
|
|
84
362
|
|
|
85
363
|
---
|
|
86
364
|
|
|
87
365
|
### Disbursements
|
|
366
|
+
|
|
88
367
|
Manage payouts, deposits, and refunds.
|
|
89
368
|
|
|
90
|
-
|
|
369
|
+
```ts
|
|
370
|
+
const disbursements = momo.Disbursements({
|
|
371
|
+
primaryKey: "YOUR_DISBURSEMENTS_KEY",
|
|
372
|
+
userId: "YOUR_USER_ID",
|
|
373
|
+
userSecret: "YOUR_USER_SECRET",
|
|
374
|
+
});
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
#### `transfer(request: TransferRequest): Promise<string>`
|
|
378
|
+
|
|
91
379
|
Transfers money from your account to a payee.
|
|
380
|
+
|
|
92
381
|
- **Arguments**:
|
|
93
|
-
- `amount`, `currency`, `externalId`: Same as Collections.
|
|
94
|
-
- `payee`: `{ partyIdType: 'MSISDN' | 'EMAIL' | 'PARTY_CODE', partyId: string }`
|
|
95
|
-
- `payerMessage`, `payeeNote`, `callbackUrl`: Same as Collections.
|
|
96
382
|
|
|
97
|
-
|
|
98
|
-
|
|
383
|
+
| Field | Type | Required | Description |
|
|
384
|
+
|-------|------|----------|-------------|
|
|
385
|
+
| `amount` | `string` | ✅ | Amount to transfer |
|
|
386
|
+
| `currency` | `string` | ✅ | ISO 4217 currency code |
|
|
387
|
+
| `payee` | `Party` | ✅ | The party receiving the transfer |
|
|
388
|
+
| `externalId` | `string` | ❌ | Your internal reference |
|
|
389
|
+
| `payerMessage` | `string` | ❌ | Message for payer |
|
|
390
|
+
| `payeeNote` | `string` | ❌ | Note for payee |
|
|
391
|
+
| `callbackUrl` | `string` | ❌ | Override callback URL |
|
|
392
|
+
|
|
393
|
+
- **Returns**: `string` — The reference ID (UUID)
|
|
394
|
+
|
|
395
|
+
```ts
|
|
396
|
+
const referenceId = await disbursements.transfer({
|
|
397
|
+
amount: "250",
|
|
398
|
+
currency: "EUR",
|
|
399
|
+
externalId: "payout-456",
|
|
400
|
+
payee: { partyIdType: "MSISDN", partyId: "46733123454" },
|
|
401
|
+
payerMessage: "Salary payment",
|
|
402
|
+
payeeNote: "March salary",
|
|
403
|
+
});
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
#### `getTransaction(referenceId: string): Promise<Transfer>`
|
|
407
|
+
|
|
408
|
+
Retrieves the status and details of a transfer.
|
|
409
|
+
|
|
410
|
+
- **Returns**: Transfer details with `status` (`PENDING`, `SUCCESSFUL`, `FAILED`)
|
|
411
|
+
- **Errors**: Rejects with a typed error if the transfer has `FAILED` status
|
|
412
|
+
|
|
413
|
+
#### `deposit(request: DepositRequest): Promise<string>`
|
|
414
|
+
|
|
415
|
+
Deposits money into a payee account (V1).
|
|
416
|
+
|
|
417
|
+
- **Arguments**:
|
|
418
|
+
|
|
419
|
+
| Field | Type | Required | Description |
|
|
420
|
+
|-------|------|----------|-------------|
|
|
421
|
+
| `amount` | `string` | ✅ | Amount to deposit |
|
|
422
|
+
| `currency` | `string` | ✅ | ISO 4217 currency code |
|
|
423
|
+
| `payee` | `Party` | ✅ | The party receiving the deposit |
|
|
424
|
+
| `externalId` | `string` | ❌ | Your internal reference |
|
|
425
|
+
| `payerMessage` | `string` | ❌ | Message for payer |
|
|
426
|
+
| `payeeNote` | `string` | ❌ | Note for payee |
|
|
427
|
+
| `callbackUrl` | `string` | ❌ | Override callback URL |
|
|
428
|
+
|
|
429
|
+
- **Returns**: `string` — The reference ID (UUID)
|
|
430
|
+
|
|
431
|
+
#### `depositV2(request: DepositRequest): Promise<string>`
|
|
432
|
+
|
|
433
|
+
Same as `deposit` but uses the V2 endpoint.
|
|
434
|
+
|
|
435
|
+
#### `getDeposit(referenceId: string): Promise<Deposit>`
|
|
436
|
+
|
|
437
|
+
Retrieves the status of a deposit.
|
|
438
|
+
|
|
439
|
+
- **Errors**: Rejects with a typed error if the deposit has `FAILED` status
|
|
440
|
+
|
|
441
|
+
#### `refund(request: RefundRequest): Promise<string>`
|
|
442
|
+
|
|
443
|
+
Refunds a previous transaction (V1).
|
|
99
444
|
|
|
100
|
-
#### `refundV2(request: RefundRequest)`
|
|
101
|
-
Refunds a previous transaction.
|
|
102
445
|
- **Arguments**:
|
|
103
|
-
|
|
104
|
-
|
|
446
|
+
|
|
447
|
+
| Field | Type | Required | Description |
|
|
448
|
+
|-------|------|----------|-------------|
|
|
449
|
+
| `referenceIdToRefund` | `string` | ✅ | UUID of the original transaction to refund |
|
|
450
|
+
| `amount` | `string` | ✅ | Amount to refund |
|
|
451
|
+
| `currency` | `string` | ✅ | ISO 4217 currency code |
|
|
452
|
+
| `externalId` | `string` | ❌ | Your internal reference |
|
|
453
|
+
| `payerMessage` | `string` | ❌ | Message for payer |
|
|
454
|
+
| `payeeNote` | `string` | ❌ | Note for payee |
|
|
455
|
+
| `callbackUrl` | `string` | ❌ | Override callback URL |
|
|
456
|
+
|
|
457
|
+
- **Returns**: `string` — The refund reference ID (UUID)
|
|
458
|
+
|
|
459
|
+
```ts
|
|
460
|
+
const refundId = await disbursements.refund({
|
|
461
|
+
referenceIdToRefund: originalTransactionId,
|
|
462
|
+
amount: "50",
|
|
463
|
+
currency: "EUR",
|
|
464
|
+
externalId: "refund-789",
|
|
465
|
+
payerMessage: "Refund for damaged goods",
|
|
466
|
+
payeeNote: "Partial refund",
|
|
467
|
+
});
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
#### `refundV2(request: RefundRequest): Promise<string>`
|
|
471
|
+
|
|
472
|
+
Same as `refund` but uses the V2 endpoint.
|
|
473
|
+
|
|
474
|
+
#### `getRefund(referenceId: string): Promise<Refund>`
|
|
475
|
+
|
|
476
|
+
Retrieves the status of a refund.
|
|
477
|
+
|
|
478
|
+
- **Errors**: Rejects with a typed error if the refund has `FAILED` status
|
|
479
|
+
|
|
480
|
+
#### `getBalance(): Promise<Balance>`
|
|
481
|
+
|
|
482
|
+
Returns the account balance.
|
|
483
|
+
|
|
484
|
+
#### `getBalanceInCurrency(currency: string): Promise<Balance>`
|
|
485
|
+
|
|
486
|
+
Returns the account balance in a specific currency.
|
|
487
|
+
|
|
488
|
+
#### `isPayerActive(partyId: string, partyIdType?: PartyIdType): Promise<boolean>`
|
|
489
|
+
|
|
490
|
+
Checks if an account holder is active.
|
|
491
|
+
|
|
492
|
+
#### `getBasicUserInfo(partyIdType: PartyIdType, partyId: string): Promise<BasicUserInfo>`
|
|
493
|
+
|
|
494
|
+
Retrieves basic user information for an account holder.
|
|
495
|
+
|
|
496
|
+
#### `bcAuthorize(request: BcAuthorizeRequest): Promise<BcAuthorizeResponse>`
|
|
497
|
+
|
|
498
|
+
Initiates a BC authorization flow. Uses **Basic Auth** for this endpoint.
|
|
499
|
+
|
|
500
|
+
#### `getUserInfoWithConsent(): Promise<ConsentKycResponse>`
|
|
501
|
+
|
|
502
|
+
Retrieves user info with KYC consent (requires prior OAuth2 authorization).
|
|
503
|
+
|
|
504
|
+
#### `getOAuth2Token(request: OAuth2TokenRequest): Promise<OAuth2TokenResponse>`
|
|
505
|
+
|
|
506
|
+
Creates an OAuth2 token for consent-based access.
|
|
105
507
|
|
|
106
508
|
---
|
|
107
509
|
|
|
108
510
|
### Remittance
|
|
109
|
-
Manage cross-border transfers.
|
|
110
511
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
512
|
+
Manage cross-border money transfers.
|
|
513
|
+
|
|
514
|
+
```ts
|
|
515
|
+
const remittance = momo.Remittance({
|
|
516
|
+
primaryKey: "YOUR_REMITTANCE_KEY",
|
|
517
|
+
userId: "YOUR_USER_ID",
|
|
518
|
+
userSecret: "YOUR_USER_SECRET",
|
|
519
|
+
});
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
#### `transfer(request: CashTransferRequest): Promise<string>`
|
|
523
|
+
|
|
524
|
+
Sends money cross-border to a beneficiary (V1).
|
|
525
|
+
|
|
526
|
+
- **Arguments**:
|
|
527
|
+
|
|
528
|
+
| Field | Type | Required | Description |
|
|
529
|
+
|-------|------|----------|-------------|
|
|
530
|
+
| `amount` | `string` | ✅ | Amount to transfer |
|
|
531
|
+
| `currency` | `string` | ✅ | ISO 4217 currency code |
|
|
532
|
+
| `payee` | `Party` | ✅ | The beneficiary |
|
|
533
|
+
| `externalId` | `string` | ❌ | Your internal reference |
|
|
534
|
+
| `originatingCountry` | `string` | ❌ | ISO country code of sender |
|
|
535
|
+
| `originalAmount` | `string` | ❌ | Original amount before conversion |
|
|
536
|
+
| `originalCurrency` | `string` | ❌ | Original currency before conversion |
|
|
537
|
+
| `payerMessage` | `string` | ❌ | Message for payer |
|
|
538
|
+
| `payeeNote` | `string` | ❌ | Note for payee |
|
|
539
|
+
| `callbackUrl` | `string` | ❌ | Override callback URL |
|
|
540
|
+
|
|
541
|
+
- **Returns**: `string` — The reference ID (UUID)
|
|
542
|
+
|
|
543
|
+
```ts
|
|
544
|
+
const referenceId = await remittance.transfer({
|
|
545
|
+
amount: "150",
|
|
546
|
+
currency: "EUR",
|
|
547
|
+
externalId: "remit-001",
|
|
548
|
+
payee: { partyIdType: "MSISDN", partyId: "46733123454" },
|
|
549
|
+
payerMessage: "Family support",
|
|
550
|
+
payeeNote: "Monthly remittance",
|
|
551
|
+
});
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
#### `getTransaction(referenceId: string): Promise<CashTransfer>`
|
|
555
|
+
|
|
556
|
+
Retrieves the status and details of a transfer.
|
|
557
|
+
|
|
558
|
+
- **Returns**: Transfer details with `status` (`PENDING`, `SUCCESSFUL`, `FAILED`)
|
|
559
|
+
- **Errors**: Rejects with a typed error if the transfer has `FAILED` status
|
|
560
|
+
|
|
561
|
+
#### `cashTransfer(request: CashTransferRequest): Promise<string>`
|
|
562
|
+
|
|
563
|
+
Sends a cross-border cash transfer using the **V2** endpoint.
|
|
564
|
+
|
|
565
|
+
- **Arguments**: Same as `transfer()` above
|
|
566
|
+
- **Returns**: `string` — The reference ID (UUID)
|
|
567
|
+
|
|
568
|
+
```ts
|
|
569
|
+
const refId = await remittance.cashTransfer({
|
|
570
|
+
amount: "75",
|
|
571
|
+
currency: "EUR",
|
|
572
|
+
payee: { partyIdType: "MSISDN", partyId: "46733123454" },
|
|
573
|
+
});
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
#### `getCashTransfer(referenceId: string): Promise<CashTransfer>`
|
|
577
|
+
|
|
578
|
+
Retrieves the status of a V2 cash transfer.
|
|
579
|
+
|
|
580
|
+
- **Errors**: Rejects with a typed error if the transfer has `FAILED` status
|
|
581
|
+
|
|
582
|
+
#### `getBalance(): Promise<Balance>`
|
|
583
|
+
|
|
584
|
+
Returns the account balance.
|
|
585
|
+
|
|
586
|
+
#### `getBalanceInCurrency(currency: string): Promise<Balance>`
|
|
587
|
+
|
|
588
|
+
Returns the account balance in a specific currency.
|
|
589
|
+
|
|
590
|
+
#### `isPayerActive(partyId: string, partyIdType?: PartyIdType): Promise<boolean>`
|
|
591
|
+
|
|
592
|
+
Checks if a beneficiary is active and can receive transfers.
|
|
593
|
+
|
|
594
|
+
#### `getBasicUserInfo(partyId: string): Promise<BasicUserInfo>`
|
|
595
|
+
|
|
596
|
+
Retrieves basic user information. Remittance uses `MSISDN` by default.
|
|
597
|
+
|
|
598
|
+
#### `bcAuthorize(request: BcAuthorizeRequest): Promise<BcAuthorizeResponse>`
|
|
599
|
+
|
|
600
|
+
Initiates a BC authorization flow. Uses **Basic Auth** for this endpoint.
|
|
601
|
+
|
|
602
|
+
#### `getUserInfoWithConsent(): Promise<ConsentKycResponse>`
|
|
603
|
+
|
|
604
|
+
Retrieves user info with KYC consent (requires prior OAuth2 authorization).
|
|
605
|
+
|
|
606
|
+
#### `getOAuth2Token(request: OAuth2TokenRequest): Promise<OAuth2TokenResponse>`
|
|
607
|
+
|
|
608
|
+
Creates an OAuth2 token for consent-based access.
|
|
609
|
+
|
|
610
|
+
---
|
|
611
|
+
|
|
612
|
+
## Error Handling
|
|
613
|
+
|
|
614
|
+
All API errors are mapped to typed error classes that extend `MtnMoMoError`. You can catch specific errors:
|
|
615
|
+
|
|
616
|
+
```ts
|
|
617
|
+
import { PayerNotFoundError, NotEnoughFundsError } from "@maxkabechani/mtn-momo-sdk";
|
|
618
|
+
|
|
619
|
+
try {
|
|
620
|
+
await collections.requestToPay({ ... });
|
|
621
|
+
} catch (error) {
|
|
622
|
+
if (error instanceof PayerNotFoundError) {
|
|
623
|
+
console.error("The payer MSISDN was not found");
|
|
624
|
+
} else if (error instanceof NotEnoughFundsError) {
|
|
625
|
+
console.error("Insufficient funds");
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
### Error Types
|
|
631
|
+
|
|
632
|
+
| Error Class | When It Occurs |
|
|
633
|
+
|-------------|---------------|
|
|
634
|
+
| `ApprovalRejectedError` | The user rejected the payment approval |
|
|
635
|
+
| `ExpiredError` | The transaction has expired |
|
|
636
|
+
| `InternalProcessingError` | An internal error occurred on the MoMo platform |
|
|
637
|
+
| `InvalidCallbackUrlHostError` | The callback URL host is invalid |
|
|
638
|
+
| `InvalidCurrencyError` | The specified currency is not supported |
|
|
639
|
+
| `NotAllowedTargetEnvironmentError` | Operation not allowed in the target environment |
|
|
640
|
+
| `NotAllowedError` | The operation is not allowed |
|
|
641
|
+
| `NotEnoughFundsError` | The payer has insufficient funds |
|
|
642
|
+
| `PayeeNotFoundError` | The payee account was not found |
|
|
643
|
+
| `PayeeNotAllowedToReceiveError` | The payee is not allowed to receive funds |
|
|
644
|
+
| `PayerLimitReachedError` | The payer has reached their transaction limit |
|
|
645
|
+
| `PayerNotFoundError` | The payer account was not found |
|
|
646
|
+
| `PaymentNotApprovedError` | The payment was not approved |
|
|
647
|
+
| `ResourceAlreadyExistError` | The resource already exists (e.g. duplicate transaction) |
|
|
648
|
+
| `ResourceNotFoundError` | The requested resource was not found |
|
|
649
|
+
| `ServiceUnavailableError` | The service is temporarily unavailable |
|
|
650
|
+
| `TransactionCancelledError` | The transaction was cancelled |
|
|
651
|
+
| `UnspecifiedError` | An unspecified error occurred |
|
|
116
652
|
|
|
117
653
|
---
|
|
118
654
|
|
|
119
655
|
## Going Live (Production)
|
|
120
656
|
|
|
121
|
-
|
|
657
|
+
1. **Change the environment**:
|
|
122
658
|
|
|
123
|
-
1. **Environment Flag**:
|
|
124
|
-
Change `Environment.SANDBOX` to `Environment.PRODUCTION`.
|
|
125
659
|
```ts
|
|
126
660
|
const momo = create({
|
|
127
661
|
callbackHost: "production-api.yoursite.com",
|
|
@@ -129,18 +663,15 @@ Transitioning from Sandbox to Production requires a few changes:
|
|
|
129
663
|
});
|
|
130
664
|
```
|
|
131
665
|
|
|
132
|
-
2. **
|
|
133
|
-
- Get your **Primary Key** from the [MTN MoMo Developer Portal](https://momodeveloper.mtn.com/).
|
|
134
|
-
- Obtain your production **User ID** and **User Secret** through the official onboarding process in your specific region.
|
|
666
|
+
2. **Use production credentials** from the [MTN MoMo Developer Portal](https://momodeveloper.mtn.com/).
|
|
135
667
|
|
|
136
|
-
3. **Endpoints**:
|
|
137
|
-
The SDK handles the URL switch automatically when `Environment.PRODUCTION` is set.
|
|
668
|
+
3. **Endpoints**: The SDK handles the URL switch automatically.
|
|
138
669
|
|
|
139
670
|
---
|
|
140
671
|
|
|
141
672
|
## Environment Variables
|
|
142
673
|
|
|
143
|
-
|
|
674
|
+
Store credentials securely using environment variables:
|
|
144
675
|
|
|
145
676
|
```bash
|
|
146
677
|
# Collections
|
|
@@ -159,8 +690,6 @@ REMITTANCE_USER_ID=your_id
|
|
|
159
690
|
REMITTANCE_USER_SECRET=your_secret
|
|
160
691
|
```
|
|
161
692
|
|
|
162
|
-
Usage in your application:
|
|
163
|
-
|
|
164
693
|
```ts
|
|
165
694
|
import "dotenv/config";
|
|
166
695
|
|
|
@@ -175,13 +704,14 @@ const collections = momo.Collections({
|
|
|
175
704
|
|
|
176
705
|
## Development & Testing
|
|
177
706
|
|
|
178
|
-
We use [Bun](https://bun.sh) for efficient development.
|
|
179
|
-
|
|
180
707
|
```bash
|
|
181
708
|
bun install
|
|
182
|
-
bun run test # Run unit
|
|
183
|
-
bun run
|
|
709
|
+
bun run test # Run all tests (unit + integration)
|
|
710
|
+
bun run test:coverage # Run tests with coverage
|
|
711
|
+
bun run typecheck # Type check
|
|
712
|
+
bun run build # Build for production (ESM + CJS)
|
|
184
713
|
```
|
|
185
714
|
|
|
186
715
|
## License
|
|
716
|
+
|
|
187
717
|
ISC
|