@singularity-payments/core 0.1.0-alpha.7 → 0.1.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/dist/index.d.mts +46 -18
- package/dist/index.d.ts +46 -18
- package/dist/index.js +166 -32
- package/dist/index.mjs +166 -32
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -262,18 +262,6 @@ interface DynamicQRResponse {
|
|
|
262
262
|
ResponseDescription: string;
|
|
263
263
|
QRCode: string;
|
|
264
264
|
}
|
|
265
|
-
interface C2BSimulateRequest {
|
|
266
|
-
shortCode?: string;
|
|
267
|
-
amount: number;
|
|
268
|
-
msisdn: string;
|
|
269
|
-
billRefNumber: string;
|
|
270
|
-
commandID?: "CustomerPayBillOnline" | "CustomerBuyGoodsOnline";
|
|
271
|
-
}
|
|
272
|
-
interface C2BSimulateResponse {
|
|
273
|
-
ConversationID: string;
|
|
274
|
-
OriginatorCoversationID: string;
|
|
275
|
-
ResponseDescription: string;
|
|
276
|
-
}
|
|
277
265
|
|
|
278
266
|
interface ParsedCallbackData {
|
|
279
267
|
merchantRequestId: string;
|
|
@@ -306,6 +294,11 @@ interface CallbackHandlerOptions {
|
|
|
306
294
|
onCallback?: (data: ParsedCallbackData) => void | Promise<void>;
|
|
307
295
|
onC2BConfirmation?: (data: ParsedC2BCallback) => void | Promise<void>;
|
|
308
296
|
onC2BValidation?: (data: ParsedC2BCallback) => Promise<boolean>;
|
|
297
|
+
onB2CResult?: (data: any) => void | Promise<void>;
|
|
298
|
+
onB2BResult?: (data: any) => void | Promise<void>;
|
|
299
|
+
onAccountBalanceResult?: (data: any) => void | Promise<void>;
|
|
300
|
+
onTransactionStatusResult?: (data: any) => void | Promise<void>;
|
|
301
|
+
onReversalResult?: (data: any) => void | Promise<void>;
|
|
309
302
|
validateIp?: boolean;
|
|
310
303
|
allowedIps?: string[];
|
|
311
304
|
isDuplicate?: (CheckoutRequestID: string) => boolean | Promise<boolean>;
|
|
@@ -351,6 +344,26 @@ declare class MpesaCallbackHandler {
|
|
|
351
344
|
* Get a readable error message based on the code
|
|
352
345
|
*/
|
|
353
346
|
getErrorMessage(resultCode: number): string;
|
|
347
|
+
/**
|
|
348
|
+
* Handle B2C result callback
|
|
349
|
+
*/
|
|
350
|
+
handleB2CResult(callback: B2BCallback, ipAddress?: string): Promise<void>;
|
|
351
|
+
/**
|
|
352
|
+
* Handle B2B result callback
|
|
353
|
+
*/
|
|
354
|
+
handleB2BResult(callback: B2BCallback, ipAddress?: string): Promise<void>;
|
|
355
|
+
/**
|
|
356
|
+
* Handle Account Balance result callback
|
|
357
|
+
*/
|
|
358
|
+
handleAccountBalanceResult(callback: AccountBalanceCallback, ipAddress?: string): Promise<void>;
|
|
359
|
+
/**
|
|
360
|
+
* Handle Transaction Status result callback
|
|
361
|
+
*/
|
|
362
|
+
handleTransactionStatusResult(callback: TransactionStatusCallback, ipAddress?: string): Promise<void>;
|
|
363
|
+
/**
|
|
364
|
+
* Handle Reversal result callback
|
|
365
|
+
*/
|
|
366
|
+
handleReversalResult(callback: ReversalCallback, ipAddress?: string): Promise<void>;
|
|
354
367
|
/**
|
|
355
368
|
* Handle STK Push callback and invoke appropriate handlers
|
|
356
369
|
*/
|
|
@@ -549,11 +562,6 @@ declare class MpesaClient {
|
|
|
549
562
|
* Handle C2B validation request
|
|
550
563
|
*/
|
|
551
564
|
handleC2BValidation(callback: C2BCallback): Promise<object>;
|
|
552
|
-
/**
|
|
553
|
-
* Simulate C2B transaction (Sandbox only)
|
|
554
|
-
* Used for testing C2B payments in sandbox environment
|
|
555
|
-
*/
|
|
556
|
-
simulateC2B(request: C2BSimulateRequest): Promise<C2BSimulateResponse>;
|
|
557
565
|
/**
|
|
558
566
|
* B2C - Send money from business to customer
|
|
559
567
|
*/
|
|
@@ -594,6 +602,26 @@ declare class MpesaClient {
|
|
|
594
602
|
* Get configuration (for plugins)
|
|
595
603
|
*/
|
|
596
604
|
getConfig(): MpesaConfig;
|
|
605
|
+
/**
|
|
606
|
+
* Handle B2C result callback
|
|
607
|
+
*/
|
|
608
|
+
handleB2CResult(callback: B2BCallback, ipAddress?: string): Promise<object>;
|
|
609
|
+
/**
|
|
610
|
+
* Handle B2B result callback
|
|
611
|
+
*/
|
|
612
|
+
handleB2BResult(callback: B2BCallback, ipAddress?: string): Promise<object>;
|
|
613
|
+
/**
|
|
614
|
+
* Handle Account Balance result callback
|
|
615
|
+
*/
|
|
616
|
+
handleAccountBalanceResult(callback: AccountBalanceCallback, ipAddress?: string): Promise<object>;
|
|
617
|
+
/**
|
|
618
|
+
* Handle Transaction Status result callback
|
|
619
|
+
*/
|
|
620
|
+
handleTransactionStatusResult(callback: TransactionStatusCallback, ipAddress?: string): Promise<object>;
|
|
621
|
+
/**
|
|
622
|
+
* Handle Reversal result callback
|
|
623
|
+
*/
|
|
624
|
+
handleReversalResult(callback: ReversalCallback, ipAddress?: string): Promise<object>;
|
|
597
625
|
/**
|
|
598
626
|
* Get rate limiter usage for a key
|
|
599
627
|
*/
|
|
@@ -647,4 +675,4 @@ declare function encryptInitiatorPassword(initiatorPassword: string, certificate
|
|
|
647
675
|
*/
|
|
648
676
|
declare function validateSecurityCredential(credential: string): boolean;
|
|
649
677
|
|
|
650
|
-
export { type AccountBalanceCallback, type AccountBalanceRequest, type AccountBalanceResponse, type B2BCallback, type B2BCommandID, type B2BRequest, type B2BResponse, type B2CCallback, type B2CCommandID, type B2CRequest, type B2CResponse, type BalanceIdentifierType, type C2BCallback, type C2BRegisterRequest, type C2BRegisterResponse, type
|
|
678
|
+
export { type AccountBalanceCallback, type AccountBalanceRequest, type AccountBalanceResponse, type B2BCallback, type B2BCommandID, type B2BRequest, type B2BResponse, type B2CCallback, type B2CCommandID, type B2CRequest, type B2CResponse, type BalanceIdentifierType, type C2BCallback, type C2BRegisterRequest, type C2BRegisterResponse, type CallbackHandlerOptions, type DynamicQRRequest, type DynamicQRResponse, type Environment, type GeneralTransactionStatusRequest, type GeneralTransactionStatusResponse, MpesaApiError, MpesaAuthError, MpesaCallbackHandler, MpesaClient, type MpesaClientOptions, type MpesaConfig, MpesaError, MpesaNetworkError, type MpesaPlugin, MpesaRateLimitError, MpesaTimeoutError, MpesaValidationError, type ParsedC2BCallback, type ParsedCallbackData, RateLimiter, type RateLimiterOptions, type RedisLike, RedisRateLimiter, type RetryOptions, type ReversalCallback, type ReversalRequest, type ReversalResponse, type STKCallback, type STKPushRequest, type STKPushResponse, type TransactionStatusCallback, type TransactionStatusRequest, type TransactionStatusResponse, encryptInitiatorPassword, retryWithBackoff, validateSecurityCredential };
|
package/dist/index.d.ts
CHANGED
|
@@ -262,18 +262,6 @@ interface DynamicQRResponse {
|
|
|
262
262
|
ResponseDescription: string;
|
|
263
263
|
QRCode: string;
|
|
264
264
|
}
|
|
265
|
-
interface C2BSimulateRequest {
|
|
266
|
-
shortCode?: string;
|
|
267
|
-
amount: number;
|
|
268
|
-
msisdn: string;
|
|
269
|
-
billRefNumber: string;
|
|
270
|
-
commandID?: "CustomerPayBillOnline" | "CustomerBuyGoodsOnline";
|
|
271
|
-
}
|
|
272
|
-
interface C2BSimulateResponse {
|
|
273
|
-
ConversationID: string;
|
|
274
|
-
OriginatorCoversationID: string;
|
|
275
|
-
ResponseDescription: string;
|
|
276
|
-
}
|
|
277
265
|
|
|
278
266
|
interface ParsedCallbackData {
|
|
279
267
|
merchantRequestId: string;
|
|
@@ -306,6 +294,11 @@ interface CallbackHandlerOptions {
|
|
|
306
294
|
onCallback?: (data: ParsedCallbackData) => void | Promise<void>;
|
|
307
295
|
onC2BConfirmation?: (data: ParsedC2BCallback) => void | Promise<void>;
|
|
308
296
|
onC2BValidation?: (data: ParsedC2BCallback) => Promise<boolean>;
|
|
297
|
+
onB2CResult?: (data: any) => void | Promise<void>;
|
|
298
|
+
onB2BResult?: (data: any) => void | Promise<void>;
|
|
299
|
+
onAccountBalanceResult?: (data: any) => void | Promise<void>;
|
|
300
|
+
onTransactionStatusResult?: (data: any) => void | Promise<void>;
|
|
301
|
+
onReversalResult?: (data: any) => void | Promise<void>;
|
|
309
302
|
validateIp?: boolean;
|
|
310
303
|
allowedIps?: string[];
|
|
311
304
|
isDuplicate?: (CheckoutRequestID: string) => boolean | Promise<boolean>;
|
|
@@ -351,6 +344,26 @@ declare class MpesaCallbackHandler {
|
|
|
351
344
|
* Get a readable error message based on the code
|
|
352
345
|
*/
|
|
353
346
|
getErrorMessage(resultCode: number): string;
|
|
347
|
+
/**
|
|
348
|
+
* Handle B2C result callback
|
|
349
|
+
*/
|
|
350
|
+
handleB2CResult(callback: B2BCallback, ipAddress?: string): Promise<void>;
|
|
351
|
+
/**
|
|
352
|
+
* Handle B2B result callback
|
|
353
|
+
*/
|
|
354
|
+
handleB2BResult(callback: B2BCallback, ipAddress?: string): Promise<void>;
|
|
355
|
+
/**
|
|
356
|
+
* Handle Account Balance result callback
|
|
357
|
+
*/
|
|
358
|
+
handleAccountBalanceResult(callback: AccountBalanceCallback, ipAddress?: string): Promise<void>;
|
|
359
|
+
/**
|
|
360
|
+
* Handle Transaction Status result callback
|
|
361
|
+
*/
|
|
362
|
+
handleTransactionStatusResult(callback: TransactionStatusCallback, ipAddress?: string): Promise<void>;
|
|
363
|
+
/**
|
|
364
|
+
* Handle Reversal result callback
|
|
365
|
+
*/
|
|
366
|
+
handleReversalResult(callback: ReversalCallback, ipAddress?: string): Promise<void>;
|
|
354
367
|
/**
|
|
355
368
|
* Handle STK Push callback and invoke appropriate handlers
|
|
356
369
|
*/
|
|
@@ -549,11 +562,6 @@ declare class MpesaClient {
|
|
|
549
562
|
* Handle C2B validation request
|
|
550
563
|
*/
|
|
551
564
|
handleC2BValidation(callback: C2BCallback): Promise<object>;
|
|
552
|
-
/**
|
|
553
|
-
* Simulate C2B transaction (Sandbox only)
|
|
554
|
-
* Used for testing C2B payments in sandbox environment
|
|
555
|
-
*/
|
|
556
|
-
simulateC2B(request: C2BSimulateRequest): Promise<C2BSimulateResponse>;
|
|
557
565
|
/**
|
|
558
566
|
* B2C - Send money from business to customer
|
|
559
567
|
*/
|
|
@@ -594,6 +602,26 @@ declare class MpesaClient {
|
|
|
594
602
|
* Get configuration (for plugins)
|
|
595
603
|
*/
|
|
596
604
|
getConfig(): MpesaConfig;
|
|
605
|
+
/**
|
|
606
|
+
* Handle B2C result callback
|
|
607
|
+
*/
|
|
608
|
+
handleB2CResult(callback: B2BCallback, ipAddress?: string): Promise<object>;
|
|
609
|
+
/**
|
|
610
|
+
* Handle B2B result callback
|
|
611
|
+
*/
|
|
612
|
+
handleB2BResult(callback: B2BCallback, ipAddress?: string): Promise<object>;
|
|
613
|
+
/**
|
|
614
|
+
* Handle Account Balance result callback
|
|
615
|
+
*/
|
|
616
|
+
handleAccountBalanceResult(callback: AccountBalanceCallback, ipAddress?: string): Promise<object>;
|
|
617
|
+
/**
|
|
618
|
+
* Handle Transaction Status result callback
|
|
619
|
+
*/
|
|
620
|
+
handleTransactionStatusResult(callback: TransactionStatusCallback, ipAddress?: string): Promise<object>;
|
|
621
|
+
/**
|
|
622
|
+
* Handle Reversal result callback
|
|
623
|
+
*/
|
|
624
|
+
handleReversalResult(callback: ReversalCallback, ipAddress?: string): Promise<object>;
|
|
597
625
|
/**
|
|
598
626
|
* Get rate limiter usage for a key
|
|
599
627
|
*/
|
|
@@ -647,4 +675,4 @@ declare function encryptInitiatorPassword(initiatorPassword: string, certificate
|
|
|
647
675
|
*/
|
|
648
676
|
declare function validateSecurityCredential(credential: string): boolean;
|
|
649
677
|
|
|
650
|
-
export { type AccountBalanceCallback, type AccountBalanceRequest, type AccountBalanceResponse, type B2BCallback, type B2BCommandID, type B2BRequest, type B2BResponse, type B2CCallback, type B2CCommandID, type B2CRequest, type B2CResponse, type BalanceIdentifierType, type C2BCallback, type C2BRegisterRequest, type C2BRegisterResponse, type
|
|
678
|
+
export { type AccountBalanceCallback, type AccountBalanceRequest, type AccountBalanceResponse, type B2BCallback, type B2BCommandID, type B2BRequest, type B2BResponse, type B2CCallback, type B2CCommandID, type B2CRequest, type B2CResponse, type BalanceIdentifierType, type C2BCallback, type C2BRegisterRequest, type C2BRegisterResponse, type CallbackHandlerOptions, type DynamicQRRequest, type DynamicQRResponse, type Environment, type GeneralTransactionStatusRequest, type GeneralTransactionStatusResponse, MpesaApiError, MpesaAuthError, MpesaCallbackHandler, MpesaClient, type MpesaClientOptions, type MpesaConfig, MpesaError, MpesaNetworkError, type MpesaPlugin, MpesaRateLimitError, MpesaTimeoutError, MpesaValidationError, type ParsedC2BCallback, type ParsedCallbackData, RateLimiter, type RateLimiterOptions, type RedisLike, RedisRateLimiter, type RetryOptions, type ReversalCallback, type ReversalRequest, type ReversalResponse, type STKCallback, type STKPushRequest, type STKPushResponse, type TransactionStatusCallback, type TransactionStatusRequest, type TransactionStatusResponse, encryptInitiatorPassword, retryWithBackoff, validateSecurityCredential };
|
package/dist/index.js
CHANGED
|
@@ -419,6 +419,91 @@ var MpesaCallbackHandler = class {
|
|
|
419
419
|
};
|
|
420
420
|
return errorMessages[resultCode] || `Transaction failed with code: ${resultCode}`;
|
|
421
421
|
}
|
|
422
|
+
/**
|
|
423
|
+
* Handle B2C result callback
|
|
424
|
+
*/
|
|
425
|
+
async handleB2CResult(callback, ipAddress) {
|
|
426
|
+
if (ipAddress && !this.validateCallbackIp(ipAddress)) {
|
|
427
|
+
this.log("warn", `Invalid callback IP: ${ipAddress}`);
|
|
428
|
+
throw new Error(`Invalid callback IP: ${ipAddress}`);
|
|
429
|
+
}
|
|
430
|
+
const parsed = this.parseB2CCallback(callback);
|
|
431
|
+
this.log("info", "Processing B2C result", {
|
|
432
|
+
transactionId: parsed.transactionId,
|
|
433
|
+
isSuccess: parsed.isSuccess
|
|
434
|
+
});
|
|
435
|
+
if (this.options.onB2CResult) {
|
|
436
|
+
await this.options.onB2CResult(parsed);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Handle B2B result callback
|
|
441
|
+
*/
|
|
442
|
+
async handleB2BResult(callback, ipAddress) {
|
|
443
|
+
if (ipAddress && !this.validateCallbackIp(ipAddress)) {
|
|
444
|
+
this.log("warn", `Invalid callback IP: ${ipAddress}`);
|
|
445
|
+
throw new Error(`Invalid callback IP: ${ipAddress}`);
|
|
446
|
+
}
|
|
447
|
+
const parsed = this.parseB2BCallback(callback);
|
|
448
|
+
this.log("info", "Processing B2B result", {
|
|
449
|
+
transactionId: parsed.transactionId,
|
|
450
|
+
isSuccess: parsed.isSuccess
|
|
451
|
+
});
|
|
452
|
+
if (this.options.onB2BResult) {
|
|
453
|
+
await this.options.onB2BResult(parsed);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Handle Account Balance result callback
|
|
458
|
+
*/
|
|
459
|
+
async handleAccountBalanceResult(callback, ipAddress) {
|
|
460
|
+
if (ipAddress && !this.validateCallbackIp(ipAddress)) {
|
|
461
|
+
this.log("warn", `Invalid callback IP: ${ipAddress}`);
|
|
462
|
+
throw new Error(`Invalid callback IP: ${ipAddress}`);
|
|
463
|
+
}
|
|
464
|
+
const parsed = this.parseAccountBalanceCallback(callback);
|
|
465
|
+
this.log("info", "Processing Account Balance result", {
|
|
466
|
+
isSuccess: parsed.isSuccess,
|
|
467
|
+
availableBalance: parsed.availableBalance
|
|
468
|
+
});
|
|
469
|
+
if (this.options.onAccountBalanceResult) {
|
|
470
|
+
await this.options.onAccountBalanceResult(parsed);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Handle Transaction Status result callback
|
|
475
|
+
*/
|
|
476
|
+
async handleTransactionStatusResult(callback, ipAddress) {
|
|
477
|
+
if (ipAddress && !this.validateCallbackIp(ipAddress)) {
|
|
478
|
+
this.log("warn", `Invalid callback IP: ${ipAddress}`);
|
|
479
|
+
throw new Error(`Invalid callback IP: ${ipAddress}`);
|
|
480
|
+
}
|
|
481
|
+
const parsed = this.parseTransactionStatusCallback(callback);
|
|
482
|
+
this.log("info", "Processing Transaction Status result", {
|
|
483
|
+
isSuccess: parsed.isSuccess,
|
|
484
|
+
receiptNo: parsed.receiptNo
|
|
485
|
+
});
|
|
486
|
+
if (this.options.onTransactionStatusResult) {
|
|
487
|
+
await this.options.onTransactionStatusResult(parsed);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Handle Reversal result callback
|
|
492
|
+
*/
|
|
493
|
+
async handleReversalResult(callback, ipAddress) {
|
|
494
|
+
if (ipAddress && !this.validateCallbackIp(ipAddress)) {
|
|
495
|
+
this.log("warn", `Invalid callback IP: ${ipAddress}`);
|
|
496
|
+
throw new Error(`Invalid callback IP: ${ipAddress}`);
|
|
497
|
+
}
|
|
498
|
+
const parsed = this.parseReversalCallback(callback);
|
|
499
|
+
this.log("info", "Processing Reversal result", {
|
|
500
|
+
isSuccess: parsed.isSuccess,
|
|
501
|
+
transactionId: parsed.transactionId
|
|
502
|
+
});
|
|
503
|
+
if (this.options.onReversalResult) {
|
|
504
|
+
await this.options.onReversalResult(parsed);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
422
507
|
/**
|
|
423
508
|
* Handle STK Push callback and invoke appropriate handlers
|
|
424
509
|
*/
|
|
@@ -956,38 +1041,6 @@ var MpesaClient = class {
|
|
|
956
1041
|
);
|
|
957
1042
|
}
|
|
958
1043
|
}
|
|
959
|
-
/**
|
|
960
|
-
* Simulate C2B transaction (Sandbox only)
|
|
961
|
-
* Used for testing C2B payments in sandbox environment
|
|
962
|
-
*/
|
|
963
|
-
async simulateC2B(request) {
|
|
964
|
-
if (this.config.environment !== "sandbox") {
|
|
965
|
-
throw new MpesaValidationError(
|
|
966
|
-
"C2B simulation is only available in sandbox environment"
|
|
967
|
-
);
|
|
968
|
-
}
|
|
969
|
-
if (request.amount < 1) {
|
|
970
|
-
throw new MpesaValidationError("Amount must be at least 1 KES");
|
|
971
|
-
}
|
|
972
|
-
if (!request.billRefNumber || request.billRefNumber.length > 20) {
|
|
973
|
-
throw new MpesaValidationError(
|
|
974
|
-
"Bill reference is required and must be 20 characters or less"
|
|
975
|
-
);
|
|
976
|
-
}
|
|
977
|
-
const phone = this.validateAndFormatPhone(request.msisdn);
|
|
978
|
-
const payload = {
|
|
979
|
-
ShortCode: request.shortCode || this.config.shortcode,
|
|
980
|
-
CommandID: request.commandID || "CustomerPayBillOnline",
|
|
981
|
-
Amount: Math.floor(request.amount),
|
|
982
|
-
Msisdn: phone,
|
|
983
|
-
BillRefNumber: request.billRefNumber
|
|
984
|
-
};
|
|
985
|
-
return this.makeRequest(
|
|
986
|
-
"/mpesa/c2b/v2/simulate",
|
|
987
|
-
payload,
|
|
988
|
-
`c2b:simulate:${phone}`
|
|
989
|
-
);
|
|
990
|
-
}
|
|
991
1044
|
/**
|
|
992
1045
|
* B2C - Send money from business to customer
|
|
993
1046
|
*/
|
|
@@ -1194,6 +1247,87 @@ var MpesaClient = class {
|
|
|
1194
1247
|
getConfig() {
|
|
1195
1248
|
return this.config;
|
|
1196
1249
|
}
|
|
1250
|
+
/**
|
|
1251
|
+
* Handle B2C result callback
|
|
1252
|
+
*/
|
|
1253
|
+
async handleB2CResult(callback, ipAddress) {
|
|
1254
|
+
try {
|
|
1255
|
+
await this.callbackHandler.handleB2CResult(callback, ipAddress);
|
|
1256
|
+
return this.callbackHandler.createCallbackResponse(true);
|
|
1257
|
+
} catch (error) {
|
|
1258
|
+
console.error("B2C result handling error:", error);
|
|
1259
|
+
return this.callbackHandler.createCallbackResponse(
|
|
1260
|
+
false,
|
|
1261
|
+
"Processing failed"
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
/**
|
|
1266
|
+
* Handle B2B result callback
|
|
1267
|
+
*/
|
|
1268
|
+
async handleB2BResult(callback, ipAddress) {
|
|
1269
|
+
try {
|
|
1270
|
+
await this.callbackHandler.handleB2BResult(callback, ipAddress);
|
|
1271
|
+
return this.callbackHandler.createCallbackResponse(true);
|
|
1272
|
+
} catch (error) {
|
|
1273
|
+
console.error("B2B result handling error:", error);
|
|
1274
|
+
return this.callbackHandler.createCallbackResponse(
|
|
1275
|
+
false,
|
|
1276
|
+
"Processing failed"
|
|
1277
|
+
);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
1281
|
+
* Handle Account Balance result callback
|
|
1282
|
+
*/
|
|
1283
|
+
async handleAccountBalanceResult(callback, ipAddress) {
|
|
1284
|
+
try {
|
|
1285
|
+
await this.callbackHandler.handleAccountBalanceResult(
|
|
1286
|
+
callback,
|
|
1287
|
+
ipAddress
|
|
1288
|
+
);
|
|
1289
|
+
return this.callbackHandler.createCallbackResponse(true);
|
|
1290
|
+
} catch (error) {
|
|
1291
|
+
console.error("Account Balance result handling error:", error);
|
|
1292
|
+
return this.callbackHandler.createCallbackResponse(
|
|
1293
|
+
false,
|
|
1294
|
+
"Processing failed"
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Handle Transaction Status result callback
|
|
1300
|
+
*/
|
|
1301
|
+
async handleTransactionStatusResult(callback, ipAddress) {
|
|
1302
|
+
try {
|
|
1303
|
+
await this.callbackHandler.handleTransactionStatusResult(
|
|
1304
|
+
callback,
|
|
1305
|
+
ipAddress
|
|
1306
|
+
);
|
|
1307
|
+
return this.callbackHandler.createCallbackResponse(true);
|
|
1308
|
+
} catch (error) {
|
|
1309
|
+
console.error("Transaction Status result handling error:", error);
|
|
1310
|
+
return this.callbackHandler.createCallbackResponse(
|
|
1311
|
+
false,
|
|
1312
|
+
"Processing failed"
|
|
1313
|
+
);
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
/**
|
|
1317
|
+
* Handle Reversal result callback
|
|
1318
|
+
*/
|
|
1319
|
+
async handleReversalResult(callback, ipAddress) {
|
|
1320
|
+
try {
|
|
1321
|
+
await this.callbackHandler.handleReversalResult(callback, ipAddress);
|
|
1322
|
+
return this.callbackHandler.createCallbackResponse(true);
|
|
1323
|
+
} catch (error) {
|
|
1324
|
+
console.error("Reversal result handling error:", error);
|
|
1325
|
+
return this.callbackHandler.createCallbackResponse(
|
|
1326
|
+
false,
|
|
1327
|
+
"Processing failed"
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1197
1331
|
/**
|
|
1198
1332
|
* Get rate limiter usage for a key
|
|
1199
1333
|
*/
|
package/dist/index.mjs
CHANGED
|
@@ -370,6 +370,91 @@ var MpesaCallbackHandler = class {
|
|
|
370
370
|
};
|
|
371
371
|
return errorMessages[resultCode] || `Transaction failed with code: ${resultCode}`;
|
|
372
372
|
}
|
|
373
|
+
/**
|
|
374
|
+
* Handle B2C result callback
|
|
375
|
+
*/
|
|
376
|
+
async handleB2CResult(callback, ipAddress) {
|
|
377
|
+
if (ipAddress && !this.validateCallbackIp(ipAddress)) {
|
|
378
|
+
this.log("warn", `Invalid callback IP: ${ipAddress}`);
|
|
379
|
+
throw new Error(`Invalid callback IP: ${ipAddress}`);
|
|
380
|
+
}
|
|
381
|
+
const parsed = this.parseB2CCallback(callback);
|
|
382
|
+
this.log("info", "Processing B2C result", {
|
|
383
|
+
transactionId: parsed.transactionId,
|
|
384
|
+
isSuccess: parsed.isSuccess
|
|
385
|
+
});
|
|
386
|
+
if (this.options.onB2CResult) {
|
|
387
|
+
await this.options.onB2CResult(parsed);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Handle B2B result callback
|
|
392
|
+
*/
|
|
393
|
+
async handleB2BResult(callback, ipAddress) {
|
|
394
|
+
if (ipAddress && !this.validateCallbackIp(ipAddress)) {
|
|
395
|
+
this.log("warn", `Invalid callback IP: ${ipAddress}`);
|
|
396
|
+
throw new Error(`Invalid callback IP: ${ipAddress}`);
|
|
397
|
+
}
|
|
398
|
+
const parsed = this.parseB2BCallback(callback);
|
|
399
|
+
this.log("info", "Processing B2B result", {
|
|
400
|
+
transactionId: parsed.transactionId,
|
|
401
|
+
isSuccess: parsed.isSuccess
|
|
402
|
+
});
|
|
403
|
+
if (this.options.onB2BResult) {
|
|
404
|
+
await this.options.onB2BResult(parsed);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Handle Account Balance result callback
|
|
409
|
+
*/
|
|
410
|
+
async handleAccountBalanceResult(callback, ipAddress) {
|
|
411
|
+
if (ipAddress && !this.validateCallbackIp(ipAddress)) {
|
|
412
|
+
this.log("warn", `Invalid callback IP: ${ipAddress}`);
|
|
413
|
+
throw new Error(`Invalid callback IP: ${ipAddress}`);
|
|
414
|
+
}
|
|
415
|
+
const parsed = this.parseAccountBalanceCallback(callback);
|
|
416
|
+
this.log("info", "Processing Account Balance result", {
|
|
417
|
+
isSuccess: parsed.isSuccess,
|
|
418
|
+
availableBalance: parsed.availableBalance
|
|
419
|
+
});
|
|
420
|
+
if (this.options.onAccountBalanceResult) {
|
|
421
|
+
await this.options.onAccountBalanceResult(parsed);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Handle Transaction Status result callback
|
|
426
|
+
*/
|
|
427
|
+
async handleTransactionStatusResult(callback, ipAddress) {
|
|
428
|
+
if (ipAddress && !this.validateCallbackIp(ipAddress)) {
|
|
429
|
+
this.log("warn", `Invalid callback IP: ${ipAddress}`);
|
|
430
|
+
throw new Error(`Invalid callback IP: ${ipAddress}`);
|
|
431
|
+
}
|
|
432
|
+
const parsed = this.parseTransactionStatusCallback(callback);
|
|
433
|
+
this.log("info", "Processing Transaction Status result", {
|
|
434
|
+
isSuccess: parsed.isSuccess,
|
|
435
|
+
receiptNo: parsed.receiptNo
|
|
436
|
+
});
|
|
437
|
+
if (this.options.onTransactionStatusResult) {
|
|
438
|
+
await this.options.onTransactionStatusResult(parsed);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Handle Reversal result callback
|
|
443
|
+
*/
|
|
444
|
+
async handleReversalResult(callback, ipAddress) {
|
|
445
|
+
if (ipAddress && !this.validateCallbackIp(ipAddress)) {
|
|
446
|
+
this.log("warn", `Invalid callback IP: ${ipAddress}`);
|
|
447
|
+
throw new Error(`Invalid callback IP: ${ipAddress}`);
|
|
448
|
+
}
|
|
449
|
+
const parsed = this.parseReversalCallback(callback);
|
|
450
|
+
this.log("info", "Processing Reversal result", {
|
|
451
|
+
isSuccess: parsed.isSuccess,
|
|
452
|
+
transactionId: parsed.transactionId
|
|
453
|
+
});
|
|
454
|
+
if (this.options.onReversalResult) {
|
|
455
|
+
await this.options.onReversalResult(parsed);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
373
458
|
/**
|
|
374
459
|
* Handle STK Push callback and invoke appropriate handlers
|
|
375
460
|
*/
|
|
@@ -907,38 +992,6 @@ var MpesaClient = class {
|
|
|
907
992
|
);
|
|
908
993
|
}
|
|
909
994
|
}
|
|
910
|
-
/**
|
|
911
|
-
* Simulate C2B transaction (Sandbox only)
|
|
912
|
-
* Used for testing C2B payments in sandbox environment
|
|
913
|
-
*/
|
|
914
|
-
async simulateC2B(request) {
|
|
915
|
-
if (this.config.environment !== "sandbox") {
|
|
916
|
-
throw new MpesaValidationError(
|
|
917
|
-
"C2B simulation is only available in sandbox environment"
|
|
918
|
-
);
|
|
919
|
-
}
|
|
920
|
-
if (request.amount < 1) {
|
|
921
|
-
throw new MpesaValidationError("Amount must be at least 1 KES");
|
|
922
|
-
}
|
|
923
|
-
if (!request.billRefNumber || request.billRefNumber.length > 20) {
|
|
924
|
-
throw new MpesaValidationError(
|
|
925
|
-
"Bill reference is required and must be 20 characters or less"
|
|
926
|
-
);
|
|
927
|
-
}
|
|
928
|
-
const phone = this.validateAndFormatPhone(request.msisdn);
|
|
929
|
-
const payload = {
|
|
930
|
-
ShortCode: request.shortCode || this.config.shortcode,
|
|
931
|
-
CommandID: request.commandID || "CustomerPayBillOnline",
|
|
932
|
-
Amount: Math.floor(request.amount),
|
|
933
|
-
Msisdn: phone,
|
|
934
|
-
BillRefNumber: request.billRefNumber
|
|
935
|
-
};
|
|
936
|
-
return this.makeRequest(
|
|
937
|
-
"/mpesa/c2b/v2/simulate",
|
|
938
|
-
payload,
|
|
939
|
-
`c2b:simulate:${phone}`
|
|
940
|
-
);
|
|
941
|
-
}
|
|
942
995
|
/**
|
|
943
996
|
* B2C - Send money from business to customer
|
|
944
997
|
*/
|
|
@@ -1145,6 +1198,87 @@ var MpesaClient = class {
|
|
|
1145
1198
|
getConfig() {
|
|
1146
1199
|
return this.config;
|
|
1147
1200
|
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Handle B2C result callback
|
|
1203
|
+
*/
|
|
1204
|
+
async handleB2CResult(callback, ipAddress) {
|
|
1205
|
+
try {
|
|
1206
|
+
await this.callbackHandler.handleB2CResult(callback, ipAddress);
|
|
1207
|
+
return this.callbackHandler.createCallbackResponse(true);
|
|
1208
|
+
} catch (error) {
|
|
1209
|
+
console.error("B2C result handling error:", error);
|
|
1210
|
+
return this.callbackHandler.createCallbackResponse(
|
|
1211
|
+
false,
|
|
1212
|
+
"Processing failed"
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
/**
|
|
1217
|
+
* Handle B2B result callback
|
|
1218
|
+
*/
|
|
1219
|
+
async handleB2BResult(callback, ipAddress) {
|
|
1220
|
+
try {
|
|
1221
|
+
await this.callbackHandler.handleB2BResult(callback, ipAddress);
|
|
1222
|
+
return this.callbackHandler.createCallbackResponse(true);
|
|
1223
|
+
} catch (error) {
|
|
1224
|
+
console.error("B2B result handling error:", error);
|
|
1225
|
+
return this.callbackHandler.createCallbackResponse(
|
|
1226
|
+
false,
|
|
1227
|
+
"Processing failed"
|
|
1228
|
+
);
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Handle Account Balance result callback
|
|
1233
|
+
*/
|
|
1234
|
+
async handleAccountBalanceResult(callback, ipAddress) {
|
|
1235
|
+
try {
|
|
1236
|
+
await this.callbackHandler.handleAccountBalanceResult(
|
|
1237
|
+
callback,
|
|
1238
|
+
ipAddress
|
|
1239
|
+
);
|
|
1240
|
+
return this.callbackHandler.createCallbackResponse(true);
|
|
1241
|
+
} catch (error) {
|
|
1242
|
+
console.error("Account Balance result handling error:", error);
|
|
1243
|
+
return this.callbackHandler.createCallbackResponse(
|
|
1244
|
+
false,
|
|
1245
|
+
"Processing failed"
|
|
1246
|
+
);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
/**
|
|
1250
|
+
* Handle Transaction Status result callback
|
|
1251
|
+
*/
|
|
1252
|
+
async handleTransactionStatusResult(callback, ipAddress) {
|
|
1253
|
+
try {
|
|
1254
|
+
await this.callbackHandler.handleTransactionStatusResult(
|
|
1255
|
+
callback,
|
|
1256
|
+
ipAddress
|
|
1257
|
+
);
|
|
1258
|
+
return this.callbackHandler.createCallbackResponse(true);
|
|
1259
|
+
} catch (error) {
|
|
1260
|
+
console.error("Transaction Status result handling error:", error);
|
|
1261
|
+
return this.callbackHandler.createCallbackResponse(
|
|
1262
|
+
false,
|
|
1263
|
+
"Processing failed"
|
|
1264
|
+
);
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Handle Reversal result callback
|
|
1269
|
+
*/
|
|
1270
|
+
async handleReversalResult(callback, ipAddress) {
|
|
1271
|
+
try {
|
|
1272
|
+
await this.callbackHandler.handleReversalResult(callback, ipAddress);
|
|
1273
|
+
return this.callbackHandler.createCallbackResponse(true);
|
|
1274
|
+
} catch (error) {
|
|
1275
|
+
console.error("Reversal result handling error:", error);
|
|
1276
|
+
return this.callbackHandler.createCallbackResponse(
|
|
1277
|
+
false,
|
|
1278
|
+
"Processing failed"
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1148
1282
|
/**
|
|
1149
1283
|
* Get rate limiter usage for a key
|
|
1150
1284
|
*/
|