pesafy 0.3.0 → 0.3.2
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.
Potentially problematic release.
This version of pesafy might be problematic. Click here for more details.
- package/dist/index.cjs +59 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +171 -103
- package/dist/index.d.ts +171 -103
- package/dist/index.js +53 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -99,145 +99,127 @@ interface DynamicQRResponse {
|
|
|
99
99
|
* C2B v1 used SHA-256 hashed MSISDN — do NOT use v1.
|
|
100
100
|
*/
|
|
101
101
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
102
|
+
* The two valid C2B CommandID values:
|
|
103
|
+
* - CustomerPayBillOnline → payment to a Paybill number
|
|
104
|
+
* - CustomerBuyGoodsOnline → payment to a Till number
|
|
105
|
+
*/
|
|
106
|
+
type C2BCommandId = "CustomerPayBillOnline" | "CustomerBuyGoodsOnline";
|
|
107
|
+
/**
|
|
108
|
+
* Default action when the ValidationURL is unreachable.
|
|
109
|
+
* "Completed" → M-PESA auto-completes the transaction.
|
|
110
|
+
* "Cancelled" → M-PESA auto-cancels the transaction.
|
|
111
|
+
* Note: values are case-sensitive per Daraja docs.
|
|
105
112
|
*/
|
|
106
113
|
type C2BResponseType = "Completed" | "Cancelled";
|
|
107
114
|
interface C2BRegisterUrlRequest {
|
|
108
|
-
/**
|
|
115
|
+
/** Paybill or Till short code */
|
|
109
116
|
shortCode: string;
|
|
110
|
-
/**
|
|
111
|
-
* What M-Pesa does if your Validation URL is unreachable.
|
|
112
|
-
* Only relevant if External Validation is enabled on your shortcode.
|
|
113
|
-
* Defaults to "Completed".
|
|
114
|
-
*/
|
|
115
|
-
responseType?: C2BResponseType;
|
|
116
|
-
/**
|
|
117
|
-
* URL that receives payment confirmation after transaction completes.
|
|
118
|
-
* Must be HTTPS in production. HTTP is allowed in sandbox.
|
|
119
|
-
*/
|
|
117
|
+
/** URL that receives payment confirmation after a successful transaction */
|
|
120
118
|
confirmationUrl: string;
|
|
121
|
-
/**
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
* Optional — omit if validation is not required.
|
|
125
|
-
*/
|
|
126
|
-
validationUrl?: string;
|
|
127
|
-
}
|
|
128
|
-
interface C2BRegisterUrlResponse {
|
|
129
|
-
/**
|
|
130
|
-
* Global unique identifier for the request.
|
|
131
|
-
* NOTE: Daraja has a typo in their field name ("Coversa" not "Conversa").
|
|
132
|
-
* We mirror it exactly so JSON parsing works.
|
|
133
|
-
*/
|
|
134
|
-
OriginatorCoversationID: string;
|
|
135
|
-
ResponseCode: string;
|
|
136
|
-
ResponseDescription: string;
|
|
119
|
+
/** URL that receives validation requests (only when external validation is enabled) */
|
|
120
|
+
validationUrl: string;
|
|
121
|
+
responseType?: C2BResponseType;
|
|
137
122
|
}
|
|
138
|
-
/**
|
|
139
|
-
* CommandID controls whether this is a Paybill or Buy Goods (Till) payment.
|
|
140
|
-
* - "CustomerPayBillOnline" → Paybill (requires BillRefNumber / account number)
|
|
141
|
-
* - "CustomerBuyGoodsOnline" → Till/Buy Goods (BillRefNumber is null)
|
|
142
|
-
*/
|
|
143
|
-
type C2BCommandId = "CustomerPayBillOnline" | "CustomerBuyGoodsOnline";
|
|
144
123
|
interface C2BSimulateRequest {
|
|
145
|
-
/**
|
|
124
|
+
/** Paybill or Till short code */
|
|
146
125
|
shortCode: string;
|
|
147
|
-
/**
|
|
148
|
-
|
|
149
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Transaction type.
|
|
128
|
+
* "CustomerPayBillOnline" → payment to a Paybill number (default)
|
|
129
|
+
* "CustomerBuyGoodsOnline" → payment to a Till number
|
|
130
|
+
*/
|
|
131
|
+
commandId?: C2BCommandId;
|
|
132
|
+
/** Transaction amount (whole number, min 1 KES) */
|
|
150
133
|
amount: number;
|
|
151
|
-
/**
|
|
134
|
+
/** Customer's phone number — any valid Kenyan MSISDN */
|
|
152
135
|
phoneNumber: string;
|
|
153
136
|
/**
|
|
154
|
-
* Account
|
|
155
|
-
*
|
|
137
|
+
* Account reference for Paybill payments.
|
|
138
|
+
* Must be null / omitted for CustomerBuyGoodsOnline.
|
|
156
139
|
*/
|
|
157
|
-
billRefNumber?: string
|
|
158
|
-
}
|
|
159
|
-
interface C2BSimulateResponse {
|
|
160
|
-
/** @see C2BRegisterUrlResponse.OriginatorCoversationID (Daraja typo) */
|
|
161
|
-
OriginatorCoversationID: string;
|
|
162
|
-
ResponseCode: string;
|
|
163
|
-
ResponseDescription: string;
|
|
140
|
+
billRefNumber?: string;
|
|
164
141
|
}
|
|
165
142
|
/**
|
|
166
|
-
*
|
|
167
|
-
* C2B v2 returns a masked MSISDN: "2547 ***** 126"
|
|
168
|
-
*
|
|
169
|
-
* This type covers BOTH the confirmation and validation callbacks —
|
|
170
|
-
* they share the same shape. The difference is:
|
|
171
|
-
* - Validation: OrgAccountBalance is blank; you must respond Accept/Reject.
|
|
172
|
-
* - Confirmation: OrgAccountBalance has the post-payment balance.
|
|
143
|
+
* Shared fields present in both Validation and Confirmation callback payloads.
|
|
173
144
|
*/
|
|
174
|
-
interface
|
|
175
|
-
/** "Pay Bill" or "Buy Goods" */
|
|
145
|
+
interface C2BCallbackPayloadBase {
|
|
176
146
|
TransactionType: string;
|
|
177
|
-
/** Unique M-
|
|
147
|
+
/** Unique M-PESA transaction ID (e.g. "RKL51ZDR4F") */
|
|
178
148
|
TransID: string;
|
|
179
|
-
/**
|
|
149
|
+
/** 14-digit timestamp: YYYYMMDDHHmmss */
|
|
180
150
|
TransTime: string;
|
|
181
|
-
/**
|
|
151
|
+
/** Transaction amount as a string (e.g. "5.00") */
|
|
182
152
|
TransAmount: string;
|
|
183
|
-
/** Your Paybill or Till shortcode */
|
|
184
153
|
BusinessShortCode: string;
|
|
185
|
-
/**
|
|
186
|
-
* Account reference / bill number entered by customer.
|
|
187
|
-
* Applies to Paybill transactions. Empty string for Buy Goods.
|
|
188
|
-
*/
|
|
154
|
+
/** Account reference; empty for Till transactions */
|
|
189
155
|
BillRefNumber: string;
|
|
190
|
-
/** Invoice number if applicable (usually empty string) */
|
|
191
156
|
InvoiceNumber: string;
|
|
192
|
-
/**
|
|
193
|
-
* Post-payment balance of your Utility Account (confirmation only).
|
|
194
|
-
* Empty string in validation requests.
|
|
195
|
-
*/
|
|
196
157
|
OrgAccountBalance: string;
|
|
197
|
-
/**
|
|
198
|
-
* Opaque ID the partner can echo back in the validation response.
|
|
199
|
-
* Safaricom sends it back in the confirmation if you returned it.
|
|
200
|
-
*/
|
|
201
158
|
ThirdPartyTransID: string;
|
|
202
|
-
/**
|
|
203
|
-
* Masked phone number: "2547 ***** 126"
|
|
204
|
-
* C2B v2 masks for privacy. C2B v1 used SHA-256 hash.
|
|
205
|
-
*/
|
|
159
|
+
/** v2: masked MSISDN e.g. "2547 ***** 126" */
|
|
206
160
|
MSISDN: string;
|
|
207
|
-
/** Customer first name (may be empty) */
|
|
208
161
|
FirstName: string;
|
|
209
|
-
/** Customer middle name (may be empty) */
|
|
210
162
|
MiddleName: string;
|
|
211
|
-
/** Customer last name (may be empty) */
|
|
212
163
|
LastName: string;
|
|
213
164
|
}
|
|
165
|
+
/** Payload posted to your ValidationURL (if external validation is enabled) */
|
|
166
|
+
type C2BValidationPayload = C2BCallbackPayloadBase;
|
|
167
|
+
/** Payload posted to your ConfirmationURL after successful payment */
|
|
168
|
+
type C2BConfirmationPayload = C2BCallbackPayloadBase;
|
|
214
169
|
/**
|
|
215
|
-
*
|
|
216
|
-
*
|
|
170
|
+
* Union of both C2B callback types.
|
|
171
|
+
* Use the discriminated `TransactionType` field if you need to distinguish them,
|
|
172
|
+
* or register separate Express routes for each URL.
|
|
217
173
|
*/
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* "0" to accept the payment.
|
|
221
|
-
* Any of the C2B rejection codes to reject (e.g. "C2B00011").
|
|
222
|
-
*/
|
|
223
|
-
ResultCode: string;
|
|
224
|
-
/** "Accepted" or "Rejected" */
|
|
225
|
-
ResultDesc: string;
|
|
226
|
-
}
|
|
174
|
+
type C2BCallbackPayload = C2BValidationPayload | C2BConfirmationPayload;
|
|
227
175
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
176
|
+
* Codes your ValidationURL must return to Safaricom to accept or reject
|
|
177
|
+
* a payment before it is processed.
|
|
230
178
|
*/
|
|
231
179
|
declare const C2B_REJECTION_CODES: {
|
|
232
|
-
|
|
233
|
-
readonly
|
|
234
|
-
|
|
235
|
-
readonly
|
|
236
|
-
readonly INVALID_SHORT_CODE: "C2B00015";
|
|
237
|
-
readonly OTHER_ERROR: "C2B00016";
|
|
180
|
+
/** Accept the transaction — M-PESA proceeds to process and confirm */
|
|
181
|
+
readonly ACCEPT: "0";
|
|
182
|
+
/** Reject the transaction — M-PESA cancels and notifies the customer */
|
|
183
|
+
readonly REJECT: "1";
|
|
238
184
|
};
|
|
239
185
|
type C2BRejectionCode = (typeof C2B_REJECTION_CODES)[keyof typeof C2B_REJECTION_CODES];
|
|
240
186
|
|
|
187
|
+
/**
|
|
188
|
+
* Actual response shape from Daraja.
|
|
189
|
+
* Note: Daraja's field name has a typo ("CoversationID" — missing the 'n').
|
|
190
|
+
* We match it exactly so JSON parsing is lossless.
|
|
191
|
+
*/
|
|
192
|
+
interface C2BRegisterUrlResponse {
|
|
193
|
+
/** Global unique identifier for this registration request. Daraja typo: "Coversation" */
|
|
194
|
+
OriginatorCoversationID: string;
|
|
195
|
+
/** "0" = accepted */
|
|
196
|
+
ResponseCode: string;
|
|
197
|
+
ResponseDescription: string;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* C2B Simulate (sandbox only)
|
|
202
|
+
* API: POST /mpesa/c2b/v2/simulate
|
|
203
|
+
*
|
|
204
|
+
* Simulates a customer paying a Paybill or Till number.
|
|
205
|
+
* This endpoint is NOT available in production — use STK Push or Dynamic QR
|
|
206
|
+
* for production payment initiation.
|
|
207
|
+
*/
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Actual response shape from Daraja.
|
|
211
|
+
* Note: Daraja's field name has a typo ("CoversationID" — missing the 'n').
|
|
212
|
+
* We match it exactly so JSON parsing is lossless.
|
|
213
|
+
* There is NO ConversationID field in this response (unlike B2C/B2B).
|
|
214
|
+
*/
|
|
215
|
+
interface C2BSimulateResponse {
|
|
216
|
+
/** Global unique identifier for this simulate request. Daraja typo: "Coversation" */
|
|
217
|
+
OriginatorCoversationID: string;
|
|
218
|
+
/** "0" = accepted */
|
|
219
|
+
ResponseCode: string;
|
|
220
|
+
ResponseDescription: string;
|
|
221
|
+
}
|
|
222
|
+
|
|
241
223
|
/** B2B (Business to Business) types */
|
|
242
224
|
type B2BCommandId = "BusinessPayBill" | "BusinessBuyGoods" | "DisburseFundsToBusiness" | "BusinessToBusinessTransfer";
|
|
243
225
|
interface B2BRequest {
|
|
@@ -339,6 +321,92 @@ interface StkQueryResponse {
|
|
|
339
321
|
ResultCode: number;
|
|
340
322
|
ResultDesc: string;
|
|
341
323
|
}
|
|
324
|
+
/** A single metadata item in a successful STK callback */
|
|
325
|
+
interface StkCallbackMetadataItem {
|
|
326
|
+
Name: "Amount" | "MpesaReceiptNumber" | "TransactionDate" | "PhoneNumber";
|
|
327
|
+
/** Present on successful transactions; absent on failure */
|
|
328
|
+
Value?: number | string;
|
|
329
|
+
}
|
|
330
|
+
/** Inner callback object for a SUCCESSFUL STK Push */
|
|
331
|
+
interface StkCallbackSuccess {
|
|
332
|
+
MerchantRequestID: string;
|
|
333
|
+
CheckoutRequestID: string;
|
|
334
|
+
/** 0 = success */
|
|
335
|
+
ResultCode: 0;
|
|
336
|
+
ResultDesc: string;
|
|
337
|
+
CallbackMetadata: {
|
|
338
|
+
Item: StkCallbackMetadataItem[];
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/** Inner callback object for a FAILED/CANCELLED STK Push */
|
|
342
|
+
interface StkCallbackFailure {
|
|
343
|
+
MerchantRequestID: string;
|
|
344
|
+
CheckoutRequestID: string;
|
|
345
|
+
/** Non-zero result codes: e.g. 1032 = cancelled by user */
|
|
346
|
+
ResultCode: number;
|
|
347
|
+
ResultDesc: string;
|
|
348
|
+
CallbackMetadata?: never;
|
|
349
|
+
}
|
|
350
|
+
type StkCallbackInner = StkCallbackSuccess | StkCallbackFailure;
|
|
351
|
+
/** Full wrapper that Safaricom POSTs to your CallBackURL */
|
|
352
|
+
interface StkPushCallback {
|
|
353
|
+
Body: {
|
|
354
|
+
stkCallback: StkCallbackInner;
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Type guard — narrows an StkCallbackInner to the success shape.
|
|
359
|
+
* Usage:
|
|
360
|
+
* if (isStkCallbackSuccess(callback.Body.stkCallback)) {
|
|
361
|
+
* const receipt = getCallbackValue(callback, "MpesaReceiptNumber");
|
|
362
|
+
* }
|
|
363
|
+
*/
|
|
364
|
+
declare function isStkCallbackSuccess(cb: StkCallbackInner): cb is StkCallbackSuccess;
|
|
365
|
+
/**
|
|
366
|
+
* Extracts a named value from a successful callback's metadata items.
|
|
367
|
+
* Returns undefined if the key is absent or the callback failed.
|
|
368
|
+
*/
|
|
369
|
+
declare function getCallbackValue(callback: StkPushCallback, name: StkCallbackMetadataItem["Name"]): string | number | undefined;
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Shared phone number utilities for M-Pesa API calls.
|
|
373
|
+
*
|
|
374
|
+
* Two formatters are intentionally separate:
|
|
375
|
+
* - formatSafaricomPhone → strict, for STK Push (only Safaricom/Airtel)
|
|
376
|
+
* - formatKenyanMsisdn → permissive, for C2B simulate and B2C PartyB
|
|
377
|
+
*
|
|
378
|
+
* Daraja consistently expects 12-digit MSISDN without the '+' prefix.
|
|
379
|
+
*/
|
|
380
|
+
/**
|
|
381
|
+
* Strict formatter for STK Push.
|
|
382
|
+
* Accepts Safaricom (2547xx) and Airtel Kenya (2541x) numbers only.
|
|
383
|
+
* Throws a clear error on invalid input so Daraja never receives a bad MSISDN.
|
|
384
|
+
*/
|
|
385
|
+
declare function formatSafaricomPhone(phone: string): string;
|
|
386
|
+
/**
|
|
387
|
+
* Permissive formatter for C2B simulate and B2C PartyB.
|
|
388
|
+
* Accepts any valid 12-digit Kenyan MSISDN (Safaricom, Airtel, Telkom, …).
|
|
389
|
+
* Still throws if the result is structurally impossible.
|
|
390
|
+
*/
|
|
391
|
+
declare function formatKenyanMsisdn(phone: string): string;
|
|
392
|
+
/**
|
|
393
|
+
* Converts a formatted MSISDN string to the numeric form Daraja expects in
|
|
394
|
+
* C2B simulate requests ("Msisdn": 254708374149 — no quotes in the JSON).
|
|
395
|
+
*/
|
|
396
|
+
declare function msisdnToNumber(phone: string): number;
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* STK Push utilities
|
|
400
|
+
*
|
|
401
|
+
* Phone formatting delegates to the shared `formatSafaricomPhone` util which
|
|
402
|
+
* validates Safaricom/Airtel numbers and throws a clear error on bad input.
|
|
403
|
+
*/
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Generates a Daraja-compatible timestamp: YYYYMMDDHHmmss
|
|
407
|
+
* Call this once per request and reuse the value.
|
|
408
|
+
*/
|
|
409
|
+
declare function getTimestamp(): string;
|
|
342
410
|
|
|
343
411
|
type Environment = "sandbox" | "production";
|
|
344
412
|
declare const DARAJA_BASE_URLS: {
|
|
@@ -560,4 +628,4 @@ declare class PesafyError extends Error {
|
|
|
560
628
|
}
|
|
561
629
|
declare function createError(options: PesafyErrorOptions): PesafyError;
|
|
562
630
|
|
|
563
|
-
export { type B2BRequest, type B2BResponse, type B2CRequest, type B2CResponse, type B2CWebhook, type C2BCallbackPayload, type C2BCommandId, type
|
|
631
|
+
export { type B2BRequest, type B2BResponse, type B2CRequest, type B2CResponse, type B2CWebhook, type C2BCallbackPayload, type C2BCallbackPayloadBase, type C2BCommandId, type C2BConfirmationPayload, type C2BRegisterUrlRequest, type C2BRegisterUrlResponse, type C2BRejectionCode, type C2BSimulateRequest, type C2BSimulateResponse, type C2BValidationPayload, type C2BWebhook, C2B_REJECTION_CODES, DARAJA_BASE_URLS, type DynamicQRRequest, type DynamicQRResponse, type ErrorCode, Mpesa, type MpesaConfig, type MpesaExpressConfig, PesafyError, type RetryOptions, type RetryResult, type ReversalRequest, type ReversalResponse, type StkCallbackFailure, type StkCallbackInner, type StkCallbackMetadataItem, type StkCallbackSuccess, type StkPushCallback, type StkPushRequest, type StkPushResponse, type StkPushWebhook, type StkQueryRequest, type StkQueryResponse, TokenManager, type TransactionStatusRequest, type TransactionStatusResponse, type WebhookEvent, type WebhookEventType, type WebhookHandlerOptions, type WebhookHandlerResult, createError, createMpesaExpressClient, createMpesaExpressRouter, encryptSecurityCredential, extractAmount, extractTransactionId, formatKenyanMsisdn, formatSafaricomPhone as formatPhoneNumber, formatSafaricomPhone, getCallbackValue, getTimestamp, handleWebhook, isStkCallbackSuccess, msisdnToNumber, retryWithBackoff, verifyWebhookIP };
|
package/dist/index.d.ts
CHANGED
|
@@ -99,145 +99,127 @@ interface DynamicQRResponse {
|
|
|
99
99
|
* C2B v1 used SHA-256 hashed MSISDN — do NOT use v1.
|
|
100
100
|
*/
|
|
101
101
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
102
|
+
* The two valid C2B CommandID values:
|
|
103
|
+
* - CustomerPayBillOnline → payment to a Paybill number
|
|
104
|
+
* - CustomerBuyGoodsOnline → payment to a Till number
|
|
105
|
+
*/
|
|
106
|
+
type C2BCommandId = "CustomerPayBillOnline" | "CustomerBuyGoodsOnline";
|
|
107
|
+
/**
|
|
108
|
+
* Default action when the ValidationURL is unreachable.
|
|
109
|
+
* "Completed" → M-PESA auto-completes the transaction.
|
|
110
|
+
* "Cancelled" → M-PESA auto-cancels the transaction.
|
|
111
|
+
* Note: values are case-sensitive per Daraja docs.
|
|
105
112
|
*/
|
|
106
113
|
type C2BResponseType = "Completed" | "Cancelled";
|
|
107
114
|
interface C2BRegisterUrlRequest {
|
|
108
|
-
/**
|
|
115
|
+
/** Paybill or Till short code */
|
|
109
116
|
shortCode: string;
|
|
110
|
-
/**
|
|
111
|
-
* What M-Pesa does if your Validation URL is unreachable.
|
|
112
|
-
* Only relevant if External Validation is enabled on your shortcode.
|
|
113
|
-
* Defaults to "Completed".
|
|
114
|
-
*/
|
|
115
|
-
responseType?: C2BResponseType;
|
|
116
|
-
/**
|
|
117
|
-
* URL that receives payment confirmation after transaction completes.
|
|
118
|
-
* Must be HTTPS in production. HTTP is allowed in sandbox.
|
|
119
|
-
*/
|
|
117
|
+
/** URL that receives payment confirmation after a successful transaction */
|
|
120
118
|
confirmationUrl: string;
|
|
121
|
-
/**
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
* Optional — omit if validation is not required.
|
|
125
|
-
*/
|
|
126
|
-
validationUrl?: string;
|
|
127
|
-
}
|
|
128
|
-
interface C2BRegisterUrlResponse {
|
|
129
|
-
/**
|
|
130
|
-
* Global unique identifier for the request.
|
|
131
|
-
* NOTE: Daraja has a typo in their field name ("Coversa" not "Conversa").
|
|
132
|
-
* We mirror it exactly so JSON parsing works.
|
|
133
|
-
*/
|
|
134
|
-
OriginatorCoversationID: string;
|
|
135
|
-
ResponseCode: string;
|
|
136
|
-
ResponseDescription: string;
|
|
119
|
+
/** URL that receives validation requests (only when external validation is enabled) */
|
|
120
|
+
validationUrl: string;
|
|
121
|
+
responseType?: C2BResponseType;
|
|
137
122
|
}
|
|
138
|
-
/**
|
|
139
|
-
* CommandID controls whether this is a Paybill or Buy Goods (Till) payment.
|
|
140
|
-
* - "CustomerPayBillOnline" → Paybill (requires BillRefNumber / account number)
|
|
141
|
-
* - "CustomerBuyGoodsOnline" → Till/Buy Goods (BillRefNumber is null)
|
|
142
|
-
*/
|
|
143
|
-
type C2BCommandId = "CustomerPayBillOnline" | "CustomerBuyGoodsOnline";
|
|
144
123
|
interface C2BSimulateRequest {
|
|
145
|
-
/**
|
|
124
|
+
/** Paybill or Till short code */
|
|
146
125
|
shortCode: string;
|
|
147
|
-
/**
|
|
148
|
-
|
|
149
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Transaction type.
|
|
128
|
+
* "CustomerPayBillOnline" → payment to a Paybill number (default)
|
|
129
|
+
* "CustomerBuyGoodsOnline" → payment to a Till number
|
|
130
|
+
*/
|
|
131
|
+
commandId?: C2BCommandId;
|
|
132
|
+
/** Transaction amount (whole number, min 1 KES) */
|
|
150
133
|
amount: number;
|
|
151
|
-
/**
|
|
134
|
+
/** Customer's phone number — any valid Kenyan MSISDN */
|
|
152
135
|
phoneNumber: string;
|
|
153
136
|
/**
|
|
154
|
-
* Account
|
|
155
|
-
*
|
|
137
|
+
* Account reference for Paybill payments.
|
|
138
|
+
* Must be null / omitted for CustomerBuyGoodsOnline.
|
|
156
139
|
*/
|
|
157
|
-
billRefNumber?: string
|
|
158
|
-
}
|
|
159
|
-
interface C2BSimulateResponse {
|
|
160
|
-
/** @see C2BRegisterUrlResponse.OriginatorCoversationID (Daraja typo) */
|
|
161
|
-
OriginatorCoversationID: string;
|
|
162
|
-
ResponseCode: string;
|
|
163
|
-
ResponseDescription: string;
|
|
140
|
+
billRefNumber?: string;
|
|
164
141
|
}
|
|
165
142
|
/**
|
|
166
|
-
*
|
|
167
|
-
* C2B v2 returns a masked MSISDN: "2547 ***** 126"
|
|
168
|
-
*
|
|
169
|
-
* This type covers BOTH the confirmation and validation callbacks —
|
|
170
|
-
* they share the same shape. The difference is:
|
|
171
|
-
* - Validation: OrgAccountBalance is blank; you must respond Accept/Reject.
|
|
172
|
-
* - Confirmation: OrgAccountBalance has the post-payment balance.
|
|
143
|
+
* Shared fields present in both Validation and Confirmation callback payloads.
|
|
173
144
|
*/
|
|
174
|
-
interface
|
|
175
|
-
/** "Pay Bill" or "Buy Goods" */
|
|
145
|
+
interface C2BCallbackPayloadBase {
|
|
176
146
|
TransactionType: string;
|
|
177
|
-
/** Unique M-
|
|
147
|
+
/** Unique M-PESA transaction ID (e.g. "RKL51ZDR4F") */
|
|
178
148
|
TransID: string;
|
|
179
|
-
/**
|
|
149
|
+
/** 14-digit timestamp: YYYYMMDDHHmmss */
|
|
180
150
|
TransTime: string;
|
|
181
|
-
/**
|
|
151
|
+
/** Transaction amount as a string (e.g. "5.00") */
|
|
182
152
|
TransAmount: string;
|
|
183
|
-
/** Your Paybill or Till shortcode */
|
|
184
153
|
BusinessShortCode: string;
|
|
185
|
-
/**
|
|
186
|
-
* Account reference / bill number entered by customer.
|
|
187
|
-
* Applies to Paybill transactions. Empty string for Buy Goods.
|
|
188
|
-
*/
|
|
154
|
+
/** Account reference; empty for Till transactions */
|
|
189
155
|
BillRefNumber: string;
|
|
190
|
-
/** Invoice number if applicable (usually empty string) */
|
|
191
156
|
InvoiceNumber: string;
|
|
192
|
-
/**
|
|
193
|
-
* Post-payment balance of your Utility Account (confirmation only).
|
|
194
|
-
* Empty string in validation requests.
|
|
195
|
-
*/
|
|
196
157
|
OrgAccountBalance: string;
|
|
197
|
-
/**
|
|
198
|
-
* Opaque ID the partner can echo back in the validation response.
|
|
199
|
-
* Safaricom sends it back in the confirmation if you returned it.
|
|
200
|
-
*/
|
|
201
158
|
ThirdPartyTransID: string;
|
|
202
|
-
/**
|
|
203
|
-
* Masked phone number: "2547 ***** 126"
|
|
204
|
-
* C2B v2 masks for privacy. C2B v1 used SHA-256 hash.
|
|
205
|
-
*/
|
|
159
|
+
/** v2: masked MSISDN e.g. "2547 ***** 126" */
|
|
206
160
|
MSISDN: string;
|
|
207
|
-
/** Customer first name (may be empty) */
|
|
208
161
|
FirstName: string;
|
|
209
|
-
/** Customer middle name (may be empty) */
|
|
210
162
|
MiddleName: string;
|
|
211
|
-
/** Customer last name (may be empty) */
|
|
212
163
|
LastName: string;
|
|
213
164
|
}
|
|
165
|
+
/** Payload posted to your ValidationURL (if external validation is enabled) */
|
|
166
|
+
type C2BValidationPayload = C2BCallbackPayloadBase;
|
|
167
|
+
/** Payload posted to your ConfirmationURL after successful payment */
|
|
168
|
+
type C2BConfirmationPayload = C2BCallbackPayloadBase;
|
|
214
169
|
/**
|
|
215
|
-
*
|
|
216
|
-
*
|
|
170
|
+
* Union of both C2B callback types.
|
|
171
|
+
* Use the discriminated `TransactionType` field if you need to distinguish them,
|
|
172
|
+
* or register separate Express routes for each URL.
|
|
217
173
|
*/
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* "0" to accept the payment.
|
|
221
|
-
* Any of the C2B rejection codes to reject (e.g. "C2B00011").
|
|
222
|
-
*/
|
|
223
|
-
ResultCode: string;
|
|
224
|
-
/** "Accepted" or "Rejected" */
|
|
225
|
-
ResultDesc: string;
|
|
226
|
-
}
|
|
174
|
+
type C2BCallbackPayload = C2BValidationPayload | C2BConfirmationPayload;
|
|
227
175
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
176
|
+
* Codes your ValidationURL must return to Safaricom to accept or reject
|
|
177
|
+
* a payment before it is processed.
|
|
230
178
|
*/
|
|
231
179
|
declare const C2B_REJECTION_CODES: {
|
|
232
|
-
|
|
233
|
-
readonly
|
|
234
|
-
|
|
235
|
-
readonly
|
|
236
|
-
readonly INVALID_SHORT_CODE: "C2B00015";
|
|
237
|
-
readonly OTHER_ERROR: "C2B00016";
|
|
180
|
+
/** Accept the transaction — M-PESA proceeds to process and confirm */
|
|
181
|
+
readonly ACCEPT: "0";
|
|
182
|
+
/** Reject the transaction — M-PESA cancels and notifies the customer */
|
|
183
|
+
readonly REJECT: "1";
|
|
238
184
|
};
|
|
239
185
|
type C2BRejectionCode = (typeof C2B_REJECTION_CODES)[keyof typeof C2B_REJECTION_CODES];
|
|
240
186
|
|
|
187
|
+
/**
|
|
188
|
+
* Actual response shape from Daraja.
|
|
189
|
+
* Note: Daraja's field name has a typo ("CoversationID" — missing the 'n').
|
|
190
|
+
* We match it exactly so JSON parsing is lossless.
|
|
191
|
+
*/
|
|
192
|
+
interface C2BRegisterUrlResponse {
|
|
193
|
+
/** Global unique identifier for this registration request. Daraja typo: "Coversation" */
|
|
194
|
+
OriginatorCoversationID: string;
|
|
195
|
+
/** "0" = accepted */
|
|
196
|
+
ResponseCode: string;
|
|
197
|
+
ResponseDescription: string;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* C2B Simulate (sandbox only)
|
|
202
|
+
* API: POST /mpesa/c2b/v2/simulate
|
|
203
|
+
*
|
|
204
|
+
* Simulates a customer paying a Paybill or Till number.
|
|
205
|
+
* This endpoint is NOT available in production — use STK Push or Dynamic QR
|
|
206
|
+
* for production payment initiation.
|
|
207
|
+
*/
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Actual response shape from Daraja.
|
|
211
|
+
* Note: Daraja's field name has a typo ("CoversationID" — missing the 'n').
|
|
212
|
+
* We match it exactly so JSON parsing is lossless.
|
|
213
|
+
* There is NO ConversationID field in this response (unlike B2C/B2B).
|
|
214
|
+
*/
|
|
215
|
+
interface C2BSimulateResponse {
|
|
216
|
+
/** Global unique identifier for this simulate request. Daraja typo: "Coversation" */
|
|
217
|
+
OriginatorCoversationID: string;
|
|
218
|
+
/** "0" = accepted */
|
|
219
|
+
ResponseCode: string;
|
|
220
|
+
ResponseDescription: string;
|
|
221
|
+
}
|
|
222
|
+
|
|
241
223
|
/** B2B (Business to Business) types */
|
|
242
224
|
type B2BCommandId = "BusinessPayBill" | "BusinessBuyGoods" | "DisburseFundsToBusiness" | "BusinessToBusinessTransfer";
|
|
243
225
|
interface B2BRequest {
|
|
@@ -339,6 +321,92 @@ interface StkQueryResponse {
|
|
|
339
321
|
ResultCode: number;
|
|
340
322
|
ResultDesc: string;
|
|
341
323
|
}
|
|
324
|
+
/** A single metadata item in a successful STK callback */
|
|
325
|
+
interface StkCallbackMetadataItem {
|
|
326
|
+
Name: "Amount" | "MpesaReceiptNumber" | "TransactionDate" | "PhoneNumber";
|
|
327
|
+
/** Present on successful transactions; absent on failure */
|
|
328
|
+
Value?: number | string;
|
|
329
|
+
}
|
|
330
|
+
/** Inner callback object for a SUCCESSFUL STK Push */
|
|
331
|
+
interface StkCallbackSuccess {
|
|
332
|
+
MerchantRequestID: string;
|
|
333
|
+
CheckoutRequestID: string;
|
|
334
|
+
/** 0 = success */
|
|
335
|
+
ResultCode: 0;
|
|
336
|
+
ResultDesc: string;
|
|
337
|
+
CallbackMetadata: {
|
|
338
|
+
Item: StkCallbackMetadataItem[];
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/** Inner callback object for a FAILED/CANCELLED STK Push */
|
|
342
|
+
interface StkCallbackFailure {
|
|
343
|
+
MerchantRequestID: string;
|
|
344
|
+
CheckoutRequestID: string;
|
|
345
|
+
/** Non-zero result codes: e.g. 1032 = cancelled by user */
|
|
346
|
+
ResultCode: number;
|
|
347
|
+
ResultDesc: string;
|
|
348
|
+
CallbackMetadata?: never;
|
|
349
|
+
}
|
|
350
|
+
type StkCallbackInner = StkCallbackSuccess | StkCallbackFailure;
|
|
351
|
+
/** Full wrapper that Safaricom POSTs to your CallBackURL */
|
|
352
|
+
interface StkPushCallback {
|
|
353
|
+
Body: {
|
|
354
|
+
stkCallback: StkCallbackInner;
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Type guard — narrows an StkCallbackInner to the success shape.
|
|
359
|
+
* Usage:
|
|
360
|
+
* if (isStkCallbackSuccess(callback.Body.stkCallback)) {
|
|
361
|
+
* const receipt = getCallbackValue(callback, "MpesaReceiptNumber");
|
|
362
|
+
* }
|
|
363
|
+
*/
|
|
364
|
+
declare function isStkCallbackSuccess(cb: StkCallbackInner): cb is StkCallbackSuccess;
|
|
365
|
+
/**
|
|
366
|
+
* Extracts a named value from a successful callback's metadata items.
|
|
367
|
+
* Returns undefined if the key is absent or the callback failed.
|
|
368
|
+
*/
|
|
369
|
+
declare function getCallbackValue(callback: StkPushCallback, name: StkCallbackMetadataItem["Name"]): string | number | undefined;
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Shared phone number utilities for M-Pesa API calls.
|
|
373
|
+
*
|
|
374
|
+
* Two formatters are intentionally separate:
|
|
375
|
+
* - formatSafaricomPhone → strict, for STK Push (only Safaricom/Airtel)
|
|
376
|
+
* - formatKenyanMsisdn → permissive, for C2B simulate and B2C PartyB
|
|
377
|
+
*
|
|
378
|
+
* Daraja consistently expects 12-digit MSISDN without the '+' prefix.
|
|
379
|
+
*/
|
|
380
|
+
/**
|
|
381
|
+
* Strict formatter for STK Push.
|
|
382
|
+
* Accepts Safaricom (2547xx) and Airtel Kenya (2541x) numbers only.
|
|
383
|
+
* Throws a clear error on invalid input so Daraja never receives a bad MSISDN.
|
|
384
|
+
*/
|
|
385
|
+
declare function formatSafaricomPhone(phone: string): string;
|
|
386
|
+
/**
|
|
387
|
+
* Permissive formatter for C2B simulate and B2C PartyB.
|
|
388
|
+
* Accepts any valid 12-digit Kenyan MSISDN (Safaricom, Airtel, Telkom, …).
|
|
389
|
+
* Still throws if the result is structurally impossible.
|
|
390
|
+
*/
|
|
391
|
+
declare function formatKenyanMsisdn(phone: string): string;
|
|
392
|
+
/**
|
|
393
|
+
* Converts a formatted MSISDN string to the numeric form Daraja expects in
|
|
394
|
+
* C2B simulate requests ("Msisdn": 254708374149 — no quotes in the JSON).
|
|
395
|
+
*/
|
|
396
|
+
declare function msisdnToNumber(phone: string): number;
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* STK Push utilities
|
|
400
|
+
*
|
|
401
|
+
* Phone formatting delegates to the shared `formatSafaricomPhone` util which
|
|
402
|
+
* validates Safaricom/Airtel numbers and throws a clear error on bad input.
|
|
403
|
+
*/
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Generates a Daraja-compatible timestamp: YYYYMMDDHHmmss
|
|
407
|
+
* Call this once per request and reuse the value.
|
|
408
|
+
*/
|
|
409
|
+
declare function getTimestamp(): string;
|
|
342
410
|
|
|
343
411
|
type Environment = "sandbox" | "production";
|
|
344
412
|
declare const DARAJA_BASE_URLS: {
|
|
@@ -560,4 +628,4 @@ declare class PesafyError extends Error {
|
|
|
560
628
|
}
|
|
561
629
|
declare function createError(options: PesafyErrorOptions): PesafyError;
|
|
562
630
|
|
|
563
|
-
export { type B2BRequest, type B2BResponse, type B2CRequest, type B2CResponse, type B2CWebhook, type C2BCallbackPayload, type C2BCommandId, type
|
|
631
|
+
export { type B2BRequest, type B2BResponse, type B2CRequest, type B2CResponse, type B2CWebhook, type C2BCallbackPayload, type C2BCallbackPayloadBase, type C2BCommandId, type C2BConfirmationPayload, type C2BRegisterUrlRequest, type C2BRegisterUrlResponse, type C2BRejectionCode, type C2BSimulateRequest, type C2BSimulateResponse, type C2BValidationPayload, type C2BWebhook, C2B_REJECTION_CODES, DARAJA_BASE_URLS, type DynamicQRRequest, type DynamicQRResponse, type ErrorCode, Mpesa, type MpesaConfig, type MpesaExpressConfig, PesafyError, type RetryOptions, type RetryResult, type ReversalRequest, type ReversalResponse, type StkCallbackFailure, type StkCallbackInner, type StkCallbackMetadataItem, type StkCallbackSuccess, type StkPushCallback, type StkPushRequest, type StkPushResponse, type StkPushWebhook, type StkQueryRequest, type StkQueryResponse, TokenManager, type TransactionStatusRequest, type TransactionStatusResponse, type WebhookEvent, type WebhookEventType, type WebhookHandlerOptions, type WebhookHandlerResult, createError, createMpesaExpressClient, createMpesaExpressRouter, encryptSecurityCredential, extractAmount, extractTransactionId, formatKenyanMsisdn, formatSafaricomPhone as formatPhoneNumber, formatSafaricomPhone, getCallbackValue, getTimestamp, handleWebhook, isStkCallbackSuccess, msisdnToNumber, retryWithBackoff, verifyWebhookIP };
|