pesafy 0.2.1 → 0.2.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.
- package/dist/index.cjs +11 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +11 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -210,10 +210,9 @@ function formatPhoneNumber(phone) {
|
|
|
210
210
|
if (cleaned.startsWith("254")) return cleaned;
|
|
211
211
|
return "254" + cleaned;
|
|
212
212
|
}
|
|
213
|
-
function getStkPushPassword(shortCode, passKey) {
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
return Buffer.from(password, "utf-8").toString("base64");
|
|
213
|
+
function getStkPushPassword(shortCode, passKey, timestamp) {
|
|
214
|
+
const raw = `${shortCode}${passKey}${timestamp}`;
|
|
215
|
+
return Buffer.from(raw, "utf-8").toString("base64");
|
|
217
216
|
}
|
|
218
217
|
function getTimestamp() {
|
|
219
218
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -342,14 +341,16 @@ async function processReversal(baseUrl, accessToken, securityCredential, initiat
|
|
|
342
341
|
|
|
343
342
|
// src/mpesa/stk-push/stk-push.ts
|
|
344
343
|
async function processStkPush(baseUrl, accessToken, request) {
|
|
344
|
+
const timestamp = getTimestamp();
|
|
345
|
+
const partyB = request.partyB ?? request.shortCode;
|
|
345
346
|
const body = {
|
|
346
347
|
BusinessShortCode: request.shortCode,
|
|
347
|
-
Password: getStkPushPassword(request.shortCode, request.passKey),
|
|
348
|
-
Timestamp:
|
|
348
|
+
Password: getStkPushPassword(request.shortCode, request.passKey, timestamp),
|
|
349
|
+
Timestamp: timestamp,
|
|
349
350
|
TransactionType: request.transactionType ?? "CustomerPayBillOnline",
|
|
350
351
|
Amount: Math.round(request.amount),
|
|
351
352
|
PartyA: formatPhoneNumber(request.phoneNumber),
|
|
352
|
-
PartyB:
|
|
353
|
+
PartyB: partyB,
|
|
353
354
|
PhoneNumber: formatPhoneNumber(request.phoneNumber),
|
|
354
355
|
CallBackURL: request.callbackUrl,
|
|
355
356
|
AccountReference: request.accountReference.slice(0, 12),
|
|
@@ -368,10 +369,11 @@ async function processStkPush(baseUrl, accessToken, request) {
|
|
|
368
369
|
|
|
369
370
|
// src/mpesa/stk-push/stk-query.ts
|
|
370
371
|
async function queryStkPush(baseUrl, accessToken, request) {
|
|
372
|
+
const timestamp = getTimestamp();
|
|
371
373
|
const body = {
|
|
372
374
|
BusinessShortCode: request.shortCode,
|
|
373
|
-
Password: getStkPushPassword(request.shortCode, request.passKey),
|
|
374
|
-
Timestamp:
|
|
375
|
+
Password: getStkPushPassword(request.shortCode, request.passKey, timestamp),
|
|
376
|
+
Timestamp: timestamp,
|
|
375
377
|
CheckoutRequestID: request.checkoutRequestId
|
|
376
378
|
};
|
|
377
379
|
const { data } = await httpRequest(
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/errors/error-factory.ts","../src/utils/http/client.ts","../src/core/auth/token-manager.ts","../src/core/encryption/security-credentials.ts","../src/mpesa/b2b/b2b.ts","../src/mpesa/stk-push/utils.ts","../src/mpesa/b2c/b2c.ts","../src/mpesa/c2b/register-url.ts","../src/mpesa/c2b/simulate.ts","../src/mpesa/qr-code/dynamic-qr.ts","../src/mpesa/reversal/reversal.ts","../src/mpesa/stk-push/stk-push.ts","../src/mpesa/stk-push/stk-query.ts","../src/mpesa/transaction-status/query.ts","../src/mpesa/types.ts","../src/mpesa/index.ts","../src/express/index.ts","../src/mpesa/webhooks/retry.ts","../src/mpesa/webhooks/signature-verifier.ts","../src/mpesa/webhooks/webhook-handler.ts"],"names":["publicEncrypt"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Error creation utilities for Pesafy\n */\n\nimport type { ErrorCode, PesafyErrorOptions } from \"./types\";\n\nexport class PesafyError extends Error {\n readonly code: ErrorCode;\n readonly statusCode?: number;\n readonly response?: unknown;\n readonly requestId?: string;\n override readonly cause?: unknown;\n\n constructor(options: PesafyErrorOptions) {\n super(options.message);\n Object.defineProperty(this, \"name\", { value: \"PesafyError\" });\n this.code = options.code;\n this.statusCode = options.statusCode;\n this.response = options.response;\n this.requestId = options.requestId;\n this.cause = options.cause;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, PesafyError);\n }\n }\n\n toJSON() {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n statusCode: this.statusCode,\n requestId: this.requestId,\n };\n }\n}\n\nexport function createError(options: PesafyErrorOptions): PesafyError {\n return new PesafyError(options);\n}\n","/**\n * HTTP client for Daraja API requests\n */\n\nimport { PesafyError } from \"../errors\";\nimport type { HttpRequestOptions, HttpResponse } from \"./types\";\n\nconst DEFAULT_TIMEOUT = 30000;\n\nexport async function httpRequest<T = unknown>(\n url: string,\n options: HttpRequestOptions = {}\n): Promise<HttpResponse<T>> {\n const {\n method = \"GET\",\n headers = {},\n body,\n timeout = DEFAULT_TIMEOUT,\n } = options;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n let data: T;\n const text = await response.text();\n try {\n data = (text ? JSON.parse(text) : {}) as T;\n } catch {\n data = { raw: text } as T;\n }\n\n if (!response.ok) {\n throw new PesafyError({\n code: \"API_ERROR\",\n message: `Request failed with status ${response.status}`,\n statusCode: response.status,\n response: data,\n });\n }\n\n return {\n data,\n status: response.status,\n headers: response.headers,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof PesafyError) throw error;\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new PesafyError({\n code: \"TIMEOUT\",\n message: `Request timed out after ${timeout}ms`,\n cause: error,\n });\n }\n throw new PesafyError({\n code: \"NETWORK_ERROR\",\n message: error.message,\n cause: error,\n });\n }\n throw new PesafyError({\n code: \"REQUEST_FAILED\",\n message: \"An unknown error occurred\",\n cause: error,\n });\n }\n}\n","/**\n * OAuth token manager for Daraja API\n * Token validity: 3600 seconds (1 hour)\n */\n\nimport { PesafyError } from \"../../utils/errors\";\nimport { httpRequest } from \"../../utils/http\";\nimport type { TokenResponse } from \"./types\";\n\nconst TOKEN_BUFFER_SECONDS = 60; // Refresh token 60s before expiry\n\nexport class TokenManager {\n private consumerKey: string;\n private consumerSecret: string;\n private baseUrl: string;\n private cachedToken: string | null = null;\n private tokenExpiresAt = 0;\n\n constructor(consumerKey: string, consumerSecret: string, baseUrl: string) {\n this.consumerKey = consumerKey;\n this.consumerSecret = consumerSecret;\n this.baseUrl = baseUrl;\n }\n\n private getAuthHeader(): string {\n const credentials = `${this.consumerKey}:${this.consumerSecret}`;\n const encoded = Buffer.from(credentials, \"utf-8\").toString(\"base64\");\n return `Basic ${encoded}`;\n }\n\n async getAccessToken(): Promise<string> {\n const now = Date.now() / 1000;\n if (this.cachedToken && this.tokenExpiresAt > now + TOKEN_BUFFER_SECONDS) {\n return this.cachedToken;\n }\n\n const url = `${this.baseUrl}/oauth/v1/generate?grant_type=client_credentials`;\n const response = await httpRequest<TokenResponse>(url, {\n method: \"GET\",\n headers: {\n Authorization: this.getAuthHeader(),\n },\n });\n\n const data = response.data;\n if (!data.access_token) {\n throw new PesafyError({\n code: \"AUTH_FAILED\",\n message: \"Failed to obtain access token\",\n response: data,\n });\n }\n\n this.cachedToken = data.access_token;\n this.tokenExpiresAt = now + (data.expires_in ?? 3600);\n return this.cachedToken;\n }\n\n clearCache(): void {\n this.cachedToken = null;\n this.tokenExpiresAt = 0;\n }\n}\n","/**\n * Security credential encryption for B2C, B2B, Reversal APIs\n * Uses RSA with PKCS#1.5 padding per Daraja API spec\n * Download certificates from: https://developer.safaricom.co.ke/APIs\n */\n\nimport { publicEncrypt } from \"node:crypto\";\nimport { PesafyError } from \"../../utils/errors\";\n\n/** Encrypt initiator password with M-Pesa public certificate (PEM format) */\nexport function encryptSecurityCredential(\n initiatorPassword: string,\n certificatePem: string\n): string {\n try {\n const passwordBuffer = Buffer.from(initiatorPassword, \"utf-8\");\n const encrypted = publicEncrypt(\n {\n key: certificatePem,\n padding: 1, // RSA_PKCS1_PADDING\n },\n passwordBuffer\n );\n return encrypted.toString(\"base64\");\n } catch (error) {\n throw new PesafyError({\n code: \"ENCRYPTION_FAILED\",\n message: \"Failed to encrypt security credential\",\n cause: error,\n });\n }\n}\n","/**\n * B2B - Business to Business payments\n * API: POST /mpesa/b2b/v1/paymentrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { B2BRequest } from \"./types\";\n\nexport interface B2BResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processB2B(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: B2BRequest\n): Promise<B2BResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: request.commandId ?? \"BusinessPayBill\",\n SenderIdentifierType: request.senderIdentifierType ?? 4,\n RecieverIdentifierType: request.receiverIdentifierType ?? 4,\n Amount: Math.round(request.amount),\n PartyA: request.shortCode,\n PartyB: request.receiverShortCode,\n AccountReference: request.accountReference ?? \"\",\n Remarks: request.remarks ?? \"B2B Payment\",\n QueueTimeOutURL: request.timeoutUrl,\n ResultURL: request.resultUrl,\n };\n\n const { data } = await httpRequest<B2BResponse>(\n `${baseUrl}/mpesa/b2b/v1/paymentrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/** Generate STK Push password: Base64(Shortcode + Passkey + Timestamp) */\n\nexport function formatPhoneNumber(phone: string): string {\n const cleaned = phone.replace(/\\D/g, \"\");\n if (cleaned.startsWith(\"0\")) return \"254\" + cleaned.slice(1);\n if (cleaned.startsWith(\"254\")) return cleaned;\n return \"254\" + cleaned;\n}\n\nexport function getStkPushPassword(shortCode: string, passKey: string): string {\n const timestamp = getTimestamp();\n const password = `${shortCode}${passKey}${timestamp}`;\n return Buffer.from(password, \"utf-8\").toString(\"base64\");\n}\n\nexport function getTimestamp(): string {\n const now = new Date();\n const pad = (n: number) => n.toString().padStart(2, \"0\");\n return [\n now.getFullYear(),\n pad(now.getMonth() + 1),\n pad(now.getDate()),\n pad(now.getHours()),\n pad(now.getMinutes()),\n pad(now.getSeconds()),\n ].join(\"\");\n}\n","/**\n * B2C - Business to Customer payments\n * API: POST /mpesa/b2c/v3/paymentrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport { formatPhoneNumber } from \"../stk-push/utils\";\nimport type { B2CRequest } from \"./types\";\n\nexport interface B2CResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processB2C(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: B2CRequest\n): Promise<B2CResponse> {\n const body = {\n OriginatorConversationID: `AG_${Date.now()}_${Math.random().toString(36).slice(2)}`,\n InitiatorName: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: request.commandId ?? \"BusinessPayment\",\n Amount: Math.round(request.amount),\n PartyA: request.shortCode,\n PartyB: formatPhoneNumber(request.phoneNumber),\n Remarks: request.remarks ?? \"Payment\",\n QueueTimeOutURL: request.timeoutUrl,\n ResultURL: request.resultUrl,\n Occasion: request.occasion ?? \"\",\n };\n\n const { data } = await httpRequest<B2CResponse>(\n `${baseUrl}/mpesa/b2c/v3/paymentrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * C2B Register URLs - Register validation and confirmation URLs\n * API: POST /mpesa/c2b/v2/registerurl\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { C2BRegisterUrlRequest } from \"./types\";\n\nexport interface C2BRegisterUrlResponse {\n ConversationID: string;\n OriginatorCoversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function registerC2BUrls(\n baseUrl: string,\n accessToken: string,\n request: C2BRegisterUrlRequest\n): Promise<C2BRegisterUrlResponse> {\n const body = {\n ShortCode: request.shortCode,\n ResponseType: request.responseType ?? \"Completed\",\n ConfirmationURL: request.confirmationUrl,\n ValidationURL: request.validationUrl,\n };\n\n const { data } = await httpRequest<C2BRegisterUrlResponse>(\n `${baseUrl}/mpesa/c2b/v2/registerurl`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * C2B Simulate - Simulate C2B payment (sandbox only)\n * API: POST /mpesa/c2b/v2/simulate\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport { formatPhoneNumber } from \"../stk-push/utils\";\nimport type { C2BSimulateRequest } from \"./types\";\n\nexport interface C2BSimulateResponse {\n ConversationID: string;\n OriginatorCoversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function simulateC2B(\n baseUrl: string,\n accessToken: string,\n request: C2BSimulateRequest\n): Promise<C2BSimulateResponse> {\n const body = {\n ShortCode: request.shortCode,\n CommandID: \"CustomerPayBillOnline\",\n Amount: Math.round(request.amount),\n Msisdn: formatPhoneNumber(request.phoneNumber),\n BillRefNumber: request.billRefNumber ?? \"default\",\n };\n\n const { data } = await httpRequest<C2BSimulateResponse>(\n `${baseUrl}/mpesa/c2b/v2/simulate`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Dynamic QR Code - Generate LIPA NA M-PESA QR codes\n * API: POST /mpesa/qrcode/v1/generate\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { DynamicQRRequest } from \"./types\";\n\nexport interface DynamicQRResponse {\n ResponseCode: string;\n RequestID: string;\n ResponseDescription: string;\n QRCode: string;\n}\n\nexport async function generateDynamicQR(\n baseUrl: string,\n accessToken: string,\n request: DynamicQRRequest\n): Promise<DynamicQRResponse> {\n const body = {\n MerchantName: request.merchantName,\n RefNo: request.refNo,\n Amount: Math.round(request.amount),\n TrxCode: request.trxCode,\n CPI: request.cpi,\n Size: request.size ?? \"300\",\n };\n\n const { data } = await httpRequest<DynamicQRResponse>(\n `${baseUrl}/mpesa/qrcode/v1/generate`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Transaction Reversal\n * API: POST /mpesa/reversal/v1/request\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { ReversalRequest } from \"./types\";\n\nexport interface ReversalResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processReversal(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: ReversalRequest\n): Promise<ReversalResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: \"TransactionReversal\",\n TransactionID: request.transactionId,\n Amount: Math.round(request.amount),\n ReceiverParty: request.shortCode,\n RecieverIdentifierType: 4,\n ResultURL: request.resultUrl,\n QueueTimeOutURL: request.timeoutUrl,\n Remarks: request.remarks ?? \"Reversal\",\n Occasion: request.occasion ?? \"Reversal\",\n };\n\n const { data } = await httpRequest<ReversalResponse>(\n `${baseUrl}/mpesa/reversal/v1/request`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * M-Pesa Express (STK Push) - Initiates payment prompt on customer's phone\n * API: POST /mpesa/stkpush/v1/processrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { StkPushRequest, StkPushResponse } from \"./types\";\nimport { formatPhoneNumber, getStkPushPassword, getTimestamp } from \"./utils\";\n\nexport async function processStkPush(\n baseUrl: string,\n accessToken: string,\n request: StkPushRequest\n): Promise<StkPushResponse> {\n const body = {\n BusinessShortCode: request.shortCode,\n Password: getStkPushPassword(request.shortCode, request.passKey),\n Timestamp: getTimestamp(),\n TransactionType: request.transactionType ?? \"CustomerPayBillOnline\",\n Amount: Math.round(request.amount),\n PartyA: formatPhoneNumber(request.phoneNumber),\n PartyB: request.shortCode,\n PhoneNumber: formatPhoneNumber(request.phoneNumber),\n CallBackURL: request.callbackUrl,\n AccountReference: request.accountReference.slice(0, 12),\n TransactionDesc: request.transactionDesc.slice(0, 13),\n };\n\n const { data } = await httpRequest<StkPushResponse>(\n `${baseUrl}/mpesa/stkpush/v1/processrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * STK Push Query - Check status of STK Push transaction\n * API: POST /mpesa/stkpushquery/v1/query\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { StkQueryRequest, StkQueryResponse } from \"./types\";\nimport { getStkPushPassword, getTimestamp } from \"./utils\";\n\nexport async function queryStkPush(\n baseUrl: string,\n accessToken: string,\n request: StkQueryRequest\n): Promise<StkQueryResponse> {\n const body = {\n BusinessShortCode: request.shortCode,\n Password: getStkPushPassword(request.shortCode, request.passKey),\n Timestamp: getTimestamp(),\n CheckoutRequestID: request.checkoutRequestId,\n };\n\n const { data } = await httpRequest<StkQueryResponse>(\n `${baseUrl}/mpesa/stkpushquery/v1/query`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Transaction Status Query\n * API: POST /mpesa/transactionstatus/v1/query\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { TransactionStatusRequest } from \"./types\";\n\nexport interface TransactionStatusResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function queryTransactionStatus(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: TransactionStatusRequest\n): Promise<TransactionStatusResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: \"TransactionStatusQuery\",\n TransactionID: request.transactionId,\n PartyA: request.shortCode,\n IdentifierType: request.identifierType ?? 4,\n ResultURL: request.resultUrl,\n QueueTimeOutURL: request.timeoutUrl,\n Remarks: \"Status\",\n Occasion: \"Query\",\n };\n\n const { data } = await httpRequest<TransactionStatusResponse>(\n `${baseUrl}/mpesa/transactionstatus/v1/query`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","export type Environment = \"sandbox\" | \"production\";\n\nexport const DARAJA_BASE_URLS = {\n sandbox: \"https://sandbox.safaricom.co.ke\",\n production: \"https://api.safaricom.co.ke\",\n} as const;\n\nexport interface MpesaConfig {\n consumerKey: string;\n consumerSecret: string;\n environment: Environment;\n /** Required for STK Push - Lipa Na M-Pesa passkey from Daraja portal */\n lipaNaMpesaShortCode?: string;\n lipaNaMpesaPassKey?: string;\n /** Required for B2C, B2B, Reversal - initiator name and password */\n initiatorName?: string;\n initiatorPassword?: string;\n /** PEM certificate for encrypting initiator password. Download from Daraja portal */\n certificatePath?: string;\n /** PEM certificate string (alternative to certificatePath) */\n certificatePem?: string;\n /** Pre-encrypted security credential (alternative to initiatorPassword + certificate) */\n securityCredential?: string;\n}\n","/**\n * M-Pesa Daraja API client\n */\n\nimport { TokenManager } from \"../core/auth\";\nimport { encryptSecurityCredential } from \"../core/encryption\";\nimport { type B2BRequest, processB2B } from \"./b2b\";\nimport { type B2CRequest, processB2C } from \"./b2c\";\nimport {\n type C2BRegisterUrlRequest,\n type C2BSimulateRequest,\n registerC2BUrls,\n simulateC2B,\n} from \"./c2b\";\nimport { type DynamicQRRequest, generateDynamicQR } from \"./qr-code\";\nimport { processReversal, type ReversalRequest } from \"./reversal\";\nimport {\n processStkPush,\n queryStkPush,\n type StkPushRequest,\n type StkQueryRequest,\n} from \"./stk-push\";\nimport {\n queryTransactionStatus,\n type TransactionStatusRequest,\n} from \"./transaction-status\";\nimport { DARAJA_BASE_URLS, type MpesaConfig } from \"./types\";\n\nexport class Mpesa {\n private config: MpesaConfig;\n private tokenManager: TokenManager;\n private baseUrl: string;\n\n constructor(config: MpesaConfig) {\n this.config = config;\n this.baseUrl = DARAJA_BASE_URLS[config.environment];\n this.tokenManager = new TokenManager(\n config.consumerKey,\n config.consumerSecret,\n this.baseUrl\n );\n }\n\n private async getToken(): Promise<string> {\n return this.tokenManager.getAccessToken();\n }\n\n private async getSecurityCredential(): Promise<string> {\n if (this.config.securityCredential) return this.config.securityCredential;\n if (!this.config.initiatorPassword) {\n throw new Error(\n \"Security credential required: provide securityCredential or (initiatorPassword + certificatePath/certificatePem)\"\n );\n }\n let cert: string;\n if (this.config.certificatePem) {\n cert = this.config.certificatePem;\n } else if (this.config.certificatePath) {\n cert = await Bun.file(this.config.certificatePath).text();\n } else {\n throw new Error(\n \"certificatePath or certificatePem required for B2C/B2B/Reversal\"\n );\n }\n return encryptSecurityCredential(this.config.initiatorPassword, cert);\n }\n\n /** STK Push (M-Pesa Express) - Initiate payment on customer phone */\n async stkPush(request: Omit<StkPushRequest, \"shortCode\" | \"passKey\">) {\n const shortCode = this.config.lipaNaMpesaShortCode ?? \"\";\n const passKey = this.config.lipaNaMpesaPassKey ?? \"\";\n if (!shortCode || !passKey) {\n throw new Error(\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey required for STK Push\"\n );\n }\n const token = await this.getToken();\n return processStkPush(this.baseUrl, token, {\n ...request,\n shortCode,\n passKey,\n });\n }\n\n /** STK Query - Check STK Push transaction status */\n async stkQuery(request: Omit<StkQueryRequest, \"shortCode\" | \"passKey\">) {\n const shortCode = this.config.lipaNaMpesaShortCode ?? \"\";\n const passKey = this.config.lipaNaMpesaPassKey ?? \"\";\n if (!shortCode || !passKey) {\n throw new Error(\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey required for STK Query\"\n );\n }\n const token = await this.getToken();\n return queryStkPush(this.baseUrl, token, {\n ...request,\n shortCode,\n passKey,\n });\n }\n\n /** B2C - Send money to customer */\n async b2c(request: B2CRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for B2C\");\n const token = await this.getToken();\n return processB2C(this.baseUrl, token, securityCred, initiator, request);\n }\n\n /** B2B - Send money to business */\n async b2b(request: B2BRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for B2B\");\n const token = await this.getToken();\n return processB2B(this.baseUrl, token, securityCred, initiator, request);\n }\n\n /** C2B - Register validation/confirmation URLs */\n async c2bRegisterUrls(request: C2BRegisterUrlRequest) {\n const token = await this.getToken();\n return registerC2BUrls(this.baseUrl, token, request);\n }\n\n /** C2B - Simulate payment (sandbox only) */\n async c2bSimulate(request: C2BSimulateRequest) {\n const token = await this.getToken();\n return simulateC2B(this.baseUrl, token, request);\n }\n\n /** Dynamic QR - Generate LIPA NA M-PESA QR code */\n async qrCode(request: DynamicQRRequest) {\n const token = await this.getToken();\n return generateDynamicQR(this.baseUrl, token, request);\n }\n\n /** Transaction Status - Query transaction status */\n async transactionStatus(request: TransactionStatusRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator)\n throw new Error(\"initiatorName required for Transaction Status\");\n const token = await this.getToken();\n return queryTransactionStatus(\n this.baseUrl,\n token,\n securityCred,\n initiator,\n request\n );\n }\n\n /** Reversal - Reverse a transaction */\n async reversal(request: ReversalRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for Reversal\");\n const token = await this.getToken();\n return processReversal(\n this.baseUrl,\n token,\n securityCred,\n initiator,\n request\n );\n }\n}\n","/**\n * Express-friendly helpers for M-Pesa Express (STK Push) and C2B simulate.\n *\n * NOTE: This module does NOT depend on Express at runtime. You pass in an\n * existing Express Router instance, and we attach handlers to it.\n */\n\nimport type { NextFunction, Request, Response, Router } from \"express\";\n\nimport { Mpesa } from \"../mpesa\";\nimport type { MpesaConfig } from \"../mpesa/types\";\nimport { PesafyError } from \"../utils/errors\";\n\nexport interface MpesaExpressConfig extends MpesaConfig {\n /**\n * Full callback URL that Safaricom will call after STK Push completes.\n * Example (sandbox):\n * https://your-domain.ngrok.io/api/mpesa/express/callback\n */\n callbackUrl: string;\n}\n\nexport function createMpesaExpressClient(config: MpesaExpressConfig): {\n mpesa: Mpesa;\n} {\n if (!config.consumerKey || !config.consumerSecret) {\n throw new PesafyError({\n code: \"INVALID_CREDENTIALS\",\n message: \"consumerKey and consumerSecret are required\",\n });\n }\n\n if (!config.lipaNaMpesaShortCode || !config.lipaNaMpesaPassKey) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message:\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey are required for STK Push\",\n });\n }\n\n if (!config.callbackUrl) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"callbackUrl is required for STK Push callbacks\",\n });\n }\n\n const mpesa = new Mpesa(config);\n return { mpesa };\n}\n\ninterface StkPushBody {\n amount: number;\n phoneNumber: string;\n accountReference?: string;\n transactionDesc?: string;\n}\n\ninterface StkQueryBody {\n checkoutRequestId: string;\n}\n\nfunction normalizePhone(phone: string): string {\n const digits = phone.replace(/\\D/g, \"\");\n if (digits.startsWith(\"254\")) return digits;\n if (digits.startsWith(\"0\")) return `254${digits.slice(1)}`;\n return digits;\n}\n\nfunction sendError(res: Response, error: unknown): void {\n if (error instanceof PesafyError) {\n const status = error.statusCode ?? 400;\n res.status(status).json({\n error: error.code,\n message: error.message,\n statusCode: status,\n });\n return;\n }\n\n res.status(500).json({\n error: \"REQUEST_FAILED\",\n message: \"Unexpected error while processing M-Pesa request\",\n });\n}\n\nexport function createMpesaExpressRouter(\n router: Router,\n config: MpesaExpressConfig\n): Router {\n const { mpesa } = createMpesaExpressClient(config);\n\n // STK Push – initiate payment on customer phone\n router.post(\n \"/mpesa/express/stk-push\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const body = req.body as StkPushBody;\n\n if (!body || typeof body.amount !== \"number\" || body.amount <= 0) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"amount must be a positive number\",\n });\n }\n\n if (!body.phoneNumber) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"phoneNumber is required\",\n });\n }\n\n const phoneNumber = normalizePhone(body.phoneNumber);\n\n const result = await mpesa.stkPush({\n amount: body.amount,\n phoneNumber,\n callbackUrl: config.callbackUrl,\n accountReference:\n body.accountReference ??\n `PESAFY-${Date.now().toString(36).toUpperCase()}`,\n transactionDesc: body.transactionDesc ?? \"Payment\",\n });\n\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // STK Query – check status of an STK Push\n router.post(\n \"/mpesa/express/stk-query\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const body = req.body as StkQueryBody;\n\n if (!body || !body.checkoutRequestId) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"checkoutRequestId is required\",\n });\n }\n\n const result = await mpesa.stkQuery({\n checkoutRequestId: body.checkoutRequestId,\n });\n\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // C2B simulate – sandbox only\n router.post(\n \"/mpesa/c2b/simulate\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const result = await mpesa.c2bSimulate(req.body);\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // C2B register URLs – sandbox only\n router.post(\n \"/mpesa/c2b/register-url\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const result = await mpesa.c2bRegisterUrls(req.body);\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n return router;\n}\n","/**\n * Webhook retry mechanism with exponential backoff\n * For at-least-once delivery guarantee\n */\n\nexport interface RetryOptions {\n maxRetries?: number;\n initialDelay?: number;\n maxDelay?: number;\n backoffMultiplier?: number;\n maxRetryDuration?: number; // milliseconds (30 days default)\n}\n\nconst DEFAULT_OPTIONS: Required<RetryOptions> = {\n maxRetries: Infinity,\n initialDelay: 1000, // 1 second\n maxDelay: 3600000, // 1 hour\n backoffMultiplier: 2,\n maxRetryDuration: 30 * 24 * 60 * 60 * 1000, // 30 days\n};\n\nexport interface RetryResult<T> {\n success: boolean;\n data?: T;\n attempts: number;\n error?: Error;\n}\n\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<RetryResult<T>> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n let delay = opts.initialDelay;\n let attempts = 0;\n const startTime = Date.now();\n\n while (attempts < opts.maxRetries) {\n attempts++;\n\n // Check if we've exceeded max retry duration\n if (Date.now() - startTime > opts.maxRetryDuration) {\n return {\n success: false,\n attempts,\n error: new Error(\"Max retry duration exceeded\"),\n };\n }\n\n try {\n const data = await fn();\n return { success: true, data, attempts };\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n\n // Don't retry on 4xx errors (client errors)\n if (err.message.includes(\"4\")) {\n return { success: false, attempts, error: err };\n }\n\n // Wait before retrying\n if (attempts < opts.maxRetries) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n delay = Math.min(delay * opts.backoffMultiplier, opts.maxDelay);\n }\n }\n }\n\n return {\n success: false,\n attempts,\n error: new Error(\"Max retries exceeded\"),\n };\n}\n","/**\n * Webhook signature verification\n * Note: Daraja API doesn't provide webhook signatures in the same way as Stripe\n * Instead, verify by whitelisting IPs: 196.201.214.200, 196.201.214.206, etc.\n * This utility helps parse and validate webhook payloads\n */\n\nimport type { B2CWebhook, C2BWebhook, StkPushWebhook } from \"./types\";\n\nexport interface WebhookVerificationOptions {\n /** IP whitelist - verify request comes from Safaricom */\n allowedIPs?: string[];\n /** Optional: verify request headers match expected pattern */\n verifyHeaders?: boolean;\n}\n\nconst SAFARICOM_IPS = [\n \"196.201.214.200\",\n \"196.201.214.206\",\n \"196.201.213.114\",\n \"196.201.214.207\",\n \"196.201.214.208\",\n \"196.201.213.44\",\n \"196.201.212.127\",\n \"196.201.212.138\",\n \"196.201.212.129\",\n \"196.201.212.136\",\n \"196.201.212.74\",\n \"196.201.212.69\",\n];\n\nexport function verifyWebhookIP(\n requestIP: string,\n allowedIPs: string[] = SAFARICOM_IPS\n): boolean {\n return allowedIPs.includes(requestIP);\n}\n\nexport function parseStkPushWebhook(body: unknown): StkPushWebhook | null {\n try {\n const parsed = body as StkPushWebhook;\n if (parsed.Body?.stkCallback) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n\nexport function parseB2CWebhook(body: unknown): B2CWebhook | null {\n try {\n const parsed = body as B2CWebhook;\n if (parsed.Result?.ResultCode !== undefined) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n\nexport function parseC2BWebhook(body: unknown): C2BWebhook | null {\n try {\n const parsed = body as C2BWebhook;\n if (parsed.TransID && parsed.TransAmount) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * Webhook event handler utilities\n */\n\nimport {\n parseB2CWebhook,\n parseC2BWebhook,\n parseStkPushWebhook,\n verifyWebhookIP,\n} from \"./signature-verifier\";\nimport type {\n B2CWebhook,\n C2BWebhook,\n StkPushWebhook,\n WebhookEventType,\n} from \"./types\";\n\nexport interface WebhookHandlerOptions {\n /** IP address of incoming request */\n requestIP?: string;\n /** Custom IP whitelist */\n allowedIPs?: string[];\n /** Skip IP verification (for testing) */\n skipIPCheck?: boolean;\n}\n\nexport interface WebhookHandlerResult<T = unknown> {\n success: boolean;\n eventType: WebhookEventType | null;\n data: T | null;\n error?: string;\n}\n\nexport function handleWebhook(\n body: unknown,\n options: WebhookHandlerOptions = {}\n): WebhookHandlerResult {\n // Verify IP if provided\n if (!options.skipIPCheck && options.requestIP) {\n if (!verifyWebhookIP(options.requestIP, options.allowedIPs)) {\n return {\n success: false,\n eventType: null,\n data: null,\n error: \"IP address not whitelisted\",\n };\n }\n }\n\n // Try to parse as STK Push\n const stkPush = parseStkPushWebhook(body);\n if (stkPush) {\n return {\n success: true,\n eventType: \"stk_push\",\n data: stkPush,\n };\n }\n\n // Try to parse as B2C\n const b2c = parseB2CWebhook(body);\n if (b2c) {\n return {\n success: true,\n eventType: \"b2c\",\n data: b2c,\n };\n }\n\n // Try to parse as C2B\n const c2b = parseC2BWebhook(body);\n if (c2b) {\n return {\n success: true,\n eventType: \"c2b\",\n data: c2b,\n };\n }\n\n return {\n success: false,\n eventType: null,\n data: null,\n error: \"Unknown webhook format\",\n };\n}\n\nexport function extractTransactionId(\n webhook: StkPushWebhook | B2CWebhook | C2BWebhook\n): string | null {\n if (\"Body\" in webhook && webhook.Body?.stkCallback) {\n const items = webhook.Body.stkCallback.CallbackMetadata?.Item;\n const mpesaReceipt = items?.find(\n (item) => item.Name === \"MpesaReceiptNumber\"\n );\n return mpesaReceipt ? String(mpesaReceipt.Value) : null;\n }\n if (\"Result\" in webhook && webhook.Result?.TransactionID) {\n return webhook.Result.TransactionID;\n }\n if (\"TransID\" in webhook) {\n return webhook.TransID;\n }\n return null;\n}\n\nexport function extractAmount(\n webhook: StkPushWebhook | B2CWebhook | C2BWebhook\n): number | null {\n if (\"Body\" in webhook && webhook.Body?.stkCallback) {\n const items = webhook.Body.stkCallback.CallbackMetadata?.Item;\n const amount = items?.find((item) => item.Name === \"Amount\");\n return amount ? Number(amount.Value) : null;\n }\n if (\"Result\" in webhook && webhook.Result?.ResultParameters) {\n const params = webhook.Result.ResultParameters.ResultParameter;\n const amount = params?.find((p) => p.Key === \"Amount\");\n return amount ? Number(amount.Value) : null;\n }\n if (\"TransAmount\" in webhook) {\n return Number.parseFloat(webhook.TransAmount);\n }\n return null;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/errors/error-factory.ts","../src/utils/http/client.ts","../src/core/auth/token-manager.ts","../src/core/encryption/security-credentials.ts","../src/mpesa/b2b/b2b.ts","../src/mpesa/stk-push/utils.ts","../src/mpesa/b2c/b2c.ts","../src/mpesa/c2b/register-url.ts","../src/mpesa/c2b/simulate.ts","../src/mpesa/qr-code/dynamic-qr.ts","../src/mpesa/reversal/reversal.ts","../src/mpesa/stk-push/stk-push.ts","../src/mpesa/stk-push/stk-query.ts","../src/mpesa/transaction-status/query.ts","../src/mpesa/types.ts","../src/mpesa/index.ts","../src/express/index.ts","../src/mpesa/webhooks/retry.ts","../src/mpesa/webhooks/signature-verifier.ts","../src/mpesa/webhooks/webhook-handler.ts"],"names":["publicEncrypt"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Error creation utilities for Pesafy\n */\n\nimport type { ErrorCode, PesafyErrorOptions } from \"./types\";\n\nexport class PesafyError extends Error {\n readonly code: ErrorCode;\n readonly statusCode?: number;\n readonly response?: unknown;\n readonly requestId?: string;\n override readonly cause?: unknown;\n\n constructor(options: PesafyErrorOptions) {\n super(options.message);\n Object.defineProperty(this, \"name\", { value: \"PesafyError\" });\n this.code = options.code;\n this.statusCode = options.statusCode;\n this.response = options.response;\n this.requestId = options.requestId;\n this.cause = options.cause;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, PesafyError);\n }\n }\n\n toJSON() {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n statusCode: this.statusCode,\n requestId: this.requestId,\n };\n }\n}\n\nexport function createError(options: PesafyErrorOptions): PesafyError {\n return new PesafyError(options);\n}\n","/**\n * HTTP client for Daraja API requests\n */\n\nimport { PesafyError } from \"../errors\";\nimport type { HttpRequestOptions, HttpResponse } from \"./types\";\n\nconst DEFAULT_TIMEOUT = 30000;\n\nexport async function httpRequest<T = unknown>(\n url: string,\n options: HttpRequestOptions = {}\n): Promise<HttpResponse<T>> {\n const {\n method = \"GET\",\n headers = {},\n body,\n timeout = DEFAULT_TIMEOUT,\n } = options;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n let data: T;\n const text = await response.text();\n try {\n data = (text ? JSON.parse(text) : {}) as T;\n } catch {\n data = { raw: text } as T;\n }\n\n if (!response.ok) {\n throw new PesafyError({\n code: \"API_ERROR\",\n message: `Request failed with status ${response.status}`,\n statusCode: response.status,\n response: data,\n });\n }\n\n return {\n data,\n status: response.status,\n headers: response.headers,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof PesafyError) throw error;\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new PesafyError({\n code: \"TIMEOUT\",\n message: `Request timed out after ${timeout}ms`,\n cause: error,\n });\n }\n throw new PesafyError({\n code: \"NETWORK_ERROR\",\n message: error.message,\n cause: error,\n });\n }\n throw new PesafyError({\n code: \"REQUEST_FAILED\",\n message: \"An unknown error occurred\",\n cause: error,\n });\n }\n}\n","/**\n * OAuth token manager for Daraja API\n * Token validity: 3600 seconds (1 hour)\n */\n\nimport { PesafyError } from \"../../utils/errors\";\nimport { httpRequest } from \"../../utils/http\";\nimport type { TokenResponse } from \"./types\";\n\nconst TOKEN_BUFFER_SECONDS = 60; // Refresh token 60s before expiry\n\nexport class TokenManager {\n private consumerKey: string;\n private consumerSecret: string;\n private baseUrl: string;\n private cachedToken: string | null = null;\n private tokenExpiresAt = 0;\n\n constructor(consumerKey: string, consumerSecret: string, baseUrl: string) {\n this.consumerKey = consumerKey;\n this.consumerSecret = consumerSecret;\n this.baseUrl = baseUrl;\n }\n\n private getAuthHeader(): string {\n const credentials = `${this.consumerKey}:${this.consumerSecret}`;\n const encoded = Buffer.from(credentials, \"utf-8\").toString(\"base64\");\n return `Basic ${encoded}`;\n }\n\n async getAccessToken(): Promise<string> {\n const now = Date.now() / 1000;\n if (this.cachedToken && this.tokenExpiresAt > now + TOKEN_BUFFER_SECONDS) {\n return this.cachedToken;\n }\n\n const url = `${this.baseUrl}/oauth/v1/generate?grant_type=client_credentials`;\n const response = await httpRequest<TokenResponse>(url, {\n method: \"GET\",\n headers: {\n Authorization: this.getAuthHeader(),\n },\n });\n\n const data = response.data;\n if (!data.access_token) {\n throw new PesafyError({\n code: \"AUTH_FAILED\",\n message: \"Failed to obtain access token\",\n response: data,\n });\n }\n\n this.cachedToken = data.access_token;\n this.tokenExpiresAt = now + (data.expires_in ?? 3600);\n return this.cachedToken;\n }\n\n clearCache(): void {\n this.cachedToken = null;\n this.tokenExpiresAt = 0;\n }\n}\n","/**\n * Security credential encryption for B2C, B2B, Reversal APIs\n * Uses RSA with PKCS#1.5 padding per Daraja API spec\n * Download certificates from: https://developer.safaricom.co.ke/APIs\n */\n\nimport { publicEncrypt } from \"node:crypto\";\nimport { PesafyError } from \"../../utils/errors\";\n\n/** Encrypt initiator password with M-Pesa public certificate (PEM format) */\nexport function encryptSecurityCredential(\n initiatorPassword: string,\n certificatePem: string\n): string {\n try {\n const passwordBuffer = Buffer.from(initiatorPassword, \"utf-8\");\n const encrypted = publicEncrypt(\n {\n key: certificatePem,\n padding: 1, // RSA_PKCS1_PADDING\n },\n passwordBuffer\n );\n return encrypted.toString(\"base64\");\n } catch (error) {\n throw new PesafyError({\n code: \"ENCRYPTION_FAILED\",\n message: \"Failed to encrypt security credential\",\n cause: error,\n });\n }\n}\n","/**\n * B2B - Business to Business payments\n * API: POST /mpesa/b2b/v1/paymentrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { B2BRequest } from \"./types\";\n\nexport interface B2BResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processB2B(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: B2BRequest\n): Promise<B2BResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: request.commandId ?? \"BusinessPayBill\",\n SenderIdentifierType: request.senderIdentifierType ?? 4,\n RecieverIdentifierType: request.receiverIdentifierType ?? 4,\n Amount: Math.round(request.amount),\n PartyA: request.shortCode,\n PartyB: request.receiverShortCode,\n AccountReference: request.accountReference ?? \"\",\n Remarks: request.remarks ?? \"B2B Payment\",\n QueueTimeOutURL: request.timeoutUrl,\n ResultURL: request.resultUrl,\n };\n\n const { data } = await httpRequest<B2BResponse>(\n `${baseUrl}/mpesa/b2b/v1/paymentrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/** STK Push utilities */\n\n/**\n * Formats a phone number to the required 2547XXXXXXXX format.\n * Handles 07XXXXXXXX, 2547XXXXXXXX, and +2547XXXXXXXX inputs.\n */\nexport function formatPhoneNumber(phone: string): string {\n const cleaned = phone.replace(/\\D/g, \"\");\n if (cleaned.startsWith(\"0\")) return \"254\" + cleaned.slice(1);\n if (cleaned.startsWith(\"254\")) return cleaned;\n return \"254\" + cleaned;\n}\n\n/**\n * Generates the STK Push password.\n * Formula: Base64(Shortcode + Passkey + Timestamp)\n *\n * IMPORTANT: The timestamp passed here MUST be the exact same value sent in\n * the request body's `Timestamp` field. Safaricom validates they match.\n * Always call getTimestamp() once and pass the result to both this function\n * and the request body — never call getTimestamp() twice.\n */\nexport function getStkPushPassword(\n shortCode: string,\n passKey: string,\n timestamp: string\n): string {\n const raw = `${shortCode}${passKey}${timestamp}`;\n return Buffer.from(raw, \"utf-8\").toString(\"base64\");\n}\n\n/**\n * Generates a Daraja-compatible timestamp: YYYYMMDDHHmmss\n * Call this once per request and reuse the value.\n */\nexport function getTimestamp(): string {\n const now = new Date();\n const pad = (n: number) => n.toString().padStart(2, \"0\");\n return [\n now.getFullYear(),\n pad(now.getMonth() + 1),\n pad(now.getDate()),\n pad(now.getHours()),\n pad(now.getMinutes()),\n pad(now.getSeconds()),\n ].join(\"\");\n}\n","/**\n * B2C - Business to Customer payments\n * API: POST /mpesa/b2c/v3/paymentrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport { formatPhoneNumber } from \"../stk-push/utils\";\nimport type { B2CRequest } from \"./types\";\n\nexport interface B2CResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processB2C(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: B2CRequest\n): Promise<B2CResponse> {\n const body = {\n OriginatorConversationID: `AG_${Date.now()}_${Math.random().toString(36).slice(2)}`,\n InitiatorName: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: request.commandId ?? \"BusinessPayment\",\n Amount: Math.round(request.amount),\n PartyA: request.shortCode,\n PartyB: formatPhoneNumber(request.phoneNumber),\n Remarks: request.remarks ?? \"Payment\",\n QueueTimeOutURL: request.timeoutUrl,\n ResultURL: request.resultUrl,\n Occasion: request.occasion ?? \"\",\n };\n\n const { data } = await httpRequest<B2CResponse>(\n `${baseUrl}/mpesa/b2c/v3/paymentrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * C2B Register URLs - Register validation and confirmation URLs\n * API: POST /mpesa/c2b/v2/registerurl\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { C2BRegisterUrlRequest } from \"./types\";\n\nexport interface C2BRegisterUrlResponse {\n ConversationID: string;\n OriginatorCoversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function registerC2BUrls(\n baseUrl: string,\n accessToken: string,\n request: C2BRegisterUrlRequest\n): Promise<C2BRegisterUrlResponse> {\n const body = {\n ShortCode: request.shortCode,\n ResponseType: request.responseType ?? \"Completed\",\n ConfirmationURL: request.confirmationUrl,\n ValidationURL: request.validationUrl,\n };\n\n const { data } = await httpRequest<C2BRegisterUrlResponse>(\n `${baseUrl}/mpesa/c2b/v2/registerurl`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * C2B Simulate - Simulate C2B payment (sandbox only)\n * API: POST /mpesa/c2b/v2/simulate\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport { formatPhoneNumber } from \"../stk-push/utils\";\nimport type { C2BSimulateRequest } from \"./types\";\n\nexport interface C2BSimulateResponse {\n ConversationID: string;\n OriginatorCoversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function simulateC2B(\n baseUrl: string,\n accessToken: string,\n request: C2BSimulateRequest\n): Promise<C2BSimulateResponse> {\n const body = {\n ShortCode: request.shortCode,\n CommandID: \"CustomerPayBillOnline\",\n Amount: Math.round(request.amount),\n Msisdn: formatPhoneNumber(request.phoneNumber),\n BillRefNumber: request.billRefNumber ?? \"default\",\n };\n\n const { data } = await httpRequest<C2BSimulateResponse>(\n `${baseUrl}/mpesa/c2b/v2/simulate`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Dynamic QR Code - Generate LIPA NA M-PESA QR codes\n * API: POST /mpesa/qrcode/v1/generate\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { DynamicQRRequest } from \"./types\";\n\nexport interface DynamicQRResponse {\n ResponseCode: string;\n RequestID: string;\n ResponseDescription: string;\n QRCode: string;\n}\n\nexport async function generateDynamicQR(\n baseUrl: string,\n accessToken: string,\n request: DynamicQRRequest\n): Promise<DynamicQRResponse> {\n const body = {\n MerchantName: request.merchantName,\n RefNo: request.refNo,\n Amount: Math.round(request.amount),\n TrxCode: request.trxCode,\n CPI: request.cpi,\n Size: request.size ?? \"300\",\n };\n\n const { data } = await httpRequest<DynamicQRResponse>(\n `${baseUrl}/mpesa/qrcode/v1/generate`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Transaction Reversal\n * API: POST /mpesa/reversal/v1/request\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { ReversalRequest } from \"./types\";\n\nexport interface ReversalResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processReversal(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: ReversalRequest\n): Promise<ReversalResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: \"TransactionReversal\",\n TransactionID: request.transactionId,\n Amount: Math.round(request.amount),\n ReceiverParty: request.shortCode,\n RecieverIdentifierType: 4,\n ResultURL: request.resultUrl,\n QueueTimeOutURL: request.timeoutUrl,\n Remarks: request.remarks ?? \"Reversal\",\n Occasion: request.occasion ?? \"Reversal\",\n };\n\n const { data } = await httpRequest<ReversalResponse>(\n `${baseUrl}/mpesa/reversal/v1/request`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * M-Pesa Express (STK Push) - Initiates payment prompt on customer's phone\n * API: POST /mpesa/stkpush/v1/processrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { StkPushRequest, StkPushResponse } from \"./types\";\nimport { formatPhoneNumber, getStkPushPassword, getTimestamp } from \"./utils\";\n\nexport async function processStkPush(\n baseUrl: string,\n accessToken: string,\n request: StkPushRequest\n): Promise<StkPushResponse> {\n // Generate timestamp ONCE — must be identical in both Password and Timestamp fields.\n // Safaricom validates that Base64(Shortcode+Passkey+Timestamp) matches the\n // Timestamp field; generating two separate timestamps causes auth failures.\n const timestamp = getTimestamp();\n\n // For CustomerBuyGoodsOnline (Till Number), PartyB is the till number.\n // For CustomerPayBillOnline (Paybill), PartyB is the shortcode.\n // Docs: https://developer.safaricom.co.ke/APIs/MpesaExpressSimulate\n const partyB = request.partyB ?? request.shortCode;\n\n const body = {\n BusinessShortCode: request.shortCode,\n Password: getStkPushPassword(request.shortCode, request.passKey, timestamp),\n Timestamp: timestamp,\n TransactionType: request.transactionType ?? \"CustomerPayBillOnline\",\n Amount: Math.round(request.amount),\n PartyA: formatPhoneNumber(request.phoneNumber),\n PartyB: partyB,\n PhoneNumber: formatPhoneNumber(request.phoneNumber),\n CallBackURL: request.callbackUrl,\n AccountReference: request.accountReference.slice(0, 12),\n TransactionDesc: request.transactionDesc.slice(0, 13),\n };\n\n const { data } = await httpRequest<StkPushResponse>(\n `${baseUrl}/mpesa/stkpush/v1/processrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * STK Push Query - Check status of STK Push transaction\n * API: POST /mpesa/stkpushquery/v1/query\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { StkQueryRequest, StkQueryResponse } from \"./types\";\nimport { getStkPushPassword, getTimestamp } from \"./utils\";\n\nexport async function queryStkPush(\n baseUrl: string,\n accessToken: string,\n request: StkQueryRequest\n): Promise<StkQueryResponse> {\n // Generate timestamp ONCE — Password and Timestamp field must match exactly.\n const timestamp = getTimestamp();\n\n const body = {\n BusinessShortCode: request.shortCode,\n Password: getStkPushPassword(request.shortCode, request.passKey, timestamp),\n Timestamp: timestamp,\n CheckoutRequestID: request.checkoutRequestId,\n };\n\n const { data } = await httpRequest<StkQueryResponse>(\n `${baseUrl}/mpesa/stkpushquery/v1/query`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Transaction Status Query\n * API: POST /mpesa/transactionstatus/v1/query\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { TransactionStatusRequest } from \"./types\";\n\nexport interface TransactionStatusResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function queryTransactionStatus(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: TransactionStatusRequest\n): Promise<TransactionStatusResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: \"TransactionStatusQuery\",\n TransactionID: request.transactionId,\n PartyA: request.shortCode,\n IdentifierType: request.identifierType ?? 4,\n ResultURL: request.resultUrl,\n QueueTimeOutURL: request.timeoutUrl,\n Remarks: \"Status\",\n Occasion: \"Query\",\n };\n\n const { data } = await httpRequest<TransactionStatusResponse>(\n `${baseUrl}/mpesa/transactionstatus/v1/query`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","export type Environment = \"sandbox\" | \"production\";\n\nexport const DARAJA_BASE_URLS = {\n sandbox: \"https://sandbox.safaricom.co.ke\",\n production: \"https://api.safaricom.co.ke\",\n} as const;\n\nexport interface MpesaConfig {\n consumerKey: string;\n consumerSecret: string;\n environment: Environment;\n /** Required for STK Push - Lipa Na M-Pesa passkey from Daraja portal */\n lipaNaMpesaShortCode?: string;\n lipaNaMpesaPassKey?: string;\n /** Required for B2C, B2B, Reversal - initiator name and password */\n initiatorName?: string;\n initiatorPassword?: string;\n /** PEM certificate for encrypting initiator password. Download from Daraja portal */\n certificatePath?: string;\n /** PEM certificate string (alternative to certificatePath) */\n certificatePem?: string;\n /** Pre-encrypted security credential (alternative to initiatorPassword + certificate) */\n securityCredential?: string;\n}\n","/**\n * M-Pesa Daraja API client\n */\n\nimport { TokenManager } from \"../core/auth\";\nimport { encryptSecurityCredential } from \"../core/encryption\";\nimport { type B2BRequest, processB2B } from \"./b2b\";\nimport { type B2CRequest, processB2C } from \"./b2c\";\nimport {\n type C2BRegisterUrlRequest,\n type C2BSimulateRequest,\n registerC2BUrls,\n simulateC2B,\n} from \"./c2b\";\nimport { type DynamicQRRequest, generateDynamicQR } from \"./qr-code\";\nimport { processReversal, type ReversalRequest } from \"./reversal\";\nimport {\n processStkPush,\n queryStkPush,\n type StkPushRequest,\n type StkQueryRequest,\n} from \"./stk-push\";\nimport {\n queryTransactionStatus,\n type TransactionStatusRequest,\n} from \"./transaction-status\";\nimport { DARAJA_BASE_URLS, type MpesaConfig } from \"./types\";\n\nexport class Mpesa {\n private config: MpesaConfig;\n private tokenManager: TokenManager;\n private baseUrl: string;\n\n constructor(config: MpesaConfig) {\n this.config = config;\n this.baseUrl = DARAJA_BASE_URLS[config.environment];\n this.tokenManager = new TokenManager(\n config.consumerKey,\n config.consumerSecret,\n this.baseUrl\n );\n }\n\n private async getToken(): Promise<string> {\n return this.tokenManager.getAccessToken();\n }\n\n private async getSecurityCredential(): Promise<string> {\n if (this.config.securityCredential) return this.config.securityCredential;\n if (!this.config.initiatorPassword) {\n throw new Error(\n \"Security credential required: provide securityCredential or (initiatorPassword + certificatePath/certificatePem)\"\n );\n }\n let cert: string;\n if (this.config.certificatePem) {\n cert = this.config.certificatePem;\n } else if (this.config.certificatePath) {\n cert = await Bun.file(this.config.certificatePath).text();\n } else {\n throw new Error(\n \"certificatePath or certificatePem required for B2C/B2B/Reversal\"\n );\n }\n return encryptSecurityCredential(this.config.initiatorPassword, cert);\n }\n\n /** STK Push (M-Pesa Express) - Initiate payment on customer phone */\n async stkPush(request: Omit<StkPushRequest, \"shortCode\" | \"passKey\">) {\n const shortCode = this.config.lipaNaMpesaShortCode ?? \"\";\n const passKey = this.config.lipaNaMpesaPassKey ?? \"\";\n if (!shortCode || !passKey) {\n throw new Error(\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey required for STK Push\"\n );\n }\n const token = await this.getToken();\n return processStkPush(this.baseUrl, token, {\n ...request,\n shortCode,\n passKey,\n });\n }\n\n /** STK Query - Check STK Push transaction status */\n async stkQuery(request: Omit<StkQueryRequest, \"shortCode\" | \"passKey\">) {\n const shortCode = this.config.lipaNaMpesaShortCode ?? \"\";\n const passKey = this.config.lipaNaMpesaPassKey ?? \"\";\n if (!shortCode || !passKey) {\n throw new Error(\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey required for STK Query\"\n );\n }\n const token = await this.getToken();\n return queryStkPush(this.baseUrl, token, {\n ...request,\n shortCode,\n passKey,\n });\n }\n\n /** B2C - Send money to customer */\n async b2c(request: B2CRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for B2C\");\n const token = await this.getToken();\n return processB2C(this.baseUrl, token, securityCred, initiator, request);\n }\n\n /** B2B - Send money to business */\n async b2b(request: B2BRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for B2B\");\n const token = await this.getToken();\n return processB2B(this.baseUrl, token, securityCred, initiator, request);\n }\n\n /** C2B - Register validation/confirmation URLs */\n async c2bRegisterUrls(request: C2BRegisterUrlRequest) {\n const token = await this.getToken();\n return registerC2BUrls(this.baseUrl, token, request);\n }\n\n /** C2B - Simulate payment (sandbox only) */\n async c2bSimulate(request: C2BSimulateRequest) {\n const token = await this.getToken();\n return simulateC2B(this.baseUrl, token, request);\n }\n\n /** Dynamic QR - Generate LIPA NA M-PESA QR code */\n async qrCode(request: DynamicQRRequest) {\n const token = await this.getToken();\n return generateDynamicQR(this.baseUrl, token, request);\n }\n\n /** Transaction Status - Query transaction status */\n async transactionStatus(request: TransactionStatusRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator)\n throw new Error(\"initiatorName required for Transaction Status\");\n const token = await this.getToken();\n return queryTransactionStatus(\n this.baseUrl,\n token,\n securityCred,\n initiator,\n request\n );\n }\n\n /** Reversal - Reverse a transaction */\n async reversal(request: ReversalRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for Reversal\");\n const token = await this.getToken();\n return processReversal(\n this.baseUrl,\n token,\n securityCred,\n initiator,\n request\n );\n }\n}\n","/**\n * Express-friendly helpers for M-Pesa Express (STK Push) and C2B simulate.\n *\n * NOTE: This module does NOT depend on Express at runtime. You pass in an\n * existing Express Router instance, and we attach handlers to it.\n */\n\nimport type { NextFunction, Request, Response, Router } from \"express\";\n\nimport { Mpesa } from \"../mpesa\";\nimport type { MpesaConfig } from \"../mpesa/types\";\nimport { PesafyError } from \"../utils/errors\";\n\nexport interface MpesaExpressConfig extends MpesaConfig {\n /**\n * Full callback URL that Safaricom will call after STK Push completes.\n * Example (sandbox):\n * https://your-domain.ngrok.io/api/mpesa/express/callback\n */\n callbackUrl: string;\n}\n\nexport function createMpesaExpressClient(config: MpesaExpressConfig): {\n mpesa: Mpesa;\n} {\n if (!config.consumerKey || !config.consumerSecret) {\n throw new PesafyError({\n code: \"INVALID_CREDENTIALS\",\n message: \"consumerKey and consumerSecret are required\",\n });\n }\n\n if (!config.lipaNaMpesaShortCode || !config.lipaNaMpesaPassKey) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message:\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey are required for STK Push\",\n });\n }\n\n if (!config.callbackUrl) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"callbackUrl is required for STK Push callbacks\",\n });\n }\n\n const mpesa = new Mpesa(config);\n return { mpesa };\n}\n\ninterface StkPushBody {\n amount: number;\n phoneNumber: string;\n accountReference?: string;\n transactionDesc?: string;\n}\n\ninterface StkQueryBody {\n checkoutRequestId: string;\n}\n\nfunction normalizePhone(phone: string): string {\n const digits = phone.replace(/\\D/g, \"\");\n if (digits.startsWith(\"254\")) return digits;\n if (digits.startsWith(\"0\")) return `254${digits.slice(1)}`;\n return digits;\n}\n\nfunction sendError(res: Response, error: unknown): void {\n if (error instanceof PesafyError) {\n const status = error.statusCode ?? 400;\n res.status(status).json({\n error: error.code,\n message: error.message,\n statusCode: status,\n });\n return;\n }\n\n res.status(500).json({\n error: \"REQUEST_FAILED\",\n message: \"Unexpected error while processing M-Pesa request\",\n });\n}\n\nexport function createMpesaExpressRouter(\n router: Router,\n config: MpesaExpressConfig\n): Router {\n const { mpesa } = createMpesaExpressClient(config);\n\n // STK Push – initiate payment on customer phone\n router.post(\n \"/mpesa/express/stk-push\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const body = req.body as StkPushBody;\n\n if (!body || typeof body.amount !== \"number\" || body.amount <= 0) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"amount must be a positive number\",\n });\n }\n\n if (!body.phoneNumber) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"phoneNumber is required\",\n });\n }\n\n const phoneNumber = normalizePhone(body.phoneNumber);\n\n const result = await mpesa.stkPush({\n amount: body.amount,\n phoneNumber,\n callbackUrl: config.callbackUrl,\n accountReference:\n body.accountReference ??\n `PESAFY-${Date.now().toString(36).toUpperCase()}`,\n transactionDesc: body.transactionDesc ?? \"Payment\",\n });\n\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // STK Query – check status of an STK Push\n router.post(\n \"/mpesa/express/stk-query\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const body = req.body as StkQueryBody;\n\n if (!body || !body.checkoutRequestId) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"checkoutRequestId is required\",\n });\n }\n\n const result = await mpesa.stkQuery({\n checkoutRequestId: body.checkoutRequestId,\n });\n\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // C2B simulate – sandbox only\n router.post(\n \"/mpesa/c2b/simulate\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const result = await mpesa.c2bSimulate(req.body);\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // C2B register URLs – sandbox only\n router.post(\n \"/mpesa/c2b/register-url\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const result = await mpesa.c2bRegisterUrls(req.body);\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n return router;\n}\n","/**\n * Webhook retry mechanism with exponential backoff\n * For at-least-once delivery guarantee\n */\n\nexport interface RetryOptions {\n maxRetries?: number;\n initialDelay?: number;\n maxDelay?: number;\n backoffMultiplier?: number;\n maxRetryDuration?: number; // milliseconds (30 days default)\n}\n\nconst DEFAULT_OPTIONS: Required<RetryOptions> = {\n maxRetries: Infinity,\n initialDelay: 1000, // 1 second\n maxDelay: 3600000, // 1 hour\n backoffMultiplier: 2,\n maxRetryDuration: 30 * 24 * 60 * 60 * 1000, // 30 days\n};\n\nexport interface RetryResult<T> {\n success: boolean;\n data?: T;\n attempts: number;\n error?: Error;\n}\n\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<RetryResult<T>> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n let delay = opts.initialDelay;\n let attempts = 0;\n const startTime = Date.now();\n\n while (attempts < opts.maxRetries) {\n attempts++;\n\n // Check if we've exceeded max retry duration\n if (Date.now() - startTime > opts.maxRetryDuration) {\n return {\n success: false,\n attempts,\n error: new Error(\"Max retry duration exceeded\"),\n };\n }\n\n try {\n const data = await fn();\n return { success: true, data, attempts };\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n\n // Don't retry on 4xx errors (client errors)\n if (err.message.includes(\"4\")) {\n return { success: false, attempts, error: err };\n }\n\n // Wait before retrying\n if (attempts < opts.maxRetries) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n delay = Math.min(delay * opts.backoffMultiplier, opts.maxDelay);\n }\n }\n }\n\n return {\n success: false,\n attempts,\n error: new Error(\"Max retries exceeded\"),\n };\n}\n","/**\n * Webhook signature verification\n * Note: Daraja API doesn't provide webhook signatures in the same way as Stripe\n * Instead, verify by whitelisting IPs: 196.201.214.200, 196.201.214.206, etc.\n * This utility helps parse and validate webhook payloads\n */\n\nimport type { B2CWebhook, C2BWebhook, StkPushWebhook } from \"./types\";\n\nexport interface WebhookVerificationOptions {\n /** IP whitelist - verify request comes from Safaricom */\n allowedIPs?: string[];\n /** Optional: verify request headers match expected pattern */\n verifyHeaders?: boolean;\n}\n\nconst SAFARICOM_IPS = [\n \"196.201.214.200\",\n \"196.201.214.206\",\n \"196.201.213.114\",\n \"196.201.214.207\",\n \"196.201.214.208\",\n \"196.201.213.44\",\n \"196.201.212.127\",\n \"196.201.212.138\",\n \"196.201.212.129\",\n \"196.201.212.136\",\n \"196.201.212.74\",\n \"196.201.212.69\",\n];\n\nexport function verifyWebhookIP(\n requestIP: string,\n allowedIPs: string[] = SAFARICOM_IPS\n): boolean {\n return allowedIPs.includes(requestIP);\n}\n\nexport function parseStkPushWebhook(body: unknown): StkPushWebhook | null {\n try {\n const parsed = body as StkPushWebhook;\n if (parsed.Body?.stkCallback) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n\nexport function parseB2CWebhook(body: unknown): B2CWebhook | null {\n try {\n const parsed = body as B2CWebhook;\n if (parsed.Result?.ResultCode !== undefined) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n\nexport function parseC2BWebhook(body: unknown): C2BWebhook | null {\n try {\n const parsed = body as C2BWebhook;\n if (parsed.TransID && parsed.TransAmount) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * Webhook event handler utilities\n */\n\nimport {\n parseB2CWebhook,\n parseC2BWebhook,\n parseStkPushWebhook,\n verifyWebhookIP,\n} from \"./signature-verifier\";\nimport type {\n B2CWebhook,\n C2BWebhook,\n StkPushWebhook,\n WebhookEventType,\n} from \"./types\";\n\nexport interface WebhookHandlerOptions {\n /** IP address of incoming request */\n requestIP?: string;\n /** Custom IP whitelist */\n allowedIPs?: string[];\n /** Skip IP verification (for testing) */\n skipIPCheck?: boolean;\n}\n\nexport interface WebhookHandlerResult<T = unknown> {\n success: boolean;\n eventType: WebhookEventType | null;\n data: T | null;\n error?: string;\n}\n\nexport function handleWebhook(\n body: unknown,\n options: WebhookHandlerOptions = {}\n): WebhookHandlerResult {\n // Verify IP if provided\n if (!options.skipIPCheck && options.requestIP) {\n if (!verifyWebhookIP(options.requestIP, options.allowedIPs)) {\n return {\n success: false,\n eventType: null,\n data: null,\n error: \"IP address not whitelisted\",\n };\n }\n }\n\n // Try to parse as STK Push\n const stkPush = parseStkPushWebhook(body);\n if (stkPush) {\n return {\n success: true,\n eventType: \"stk_push\",\n data: stkPush,\n };\n }\n\n // Try to parse as B2C\n const b2c = parseB2CWebhook(body);\n if (b2c) {\n return {\n success: true,\n eventType: \"b2c\",\n data: b2c,\n };\n }\n\n // Try to parse as C2B\n const c2b = parseC2BWebhook(body);\n if (c2b) {\n return {\n success: true,\n eventType: \"c2b\",\n data: c2b,\n };\n }\n\n return {\n success: false,\n eventType: null,\n data: null,\n error: \"Unknown webhook format\",\n };\n}\n\nexport function extractTransactionId(\n webhook: StkPushWebhook | B2CWebhook | C2BWebhook\n): string | null {\n if (\"Body\" in webhook && webhook.Body?.stkCallback) {\n const items = webhook.Body.stkCallback.CallbackMetadata?.Item;\n const mpesaReceipt = items?.find(\n (item) => item.Name === \"MpesaReceiptNumber\"\n );\n return mpesaReceipt ? String(mpesaReceipt.Value) : null;\n }\n if (\"Result\" in webhook && webhook.Result?.TransactionID) {\n return webhook.Result.TransactionID;\n }\n if (\"TransID\" in webhook) {\n return webhook.TransID;\n }\n return null;\n}\n\nexport function extractAmount(\n webhook: StkPushWebhook | B2CWebhook | C2BWebhook\n): number | null {\n if (\"Body\" in webhook && webhook.Body?.stkCallback) {\n const items = webhook.Body.stkCallback.CallbackMetadata?.Item;\n const amount = items?.find((item) => item.Name === \"Amount\");\n return amount ? Number(amount.Value) : null;\n }\n if (\"Result\" in webhook && webhook.Result?.ResultParameters) {\n const params = webhook.Result.ResultParameters.ResultParameter;\n const amount = params?.find((p) => p.Key === \"Amount\");\n return amount ? Number(amount.Value) : null;\n }\n if (\"TransAmount\" in webhook) {\n return Number.parseFloat(webhook.TransAmount);\n }\n return null;\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -189,10 +189,17 @@ interface StkPushRequest {
|
|
|
189
189
|
callbackUrl: string;
|
|
190
190
|
accountReference: string;
|
|
191
191
|
transactionDesc: string;
|
|
192
|
-
/** Business shortcode - Paybill or
|
|
192
|
+
/** Business shortcode - Paybill or HO/store number for Till */
|
|
193
193
|
shortCode: string;
|
|
194
194
|
passKey: string;
|
|
195
195
|
transactionType?: TransactionType;
|
|
196
|
+
/**
|
|
197
|
+
* The credit party receiving funds.
|
|
198
|
+
* - CustomerPayBillOnline: omit (defaults to shortCode)
|
|
199
|
+
* - CustomerBuyGoodsOnline: provide the Till Number
|
|
200
|
+
* Docs: PartyB must be the Till Number when using Buy Goods.
|
|
201
|
+
*/
|
|
202
|
+
partyB?: string;
|
|
196
203
|
}
|
|
197
204
|
interface StkPushResponse {
|
|
198
205
|
MerchantRequestID: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -189,10 +189,17 @@ interface StkPushRequest {
|
|
|
189
189
|
callbackUrl: string;
|
|
190
190
|
accountReference: string;
|
|
191
191
|
transactionDesc: string;
|
|
192
|
-
/** Business shortcode - Paybill or
|
|
192
|
+
/** Business shortcode - Paybill or HO/store number for Till */
|
|
193
193
|
shortCode: string;
|
|
194
194
|
passKey: string;
|
|
195
195
|
transactionType?: TransactionType;
|
|
196
|
+
/**
|
|
197
|
+
* The credit party receiving funds.
|
|
198
|
+
* - CustomerPayBillOnline: omit (defaults to shortCode)
|
|
199
|
+
* - CustomerBuyGoodsOnline: provide the Till Number
|
|
200
|
+
* Docs: PartyB must be the Till Number when using Buy Goods.
|
|
201
|
+
*/
|
|
202
|
+
partyB?: string;
|
|
196
203
|
}
|
|
197
204
|
interface StkPushResponse {
|
|
198
205
|
MerchantRequestID: string;
|
package/dist/index.js
CHANGED
|
@@ -208,10 +208,9 @@ function formatPhoneNumber(phone) {
|
|
|
208
208
|
if (cleaned.startsWith("254")) return cleaned;
|
|
209
209
|
return "254" + cleaned;
|
|
210
210
|
}
|
|
211
|
-
function getStkPushPassword(shortCode, passKey) {
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
return Buffer.from(password, "utf-8").toString("base64");
|
|
211
|
+
function getStkPushPassword(shortCode, passKey, timestamp) {
|
|
212
|
+
const raw = `${shortCode}${passKey}${timestamp}`;
|
|
213
|
+
return Buffer.from(raw, "utf-8").toString("base64");
|
|
215
214
|
}
|
|
216
215
|
function getTimestamp() {
|
|
217
216
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -340,14 +339,16 @@ async function processReversal(baseUrl, accessToken, securityCredential, initiat
|
|
|
340
339
|
|
|
341
340
|
// src/mpesa/stk-push/stk-push.ts
|
|
342
341
|
async function processStkPush(baseUrl, accessToken, request) {
|
|
342
|
+
const timestamp = getTimestamp();
|
|
343
|
+
const partyB = request.partyB ?? request.shortCode;
|
|
343
344
|
const body = {
|
|
344
345
|
BusinessShortCode: request.shortCode,
|
|
345
|
-
Password: getStkPushPassword(request.shortCode, request.passKey),
|
|
346
|
-
Timestamp:
|
|
346
|
+
Password: getStkPushPassword(request.shortCode, request.passKey, timestamp),
|
|
347
|
+
Timestamp: timestamp,
|
|
347
348
|
TransactionType: request.transactionType ?? "CustomerPayBillOnline",
|
|
348
349
|
Amount: Math.round(request.amount),
|
|
349
350
|
PartyA: formatPhoneNumber(request.phoneNumber),
|
|
350
|
-
PartyB:
|
|
351
|
+
PartyB: partyB,
|
|
351
352
|
PhoneNumber: formatPhoneNumber(request.phoneNumber),
|
|
352
353
|
CallBackURL: request.callbackUrl,
|
|
353
354
|
AccountReference: request.accountReference.slice(0, 12),
|
|
@@ -366,10 +367,11 @@ async function processStkPush(baseUrl, accessToken, request) {
|
|
|
366
367
|
|
|
367
368
|
// src/mpesa/stk-push/stk-query.ts
|
|
368
369
|
async function queryStkPush(baseUrl, accessToken, request) {
|
|
370
|
+
const timestamp = getTimestamp();
|
|
369
371
|
const body = {
|
|
370
372
|
BusinessShortCode: request.shortCode,
|
|
371
|
-
Password: getStkPushPassword(request.shortCode, request.passKey),
|
|
372
|
-
Timestamp:
|
|
373
|
+
Password: getStkPushPassword(request.shortCode, request.passKey, timestamp),
|
|
374
|
+
Timestamp: timestamp,
|
|
373
375
|
CheckoutRequestID: request.checkoutRequestId
|
|
374
376
|
};
|
|
375
377
|
const { data } = await httpRequest(
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/errors/error-factory.ts","../src/utils/http/client.ts","../src/core/auth/token-manager.ts","../src/core/encryption/security-credentials.ts","../src/mpesa/b2b/b2b.ts","../src/mpesa/stk-push/utils.ts","../src/mpesa/b2c/b2c.ts","../src/mpesa/c2b/register-url.ts","../src/mpesa/c2b/simulate.ts","../src/mpesa/qr-code/dynamic-qr.ts","../src/mpesa/reversal/reversal.ts","../src/mpesa/stk-push/stk-push.ts","../src/mpesa/stk-push/stk-query.ts","../src/mpesa/transaction-status/query.ts","../src/mpesa/types.ts","../src/mpesa/index.ts","../src/express/index.ts","../src/mpesa/webhooks/retry.ts","../src/mpesa/webhooks/signature-verifier.ts","../src/mpesa/webhooks/webhook-handler.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Error creation utilities for Pesafy\n */\n\nimport type { ErrorCode, PesafyErrorOptions } from \"./types\";\n\nexport class PesafyError extends Error {\n readonly code: ErrorCode;\n readonly statusCode?: number;\n readonly response?: unknown;\n readonly requestId?: string;\n override readonly cause?: unknown;\n\n constructor(options: PesafyErrorOptions) {\n super(options.message);\n Object.defineProperty(this, \"name\", { value: \"PesafyError\" });\n this.code = options.code;\n this.statusCode = options.statusCode;\n this.response = options.response;\n this.requestId = options.requestId;\n this.cause = options.cause;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, PesafyError);\n }\n }\n\n toJSON() {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n statusCode: this.statusCode,\n requestId: this.requestId,\n };\n }\n}\n\nexport function createError(options: PesafyErrorOptions): PesafyError {\n return new PesafyError(options);\n}\n","/**\n * HTTP client for Daraja API requests\n */\n\nimport { PesafyError } from \"../errors\";\nimport type { HttpRequestOptions, HttpResponse } from \"./types\";\n\nconst DEFAULT_TIMEOUT = 30000;\n\nexport async function httpRequest<T = unknown>(\n url: string,\n options: HttpRequestOptions = {}\n): Promise<HttpResponse<T>> {\n const {\n method = \"GET\",\n headers = {},\n body,\n timeout = DEFAULT_TIMEOUT,\n } = options;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n let data: T;\n const text = await response.text();\n try {\n data = (text ? JSON.parse(text) : {}) as T;\n } catch {\n data = { raw: text } as T;\n }\n\n if (!response.ok) {\n throw new PesafyError({\n code: \"API_ERROR\",\n message: `Request failed with status ${response.status}`,\n statusCode: response.status,\n response: data,\n });\n }\n\n return {\n data,\n status: response.status,\n headers: response.headers,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof PesafyError) throw error;\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new PesafyError({\n code: \"TIMEOUT\",\n message: `Request timed out after ${timeout}ms`,\n cause: error,\n });\n }\n throw new PesafyError({\n code: \"NETWORK_ERROR\",\n message: error.message,\n cause: error,\n });\n }\n throw new PesafyError({\n code: \"REQUEST_FAILED\",\n message: \"An unknown error occurred\",\n cause: error,\n });\n }\n}\n","/**\n * OAuth token manager for Daraja API\n * Token validity: 3600 seconds (1 hour)\n */\n\nimport { PesafyError } from \"../../utils/errors\";\nimport { httpRequest } from \"../../utils/http\";\nimport type { TokenResponse } from \"./types\";\n\nconst TOKEN_BUFFER_SECONDS = 60; // Refresh token 60s before expiry\n\nexport class TokenManager {\n private consumerKey: string;\n private consumerSecret: string;\n private baseUrl: string;\n private cachedToken: string | null = null;\n private tokenExpiresAt = 0;\n\n constructor(consumerKey: string, consumerSecret: string, baseUrl: string) {\n this.consumerKey = consumerKey;\n this.consumerSecret = consumerSecret;\n this.baseUrl = baseUrl;\n }\n\n private getAuthHeader(): string {\n const credentials = `${this.consumerKey}:${this.consumerSecret}`;\n const encoded = Buffer.from(credentials, \"utf-8\").toString(\"base64\");\n return `Basic ${encoded}`;\n }\n\n async getAccessToken(): Promise<string> {\n const now = Date.now() / 1000;\n if (this.cachedToken && this.tokenExpiresAt > now + TOKEN_BUFFER_SECONDS) {\n return this.cachedToken;\n }\n\n const url = `${this.baseUrl}/oauth/v1/generate?grant_type=client_credentials`;\n const response = await httpRequest<TokenResponse>(url, {\n method: \"GET\",\n headers: {\n Authorization: this.getAuthHeader(),\n },\n });\n\n const data = response.data;\n if (!data.access_token) {\n throw new PesafyError({\n code: \"AUTH_FAILED\",\n message: \"Failed to obtain access token\",\n response: data,\n });\n }\n\n this.cachedToken = data.access_token;\n this.tokenExpiresAt = now + (data.expires_in ?? 3600);\n return this.cachedToken;\n }\n\n clearCache(): void {\n this.cachedToken = null;\n this.tokenExpiresAt = 0;\n }\n}\n","/**\n * Security credential encryption for B2C, B2B, Reversal APIs\n * Uses RSA with PKCS#1.5 padding per Daraja API spec\n * Download certificates from: https://developer.safaricom.co.ke/APIs\n */\n\nimport { publicEncrypt } from \"node:crypto\";\nimport { PesafyError } from \"../../utils/errors\";\n\n/** Encrypt initiator password with M-Pesa public certificate (PEM format) */\nexport function encryptSecurityCredential(\n initiatorPassword: string,\n certificatePem: string\n): string {\n try {\n const passwordBuffer = Buffer.from(initiatorPassword, \"utf-8\");\n const encrypted = publicEncrypt(\n {\n key: certificatePem,\n padding: 1, // RSA_PKCS1_PADDING\n },\n passwordBuffer\n );\n return encrypted.toString(\"base64\");\n } catch (error) {\n throw new PesafyError({\n code: \"ENCRYPTION_FAILED\",\n message: \"Failed to encrypt security credential\",\n cause: error,\n });\n }\n}\n","/**\n * B2B - Business to Business payments\n * API: POST /mpesa/b2b/v1/paymentrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { B2BRequest } from \"./types\";\n\nexport interface B2BResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processB2B(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: B2BRequest\n): Promise<B2BResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: request.commandId ?? \"BusinessPayBill\",\n SenderIdentifierType: request.senderIdentifierType ?? 4,\n RecieverIdentifierType: request.receiverIdentifierType ?? 4,\n Amount: Math.round(request.amount),\n PartyA: request.shortCode,\n PartyB: request.receiverShortCode,\n AccountReference: request.accountReference ?? \"\",\n Remarks: request.remarks ?? \"B2B Payment\",\n QueueTimeOutURL: request.timeoutUrl,\n ResultURL: request.resultUrl,\n };\n\n const { data } = await httpRequest<B2BResponse>(\n `${baseUrl}/mpesa/b2b/v1/paymentrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/** Generate STK Push password: Base64(Shortcode + Passkey + Timestamp) */\n\nexport function formatPhoneNumber(phone: string): string {\n const cleaned = phone.replace(/\\D/g, \"\");\n if (cleaned.startsWith(\"0\")) return \"254\" + cleaned.slice(1);\n if (cleaned.startsWith(\"254\")) return cleaned;\n return \"254\" + cleaned;\n}\n\nexport function getStkPushPassword(shortCode: string, passKey: string): string {\n const timestamp = getTimestamp();\n const password = `${shortCode}${passKey}${timestamp}`;\n return Buffer.from(password, \"utf-8\").toString(\"base64\");\n}\n\nexport function getTimestamp(): string {\n const now = new Date();\n const pad = (n: number) => n.toString().padStart(2, \"0\");\n return [\n now.getFullYear(),\n pad(now.getMonth() + 1),\n pad(now.getDate()),\n pad(now.getHours()),\n pad(now.getMinutes()),\n pad(now.getSeconds()),\n ].join(\"\");\n}\n","/**\n * B2C - Business to Customer payments\n * API: POST /mpesa/b2c/v3/paymentrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport { formatPhoneNumber } from \"../stk-push/utils\";\nimport type { B2CRequest } from \"./types\";\n\nexport interface B2CResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processB2C(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: B2CRequest\n): Promise<B2CResponse> {\n const body = {\n OriginatorConversationID: `AG_${Date.now()}_${Math.random().toString(36).slice(2)}`,\n InitiatorName: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: request.commandId ?? \"BusinessPayment\",\n Amount: Math.round(request.amount),\n PartyA: request.shortCode,\n PartyB: formatPhoneNumber(request.phoneNumber),\n Remarks: request.remarks ?? \"Payment\",\n QueueTimeOutURL: request.timeoutUrl,\n ResultURL: request.resultUrl,\n Occasion: request.occasion ?? \"\",\n };\n\n const { data } = await httpRequest<B2CResponse>(\n `${baseUrl}/mpesa/b2c/v3/paymentrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * C2B Register URLs - Register validation and confirmation URLs\n * API: POST /mpesa/c2b/v2/registerurl\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { C2BRegisterUrlRequest } from \"./types\";\n\nexport interface C2BRegisterUrlResponse {\n ConversationID: string;\n OriginatorCoversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function registerC2BUrls(\n baseUrl: string,\n accessToken: string,\n request: C2BRegisterUrlRequest\n): Promise<C2BRegisterUrlResponse> {\n const body = {\n ShortCode: request.shortCode,\n ResponseType: request.responseType ?? \"Completed\",\n ConfirmationURL: request.confirmationUrl,\n ValidationURL: request.validationUrl,\n };\n\n const { data } = await httpRequest<C2BRegisterUrlResponse>(\n `${baseUrl}/mpesa/c2b/v2/registerurl`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * C2B Simulate - Simulate C2B payment (sandbox only)\n * API: POST /mpesa/c2b/v2/simulate\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport { formatPhoneNumber } from \"../stk-push/utils\";\nimport type { C2BSimulateRequest } from \"./types\";\n\nexport interface C2BSimulateResponse {\n ConversationID: string;\n OriginatorCoversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function simulateC2B(\n baseUrl: string,\n accessToken: string,\n request: C2BSimulateRequest\n): Promise<C2BSimulateResponse> {\n const body = {\n ShortCode: request.shortCode,\n CommandID: \"CustomerPayBillOnline\",\n Amount: Math.round(request.amount),\n Msisdn: formatPhoneNumber(request.phoneNumber),\n BillRefNumber: request.billRefNumber ?? \"default\",\n };\n\n const { data } = await httpRequest<C2BSimulateResponse>(\n `${baseUrl}/mpesa/c2b/v2/simulate`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Dynamic QR Code - Generate LIPA NA M-PESA QR codes\n * API: POST /mpesa/qrcode/v1/generate\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { DynamicQRRequest } from \"./types\";\n\nexport interface DynamicQRResponse {\n ResponseCode: string;\n RequestID: string;\n ResponseDescription: string;\n QRCode: string;\n}\n\nexport async function generateDynamicQR(\n baseUrl: string,\n accessToken: string,\n request: DynamicQRRequest\n): Promise<DynamicQRResponse> {\n const body = {\n MerchantName: request.merchantName,\n RefNo: request.refNo,\n Amount: Math.round(request.amount),\n TrxCode: request.trxCode,\n CPI: request.cpi,\n Size: request.size ?? \"300\",\n };\n\n const { data } = await httpRequest<DynamicQRResponse>(\n `${baseUrl}/mpesa/qrcode/v1/generate`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Transaction Reversal\n * API: POST /mpesa/reversal/v1/request\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { ReversalRequest } from \"./types\";\n\nexport interface ReversalResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processReversal(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: ReversalRequest\n): Promise<ReversalResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: \"TransactionReversal\",\n TransactionID: request.transactionId,\n Amount: Math.round(request.amount),\n ReceiverParty: request.shortCode,\n RecieverIdentifierType: 4,\n ResultURL: request.resultUrl,\n QueueTimeOutURL: request.timeoutUrl,\n Remarks: request.remarks ?? \"Reversal\",\n Occasion: request.occasion ?? \"Reversal\",\n };\n\n const { data } = await httpRequest<ReversalResponse>(\n `${baseUrl}/mpesa/reversal/v1/request`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * M-Pesa Express (STK Push) - Initiates payment prompt on customer's phone\n * API: POST /mpesa/stkpush/v1/processrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { StkPushRequest, StkPushResponse } from \"./types\";\nimport { formatPhoneNumber, getStkPushPassword, getTimestamp } from \"./utils\";\n\nexport async function processStkPush(\n baseUrl: string,\n accessToken: string,\n request: StkPushRequest\n): Promise<StkPushResponse> {\n const body = {\n BusinessShortCode: request.shortCode,\n Password: getStkPushPassword(request.shortCode, request.passKey),\n Timestamp: getTimestamp(),\n TransactionType: request.transactionType ?? \"CustomerPayBillOnline\",\n Amount: Math.round(request.amount),\n PartyA: formatPhoneNumber(request.phoneNumber),\n PartyB: request.shortCode,\n PhoneNumber: formatPhoneNumber(request.phoneNumber),\n CallBackURL: request.callbackUrl,\n AccountReference: request.accountReference.slice(0, 12),\n TransactionDesc: request.transactionDesc.slice(0, 13),\n };\n\n const { data } = await httpRequest<StkPushResponse>(\n `${baseUrl}/mpesa/stkpush/v1/processrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * STK Push Query - Check status of STK Push transaction\n * API: POST /mpesa/stkpushquery/v1/query\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { StkQueryRequest, StkQueryResponse } from \"./types\";\nimport { getStkPushPassword, getTimestamp } from \"./utils\";\n\nexport async function queryStkPush(\n baseUrl: string,\n accessToken: string,\n request: StkQueryRequest\n): Promise<StkQueryResponse> {\n const body = {\n BusinessShortCode: request.shortCode,\n Password: getStkPushPassword(request.shortCode, request.passKey),\n Timestamp: getTimestamp(),\n CheckoutRequestID: request.checkoutRequestId,\n };\n\n const { data } = await httpRequest<StkQueryResponse>(\n `${baseUrl}/mpesa/stkpushquery/v1/query`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Transaction Status Query\n * API: POST /mpesa/transactionstatus/v1/query\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { TransactionStatusRequest } from \"./types\";\n\nexport interface TransactionStatusResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function queryTransactionStatus(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: TransactionStatusRequest\n): Promise<TransactionStatusResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: \"TransactionStatusQuery\",\n TransactionID: request.transactionId,\n PartyA: request.shortCode,\n IdentifierType: request.identifierType ?? 4,\n ResultURL: request.resultUrl,\n QueueTimeOutURL: request.timeoutUrl,\n Remarks: \"Status\",\n Occasion: \"Query\",\n };\n\n const { data } = await httpRequest<TransactionStatusResponse>(\n `${baseUrl}/mpesa/transactionstatus/v1/query`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","export type Environment = \"sandbox\" | \"production\";\n\nexport const DARAJA_BASE_URLS = {\n sandbox: \"https://sandbox.safaricom.co.ke\",\n production: \"https://api.safaricom.co.ke\",\n} as const;\n\nexport interface MpesaConfig {\n consumerKey: string;\n consumerSecret: string;\n environment: Environment;\n /** Required for STK Push - Lipa Na M-Pesa passkey from Daraja portal */\n lipaNaMpesaShortCode?: string;\n lipaNaMpesaPassKey?: string;\n /** Required for B2C, B2B, Reversal - initiator name and password */\n initiatorName?: string;\n initiatorPassword?: string;\n /** PEM certificate for encrypting initiator password. Download from Daraja portal */\n certificatePath?: string;\n /** PEM certificate string (alternative to certificatePath) */\n certificatePem?: string;\n /** Pre-encrypted security credential (alternative to initiatorPassword + certificate) */\n securityCredential?: string;\n}\n","/**\n * M-Pesa Daraja API client\n */\n\nimport { TokenManager } from \"../core/auth\";\nimport { encryptSecurityCredential } from \"../core/encryption\";\nimport { type B2BRequest, processB2B } from \"./b2b\";\nimport { type B2CRequest, processB2C } from \"./b2c\";\nimport {\n type C2BRegisterUrlRequest,\n type C2BSimulateRequest,\n registerC2BUrls,\n simulateC2B,\n} from \"./c2b\";\nimport { type DynamicQRRequest, generateDynamicQR } from \"./qr-code\";\nimport { processReversal, type ReversalRequest } from \"./reversal\";\nimport {\n processStkPush,\n queryStkPush,\n type StkPushRequest,\n type StkQueryRequest,\n} from \"./stk-push\";\nimport {\n queryTransactionStatus,\n type TransactionStatusRequest,\n} from \"./transaction-status\";\nimport { DARAJA_BASE_URLS, type MpesaConfig } from \"./types\";\n\nexport class Mpesa {\n private config: MpesaConfig;\n private tokenManager: TokenManager;\n private baseUrl: string;\n\n constructor(config: MpesaConfig) {\n this.config = config;\n this.baseUrl = DARAJA_BASE_URLS[config.environment];\n this.tokenManager = new TokenManager(\n config.consumerKey,\n config.consumerSecret,\n this.baseUrl\n );\n }\n\n private async getToken(): Promise<string> {\n return this.tokenManager.getAccessToken();\n }\n\n private async getSecurityCredential(): Promise<string> {\n if (this.config.securityCredential) return this.config.securityCredential;\n if (!this.config.initiatorPassword) {\n throw new Error(\n \"Security credential required: provide securityCredential or (initiatorPassword + certificatePath/certificatePem)\"\n );\n }\n let cert: string;\n if (this.config.certificatePem) {\n cert = this.config.certificatePem;\n } else if (this.config.certificatePath) {\n cert = await Bun.file(this.config.certificatePath).text();\n } else {\n throw new Error(\n \"certificatePath or certificatePem required for B2C/B2B/Reversal\"\n );\n }\n return encryptSecurityCredential(this.config.initiatorPassword, cert);\n }\n\n /** STK Push (M-Pesa Express) - Initiate payment on customer phone */\n async stkPush(request: Omit<StkPushRequest, \"shortCode\" | \"passKey\">) {\n const shortCode = this.config.lipaNaMpesaShortCode ?? \"\";\n const passKey = this.config.lipaNaMpesaPassKey ?? \"\";\n if (!shortCode || !passKey) {\n throw new Error(\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey required for STK Push\"\n );\n }\n const token = await this.getToken();\n return processStkPush(this.baseUrl, token, {\n ...request,\n shortCode,\n passKey,\n });\n }\n\n /** STK Query - Check STK Push transaction status */\n async stkQuery(request: Omit<StkQueryRequest, \"shortCode\" | \"passKey\">) {\n const shortCode = this.config.lipaNaMpesaShortCode ?? \"\";\n const passKey = this.config.lipaNaMpesaPassKey ?? \"\";\n if (!shortCode || !passKey) {\n throw new Error(\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey required for STK Query\"\n );\n }\n const token = await this.getToken();\n return queryStkPush(this.baseUrl, token, {\n ...request,\n shortCode,\n passKey,\n });\n }\n\n /** B2C - Send money to customer */\n async b2c(request: B2CRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for B2C\");\n const token = await this.getToken();\n return processB2C(this.baseUrl, token, securityCred, initiator, request);\n }\n\n /** B2B - Send money to business */\n async b2b(request: B2BRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for B2B\");\n const token = await this.getToken();\n return processB2B(this.baseUrl, token, securityCred, initiator, request);\n }\n\n /** C2B - Register validation/confirmation URLs */\n async c2bRegisterUrls(request: C2BRegisterUrlRequest) {\n const token = await this.getToken();\n return registerC2BUrls(this.baseUrl, token, request);\n }\n\n /** C2B - Simulate payment (sandbox only) */\n async c2bSimulate(request: C2BSimulateRequest) {\n const token = await this.getToken();\n return simulateC2B(this.baseUrl, token, request);\n }\n\n /** Dynamic QR - Generate LIPA NA M-PESA QR code */\n async qrCode(request: DynamicQRRequest) {\n const token = await this.getToken();\n return generateDynamicQR(this.baseUrl, token, request);\n }\n\n /** Transaction Status - Query transaction status */\n async transactionStatus(request: TransactionStatusRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator)\n throw new Error(\"initiatorName required for Transaction Status\");\n const token = await this.getToken();\n return queryTransactionStatus(\n this.baseUrl,\n token,\n securityCred,\n initiator,\n request\n );\n }\n\n /** Reversal - Reverse a transaction */\n async reversal(request: ReversalRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for Reversal\");\n const token = await this.getToken();\n return processReversal(\n this.baseUrl,\n token,\n securityCred,\n initiator,\n request\n );\n }\n}\n","/**\n * Express-friendly helpers for M-Pesa Express (STK Push) and C2B simulate.\n *\n * NOTE: This module does NOT depend on Express at runtime. You pass in an\n * existing Express Router instance, and we attach handlers to it.\n */\n\nimport type { NextFunction, Request, Response, Router } from \"express\";\n\nimport { Mpesa } from \"../mpesa\";\nimport type { MpesaConfig } from \"../mpesa/types\";\nimport { PesafyError } from \"../utils/errors\";\n\nexport interface MpesaExpressConfig extends MpesaConfig {\n /**\n * Full callback URL that Safaricom will call after STK Push completes.\n * Example (sandbox):\n * https://your-domain.ngrok.io/api/mpesa/express/callback\n */\n callbackUrl: string;\n}\n\nexport function createMpesaExpressClient(config: MpesaExpressConfig): {\n mpesa: Mpesa;\n} {\n if (!config.consumerKey || !config.consumerSecret) {\n throw new PesafyError({\n code: \"INVALID_CREDENTIALS\",\n message: \"consumerKey and consumerSecret are required\",\n });\n }\n\n if (!config.lipaNaMpesaShortCode || !config.lipaNaMpesaPassKey) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message:\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey are required for STK Push\",\n });\n }\n\n if (!config.callbackUrl) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"callbackUrl is required for STK Push callbacks\",\n });\n }\n\n const mpesa = new Mpesa(config);\n return { mpesa };\n}\n\ninterface StkPushBody {\n amount: number;\n phoneNumber: string;\n accountReference?: string;\n transactionDesc?: string;\n}\n\ninterface StkQueryBody {\n checkoutRequestId: string;\n}\n\nfunction normalizePhone(phone: string): string {\n const digits = phone.replace(/\\D/g, \"\");\n if (digits.startsWith(\"254\")) return digits;\n if (digits.startsWith(\"0\")) return `254${digits.slice(1)}`;\n return digits;\n}\n\nfunction sendError(res: Response, error: unknown): void {\n if (error instanceof PesafyError) {\n const status = error.statusCode ?? 400;\n res.status(status).json({\n error: error.code,\n message: error.message,\n statusCode: status,\n });\n return;\n }\n\n res.status(500).json({\n error: \"REQUEST_FAILED\",\n message: \"Unexpected error while processing M-Pesa request\",\n });\n}\n\nexport function createMpesaExpressRouter(\n router: Router,\n config: MpesaExpressConfig\n): Router {\n const { mpesa } = createMpesaExpressClient(config);\n\n // STK Push – initiate payment on customer phone\n router.post(\n \"/mpesa/express/stk-push\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const body = req.body as StkPushBody;\n\n if (!body || typeof body.amount !== \"number\" || body.amount <= 0) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"amount must be a positive number\",\n });\n }\n\n if (!body.phoneNumber) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"phoneNumber is required\",\n });\n }\n\n const phoneNumber = normalizePhone(body.phoneNumber);\n\n const result = await mpesa.stkPush({\n amount: body.amount,\n phoneNumber,\n callbackUrl: config.callbackUrl,\n accountReference:\n body.accountReference ??\n `PESAFY-${Date.now().toString(36).toUpperCase()}`,\n transactionDesc: body.transactionDesc ?? \"Payment\",\n });\n\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // STK Query – check status of an STK Push\n router.post(\n \"/mpesa/express/stk-query\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const body = req.body as StkQueryBody;\n\n if (!body || !body.checkoutRequestId) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"checkoutRequestId is required\",\n });\n }\n\n const result = await mpesa.stkQuery({\n checkoutRequestId: body.checkoutRequestId,\n });\n\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // C2B simulate – sandbox only\n router.post(\n \"/mpesa/c2b/simulate\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const result = await mpesa.c2bSimulate(req.body);\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // C2B register URLs – sandbox only\n router.post(\n \"/mpesa/c2b/register-url\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const result = await mpesa.c2bRegisterUrls(req.body);\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n return router;\n}\n","/**\n * Webhook retry mechanism with exponential backoff\n * For at-least-once delivery guarantee\n */\n\nexport interface RetryOptions {\n maxRetries?: number;\n initialDelay?: number;\n maxDelay?: number;\n backoffMultiplier?: number;\n maxRetryDuration?: number; // milliseconds (30 days default)\n}\n\nconst DEFAULT_OPTIONS: Required<RetryOptions> = {\n maxRetries: Infinity,\n initialDelay: 1000, // 1 second\n maxDelay: 3600000, // 1 hour\n backoffMultiplier: 2,\n maxRetryDuration: 30 * 24 * 60 * 60 * 1000, // 30 days\n};\n\nexport interface RetryResult<T> {\n success: boolean;\n data?: T;\n attempts: number;\n error?: Error;\n}\n\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<RetryResult<T>> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n let delay = opts.initialDelay;\n let attempts = 0;\n const startTime = Date.now();\n\n while (attempts < opts.maxRetries) {\n attempts++;\n\n // Check if we've exceeded max retry duration\n if (Date.now() - startTime > opts.maxRetryDuration) {\n return {\n success: false,\n attempts,\n error: new Error(\"Max retry duration exceeded\"),\n };\n }\n\n try {\n const data = await fn();\n return { success: true, data, attempts };\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n\n // Don't retry on 4xx errors (client errors)\n if (err.message.includes(\"4\")) {\n return { success: false, attempts, error: err };\n }\n\n // Wait before retrying\n if (attempts < opts.maxRetries) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n delay = Math.min(delay * opts.backoffMultiplier, opts.maxDelay);\n }\n }\n }\n\n return {\n success: false,\n attempts,\n error: new Error(\"Max retries exceeded\"),\n };\n}\n","/**\n * Webhook signature verification\n * Note: Daraja API doesn't provide webhook signatures in the same way as Stripe\n * Instead, verify by whitelisting IPs: 196.201.214.200, 196.201.214.206, etc.\n * This utility helps parse and validate webhook payloads\n */\n\nimport type { B2CWebhook, C2BWebhook, StkPushWebhook } from \"./types\";\n\nexport interface WebhookVerificationOptions {\n /** IP whitelist - verify request comes from Safaricom */\n allowedIPs?: string[];\n /** Optional: verify request headers match expected pattern */\n verifyHeaders?: boolean;\n}\n\nconst SAFARICOM_IPS = [\n \"196.201.214.200\",\n \"196.201.214.206\",\n \"196.201.213.114\",\n \"196.201.214.207\",\n \"196.201.214.208\",\n \"196.201.213.44\",\n \"196.201.212.127\",\n \"196.201.212.138\",\n \"196.201.212.129\",\n \"196.201.212.136\",\n \"196.201.212.74\",\n \"196.201.212.69\",\n];\n\nexport function verifyWebhookIP(\n requestIP: string,\n allowedIPs: string[] = SAFARICOM_IPS\n): boolean {\n return allowedIPs.includes(requestIP);\n}\n\nexport function parseStkPushWebhook(body: unknown): StkPushWebhook | null {\n try {\n const parsed = body as StkPushWebhook;\n if (parsed.Body?.stkCallback) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n\nexport function parseB2CWebhook(body: unknown): B2CWebhook | null {\n try {\n const parsed = body as B2CWebhook;\n if (parsed.Result?.ResultCode !== undefined) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n\nexport function parseC2BWebhook(body: unknown): C2BWebhook | null {\n try {\n const parsed = body as C2BWebhook;\n if (parsed.TransID && parsed.TransAmount) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * Webhook event handler utilities\n */\n\nimport {\n parseB2CWebhook,\n parseC2BWebhook,\n parseStkPushWebhook,\n verifyWebhookIP,\n} from \"./signature-verifier\";\nimport type {\n B2CWebhook,\n C2BWebhook,\n StkPushWebhook,\n WebhookEventType,\n} from \"./types\";\n\nexport interface WebhookHandlerOptions {\n /** IP address of incoming request */\n requestIP?: string;\n /** Custom IP whitelist */\n allowedIPs?: string[];\n /** Skip IP verification (for testing) */\n skipIPCheck?: boolean;\n}\n\nexport interface WebhookHandlerResult<T = unknown> {\n success: boolean;\n eventType: WebhookEventType | null;\n data: T | null;\n error?: string;\n}\n\nexport function handleWebhook(\n body: unknown,\n options: WebhookHandlerOptions = {}\n): WebhookHandlerResult {\n // Verify IP if provided\n if (!options.skipIPCheck && options.requestIP) {\n if (!verifyWebhookIP(options.requestIP, options.allowedIPs)) {\n return {\n success: false,\n eventType: null,\n data: null,\n error: \"IP address not whitelisted\",\n };\n }\n }\n\n // Try to parse as STK Push\n const stkPush = parseStkPushWebhook(body);\n if (stkPush) {\n return {\n success: true,\n eventType: \"stk_push\",\n data: stkPush,\n };\n }\n\n // Try to parse as B2C\n const b2c = parseB2CWebhook(body);\n if (b2c) {\n return {\n success: true,\n eventType: \"b2c\",\n data: b2c,\n };\n }\n\n // Try to parse as C2B\n const c2b = parseC2BWebhook(body);\n if (c2b) {\n return {\n success: true,\n eventType: \"c2b\",\n data: c2b,\n };\n }\n\n return {\n success: false,\n eventType: null,\n data: null,\n error: \"Unknown webhook format\",\n };\n}\n\nexport function extractTransactionId(\n webhook: StkPushWebhook | B2CWebhook | C2BWebhook\n): string | null {\n if (\"Body\" in webhook && webhook.Body?.stkCallback) {\n const items = webhook.Body.stkCallback.CallbackMetadata?.Item;\n const mpesaReceipt = items?.find(\n (item) => item.Name === \"MpesaReceiptNumber\"\n );\n return mpesaReceipt ? String(mpesaReceipt.Value) : null;\n }\n if (\"Result\" in webhook && webhook.Result?.TransactionID) {\n return webhook.Result.TransactionID;\n }\n if (\"TransID\" in webhook) {\n return webhook.TransID;\n }\n return null;\n}\n\nexport function extractAmount(\n webhook: StkPushWebhook | B2CWebhook | C2BWebhook\n): number | null {\n if (\"Body\" in webhook && webhook.Body?.stkCallback) {\n const items = webhook.Body.stkCallback.CallbackMetadata?.Item;\n const amount = items?.find((item) => item.Name === \"Amount\");\n return amount ? Number(amount.Value) : null;\n }\n if (\"Result\" in webhook && webhook.Result?.ResultParameters) {\n const params = webhook.Result.ResultParameters.ResultParameter;\n const amount = params?.find((p) => p.Key === \"Amount\");\n return amount ? Number(amount.Value) : null;\n }\n if (\"TransAmount\" in webhook) {\n return Number.parseFloat(webhook.TransAmount);\n }\n return null;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/errors/error-factory.ts","../src/utils/http/client.ts","../src/core/auth/token-manager.ts","../src/core/encryption/security-credentials.ts","../src/mpesa/b2b/b2b.ts","../src/mpesa/stk-push/utils.ts","../src/mpesa/b2c/b2c.ts","../src/mpesa/c2b/register-url.ts","../src/mpesa/c2b/simulate.ts","../src/mpesa/qr-code/dynamic-qr.ts","../src/mpesa/reversal/reversal.ts","../src/mpesa/stk-push/stk-push.ts","../src/mpesa/stk-push/stk-query.ts","../src/mpesa/transaction-status/query.ts","../src/mpesa/types.ts","../src/mpesa/index.ts","../src/express/index.ts","../src/mpesa/webhooks/retry.ts","../src/mpesa/webhooks/signature-verifier.ts","../src/mpesa/webhooks/webhook-handler.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Error creation utilities for Pesafy\n */\n\nimport type { ErrorCode, PesafyErrorOptions } from \"./types\";\n\nexport class PesafyError extends Error {\n readonly code: ErrorCode;\n readonly statusCode?: number;\n readonly response?: unknown;\n readonly requestId?: string;\n override readonly cause?: unknown;\n\n constructor(options: PesafyErrorOptions) {\n super(options.message);\n Object.defineProperty(this, \"name\", { value: \"PesafyError\" });\n this.code = options.code;\n this.statusCode = options.statusCode;\n this.response = options.response;\n this.requestId = options.requestId;\n this.cause = options.cause;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, PesafyError);\n }\n }\n\n toJSON() {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n statusCode: this.statusCode,\n requestId: this.requestId,\n };\n }\n}\n\nexport function createError(options: PesafyErrorOptions): PesafyError {\n return new PesafyError(options);\n}\n","/**\n * HTTP client for Daraja API requests\n */\n\nimport { PesafyError } from \"../errors\";\nimport type { HttpRequestOptions, HttpResponse } from \"./types\";\n\nconst DEFAULT_TIMEOUT = 30000;\n\nexport async function httpRequest<T = unknown>(\n url: string,\n options: HttpRequestOptions = {}\n): Promise<HttpResponse<T>> {\n const {\n method = \"GET\",\n headers = {},\n body,\n timeout = DEFAULT_TIMEOUT,\n } = options;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n ...headers,\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n let data: T;\n const text = await response.text();\n try {\n data = (text ? JSON.parse(text) : {}) as T;\n } catch {\n data = { raw: text } as T;\n }\n\n if (!response.ok) {\n throw new PesafyError({\n code: \"API_ERROR\",\n message: `Request failed with status ${response.status}`,\n statusCode: response.status,\n response: data,\n });\n }\n\n return {\n data,\n status: response.status,\n headers: response.headers,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof PesafyError) throw error;\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n throw new PesafyError({\n code: \"TIMEOUT\",\n message: `Request timed out after ${timeout}ms`,\n cause: error,\n });\n }\n throw new PesafyError({\n code: \"NETWORK_ERROR\",\n message: error.message,\n cause: error,\n });\n }\n throw new PesafyError({\n code: \"REQUEST_FAILED\",\n message: \"An unknown error occurred\",\n cause: error,\n });\n }\n}\n","/**\n * OAuth token manager for Daraja API\n * Token validity: 3600 seconds (1 hour)\n */\n\nimport { PesafyError } from \"../../utils/errors\";\nimport { httpRequest } from \"../../utils/http\";\nimport type { TokenResponse } from \"./types\";\n\nconst TOKEN_BUFFER_SECONDS = 60; // Refresh token 60s before expiry\n\nexport class TokenManager {\n private consumerKey: string;\n private consumerSecret: string;\n private baseUrl: string;\n private cachedToken: string | null = null;\n private tokenExpiresAt = 0;\n\n constructor(consumerKey: string, consumerSecret: string, baseUrl: string) {\n this.consumerKey = consumerKey;\n this.consumerSecret = consumerSecret;\n this.baseUrl = baseUrl;\n }\n\n private getAuthHeader(): string {\n const credentials = `${this.consumerKey}:${this.consumerSecret}`;\n const encoded = Buffer.from(credentials, \"utf-8\").toString(\"base64\");\n return `Basic ${encoded}`;\n }\n\n async getAccessToken(): Promise<string> {\n const now = Date.now() / 1000;\n if (this.cachedToken && this.tokenExpiresAt > now + TOKEN_BUFFER_SECONDS) {\n return this.cachedToken;\n }\n\n const url = `${this.baseUrl}/oauth/v1/generate?grant_type=client_credentials`;\n const response = await httpRequest<TokenResponse>(url, {\n method: \"GET\",\n headers: {\n Authorization: this.getAuthHeader(),\n },\n });\n\n const data = response.data;\n if (!data.access_token) {\n throw new PesafyError({\n code: \"AUTH_FAILED\",\n message: \"Failed to obtain access token\",\n response: data,\n });\n }\n\n this.cachedToken = data.access_token;\n this.tokenExpiresAt = now + (data.expires_in ?? 3600);\n return this.cachedToken;\n }\n\n clearCache(): void {\n this.cachedToken = null;\n this.tokenExpiresAt = 0;\n }\n}\n","/**\n * Security credential encryption for B2C, B2B, Reversal APIs\n * Uses RSA with PKCS#1.5 padding per Daraja API spec\n * Download certificates from: https://developer.safaricom.co.ke/APIs\n */\n\nimport { publicEncrypt } from \"node:crypto\";\nimport { PesafyError } from \"../../utils/errors\";\n\n/** Encrypt initiator password with M-Pesa public certificate (PEM format) */\nexport function encryptSecurityCredential(\n initiatorPassword: string,\n certificatePem: string\n): string {\n try {\n const passwordBuffer = Buffer.from(initiatorPassword, \"utf-8\");\n const encrypted = publicEncrypt(\n {\n key: certificatePem,\n padding: 1, // RSA_PKCS1_PADDING\n },\n passwordBuffer\n );\n return encrypted.toString(\"base64\");\n } catch (error) {\n throw new PesafyError({\n code: \"ENCRYPTION_FAILED\",\n message: \"Failed to encrypt security credential\",\n cause: error,\n });\n }\n}\n","/**\n * B2B - Business to Business payments\n * API: POST /mpesa/b2b/v1/paymentrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { B2BRequest } from \"./types\";\n\nexport interface B2BResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processB2B(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: B2BRequest\n): Promise<B2BResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: request.commandId ?? \"BusinessPayBill\",\n SenderIdentifierType: request.senderIdentifierType ?? 4,\n RecieverIdentifierType: request.receiverIdentifierType ?? 4,\n Amount: Math.round(request.amount),\n PartyA: request.shortCode,\n PartyB: request.receiverShortCode,\n AccountReference: request.accountReference ?? \"\",\n Remarks: request.remarks ?? \"B2B Payment\",\n QueueTimeOutURL: request.timeoutUrl,\n ResultURL: request.resultUrl,\n };\n\n const { data } = await httpRequest<B2BResponse>(\n `${baseUrl}/mpesa/b2b/v1/paymentrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/** STK Push utilities */\n\n/**\n * Formats a phone number to the required 2547XXXXXXXX format.\n * Handles 07XXXXXXXX, 2547XXXXXXXX, and +2547XXXXXXXX inputs.\n */\nexport function formatPhoneNumber(phone: string): string {\n const cleaned = phone.replace(/\\D/g, \"\");\n if (cleaned.startsWith(\"0\")) return \"254\" + cleaned.slice(1);\n if (cleaned.startsWith(\"254\")) return cleaned;\n return \"254\" + cleaned;\n}\n\n/**\n * Generates the STK Push password.\n * Formula: Base64(Shortcode + Passkey + Timestamp)\n *\n * IMPORTANT: The timestamp passed here MUST be the exact same value sent in\n * the request body's `Timestamp` field. Safaricom validates they match.\n * Always call getTimestamp() once and pass the result to both this function\n * and the request body — never call getTimestamp() twice.\n */\nexport function getStkPushPassword(\n shortCode: string,\n passKey: string,\n timestamp: string\n): string {\n const raw = `${shortCode}${passKey}${timestamp}`;\n return Buffer.from(raw, \"utf-8\").toString(\"base64\");\n}\n\n/**\n * Generates a Daraja-compatible timestamp: YYYYMMDDHHmmss\n * Call this once per request and reuse the value.\n */\nexport function getTimestamp(): string {\n const now = new Date();\n const pad = (n: number) => n.toString().padStart(2, \"0\");\n return [\n now.getFullYear(),\n pad(now.getMonth() + 1),\n pad(now.getDate()),\n pad(now.getHours()),\n pad(now.getMinutes()),\n pad(now.getSeconds()),\n ].join(\"\");\n}\n","/**\n * B2C - Business to Customer payments\n * API: POST /mpesa/b2c/v3/paymentrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport { formatPhoneNumber } from \"../stk-push/utils\";\nimport type { B2CRequest } from \"./types\";\n\nexport interface B2CResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processB2C(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: B2CRequest\n): Promise<B2CResponse> {\n const body = {\n OriginatorConversationID: `AG_${Date.now()}_${Math.random().toString(36).slice(2)}`,\n InitiatorName: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: request.commandId ?? \"BusinessPayment\",\n Amount: Math.round(request.amount),\n PartyA: request.shortCode,\n PartyB: formatPhoneNumber(request.phoneNumber),\n Remarks: request.remarks ?? \"Payment\",\n QueueTimeOutURL: request.timeoutUrl,\n ResultURL: request.resultUrl,\n Occasion: request.occasion ?? \"\",\n };\n\n const { data } = await httpRequest<B2CResponse>(\n `${baseUrl}/mpesa/b2c/v3/paymentrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * C2B Register URLs - Register validation and confirmation URLs\n * API: POST /mpesa/c2b/v2/registerurl\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { C2BRegisterUrlRequest } from \"./types\";\n\nexport interface C2BRegisterUrlResponse {\n ConversationID: string;\n OriginatorCoversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function registerC2BUrls(\n baseUrl: string,\n accessToken: string,\n request: C2BRegisterUrlRequest\n): Promise<C2BRegisterUrlResponse> {\n const body = {\n ShortCode: request.shortCode,\n ResponseType: request.responseType ?? \"Completed\",\n ConfirmationURL: request.confirmationUrl,\n ValidationURL: request.validationUrl,\n };\n\n const { data } = await httpRequest<C2BRegisterUrlResponse>(\n `${baseUrl}/mpesa/c2b/v2/registerurl`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * C2B Simulate - Simulate C2B payment (sandbox only)\n * API: POST /mpesa/c2b/v2/simulate\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport { formatPhoneNumber } from \"../stk-push/utils\";\nimport type { C2BSimulateRequest } from \"./types\";\n\nexport interface C2BSimulateResponse {\n ConversationID: string;\n OriginatorCoversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function simulateC2B(\n baseUrl: string,\n accessToken: string,\n request: C2BSimulateRequest\n): Promise<C2BSimulateResponse> {\n const body = {\n ShortCode: request.shortCode,\n CommandID: \"CustomerPayBillOnline\",\n Amount: Math.round(request.amount),\n Msisdn: formatPhoneNumber(request.phoneNumber),\n BillRefNumber: request.billRefNumber ?? \"default\",\n };\n\n const { data } = await httpRequest<C2BSimulateResponse>(\n `${baseUrl}/mpesa/c2b/v2/simulate`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Dynamic QR Code - Generate LIPA NA M-PESA QR codes\n * API: POST /mpesa/qrcode/v1/generate\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { DynamicQRRequest } from \"./types\";\n\nexport interface DynamicQRResponse {\n ResponseCode: string;\n RequestID: string;\n ResponseDescription: string;\n QRCode: string;\n}\n\nexport async function generateDynamicQR(\n baseUrl: string,\n accessToken: string,\n request: DynamicQRRequest\n): Promise<DynamicQRResponse> {\n const body = {\n MerchantName: request.merchantName,\n RefNo: request.refNo,\n Amount: Math.round(request.amount),\n TrxCode: request.trxCode,\n CPI: request.cpi,\n Size: request.size ?? \"300\",\n };\n\n const { data } = await httpRequest<DynamicQRResponse>(\n `${baseUrl}/mpesa/qrcode/v1/generate`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Transaction Reversal\n * API: POST /mpesa/reversal/v1/request\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { ReversalRequest } from \"./types\";\n\nexport interface ReversalResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function processReversal(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: ReversalRequest\n): Promise<ReversalResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: \"TransactionReversal\",\n TransactionID: request.transactionId,\n Amount: Math.round(request.amount),\n ReceiverParty: request.shortCode,\n RecieverIdentifierType: 4,\n ResultURL: request.resultUrl,\n QueueTimeOutURL: request.timeoutUrl,\n Remarks: request.remarks ?? \"Reversal\",\n Occasion: request.occasion ?? \"Reversal\",\n };\n\n const { data } = await httpRequest<ReversalResponse>(\n `${baseUrl}/mpesa/reversal/v1/request`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * M-Pesa Express (STK Push) - Initiates payment prompt on customer's phone\n * API: POST /mpesa/stkpush/v1/processrequest\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { StkPushRequest, StkPushResponse } from \"./types\";\nimport { formatPhoneNumber, getStkPushPassword, getTimestamp } from \"./utils\";\n\nexport async function processStkPush(\n baseUrl: string,\n accessToken: string,\n request: StkPushRequest\n): Promise<StkPushResponse> {\n // Generate timestamp ONCE — must be identical in both Password and Timestamp fields.\n // Safaricom validates that Base64(Shortcode+Passkey+Timestamp) matches the\n // Timestamp field; generating two separate timestamps causes auth failures.\n const timestamp = getTimestamp();\n\n // For CustomerBuyGoodsOnline (Till Number), PartyB is the till number.\n // For CustomerPayBillOnline (Paybill), PartyB is the shortcode.\n // Docs: https://developer.safaricom.co.ke/APIs/MpesaExpressSimulate\n const partyB = request.partyB ?? request.shortCode;\n\n const body = {\n BusinessShortCode: request.shortCode,\n Password: getStkPushPassword(request.shortCode, request.passKey, timestamp),\n Timestamp: timestamp,\n TransactionType: request.transactionType ?? \"CustomerPayBillOnline\",\n Amount: Math.round(request.amount),\n PartyA: formatPhoneNumber(request.phoneNumber),\n PartyB: partyB,\n PhoneNumber: formatPhoneNumber(request.phoneNumber),\n CallBackURL: request.callbackUrl,\n AccountReference: request.accountReference.slice(0, 12),\n TransactionDesc: request.transactionDesc.slice(0, 13),\n };\n\n const { data } = await httpRequest<StkPushResponse>(\n `${baseUrl}/mpesa/stkpush/v1/processrequest`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * STK Push Query - Check status of STK Push transaction\n * API: POST /mpesa/stkpushquery/v1/query\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { StkQueryRequest, StkQueryResponse } from \"./types\";\nimport { getStkPushPassword, getTimestamp } from \"./utils\";\n\nexport async function queryStkPush(\n baseUrl: string,\n accessToken: string,\n request: StkQueryRequest\n): Promise<StkQueryResponse> {\n // Generate timestamp ONCE — Password and Timestamp field must match exactly.\n const timestamp = getTimestamp();\n\n const body = {\n BusinessShortCode: request.shortCode,\n Password: getStkPushPassword(request.shortCode, request.passKey, timestamp),\n Timestamp: timestamp,\n CheckoutRequestID: request.checkoutRequestId,\n };\n\n const { data } = await httpRequest<StkQueryResponse>(\n `${baseUrl}/mpesa/stkpushquery/v1/query`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","/**\n * Transaction Status Query\n * API: POST /mpesa/transactionstatus/v1/query\n */\n\nimport { httpRequest } from \"../../utils/http\";\nimport type { TransactionStatusRequest } from \"./types\";\n\nexport interface TransactionStatusResponse {\n OriginatorConversationID: string;\n ConversationID: string;\n ResponseCode: string;\n ResponseDescription: string;\n}\n\nexport async function queryTransactionStatus(\n baseUrl: string,\n accessToken: string,\n securityCredential: string,\n initiatorName: string,\n request: TransactionStatusRequest\n): Promise<TransactionStatusResponse> {\n const body = {\n Initiator: initiatorName,\n SecurityCredential: securityCredential,\n CommandID: \"TransactionStatusQuery\",\n TransactionID: request.transactionId,\n PartyA: request.shortCode,\n IdentifierType: request.identifierType ?? 4,\n ResultURL: request.resultUrl,\n QueueTimeOutURL: request.timeoutUrl,\n Remarks: \"Status\",\n Occasion: \"Query\",\n };\n\n const { data } = await httpRequest<TransactionStatusResponse>(\n `${baseUrl}/mpesa/transactionstatus/v1/query`,\n {\n method: \"POST\",\n headers: { Authorization: `Bearer ${accessToken}` },\n body,\n }\n );\n\n return data;\n}\n","export type Environment = \"sandbox\" | \"production\";\n\nexport const DARAJA_BASE_URLS = {\n sandbox: \"https://sandbox.safaricom.co.ke\",\n production: \"https://api.safaricom.co.ke\",\n} as const;\n\nexport interface MpesaConfig {\n consumerKey: string;\n consumerSecret: string;\n environment: Environment;\n /** Required for STK Push - Lipa Na M-Pesa passkey from Daraja portal */\n lipaNaMpesaShortCode?: string;\n lipaNaMpesaPassKey?: string;\n /** Required for B2C, B2B, Reversal - initiator name and password */\n initiatorName?: string;\n initiatorPassword?: string;\n /** PEM certificate for encrypting initiator password. Download from Daraja portal */\n certificatePath?: string;\n /** PEM certificate string (alternative to certificatePath) */\n certificatePem?: string;\n /** Pre-encrypted security credential (alternative to initiatorPassword + certificate) */\n securityCredential?: string;\n}\n","/**\n * M-Pesa Daraja API client\n */\n\nimport { TokenManager } from \"../core/auth\";\nimport { encryptSecurityCredential } from \"../core/encryption\";\nimport { type B2BRequest, processB2B } from \"./b2b\";\nimport { type B2CRequest, processB2C } from \"./b2c\";\nimport {\n type C2BRegisterUrlRequest,\n type C2BSimulateRequest,\n registerC2BUrls,\n simulateC2B,\n} from \"./c2b\";\nimport { type DynamicQRRequest, generateDynamicQR } from \"./qr-code\";\nimport { processReversal, type ReversalRequest } from \"./reversal\";\nimport {\n processStkPush,\n queryStkPush,\n type StkPushRequest,\n type StkQueryRequest,\n} from \"./stk-push\";\nimport {\n queryTransactionStatus,\n type TransactionStatusRequest,\n} from \"./transaction-status\";\nimport { DARAJA_BASE_URLS, type MpesaConfig } from \"./types\";\n\nexport class Mpesa {\n private config: MpesaConfig;\n private tokenManager: TokenManager;\n private baseUrl: string;\n\n constructor(config: MpesaConfig) {\n this.config = config;\n this.baseUrl = DARAJA_BASE_URLS[config.environment];\n this.tokenManager = new TokenManager(\n config.consumerKey,\n config.consumerSecret,\n this.baseUrl\n );\n }\n\n private async getToken(): Promise<string> {\n return this.tokenManager.getAccessToken();\n }\n\n private async getSecurityCredential(): Promise<string> {\n if (this.config.securityCredential) return this.config.securityCredential;\n if (!this.config.initiatorPassword) {\n throw new Error(\n \"Security credential required: provide securityCredential or (initiatorPassword + certificatePath/certificatePem)\"\n );\n }\n let cert: string;\n if (this.config.certificatePem) {\n cert = this.config.certificatePem;\n } else if (this.config.certificatePath) {\n cert = await Bun.file(this.config.certificatePath).text();\n } else {\n throw new Error(\n \"certificatePath or certificatePem required for B2C/B2B/Reversal\"\n );\n }\n return encryptSecurityCredential(this.config.initiatorPassword, cert);\n }\n\n /** STK Push (M-Pesa Express) - Initiate payment on customer phone */\n async stkPush(request: Omit<StkPushRequest, \"shortCode\" | \"passKey\">) {\n const shortCode = this.config.lipaNaMpesaShortCode ?? \"\";\n const passKey = this.config.lipaNaMpesaPassKey ?? \"\";\n if (!shortCode || !passKey) {\n throw new Error(\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey required for STK Push\"\n );\n }\n const token = await this.getToken();\n return processStkPush(this.baseUrl, token, {\n ...request,\n shortCode,\n passKey,\n });\n }\n\n /** STK Query - Check STK Push transaction status */\n async stkQuery(request: Omit<StkQueryRequest, \"shortCode\" | \"passKey\">) {\n const shortCode = this.config.lipaNaMpesaShortCode ?? \"\";\n const passKey = this.config.lipaNaMpesaPassKey ?? \"\";\n if (!shortCode || !passKey) {\n throw new Error(\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey required for STK Query\"\n );\n }\n const token = await this.getToken();\n return queryStkPush(this.baseUrl, token, {\n ...request,\n shortCode,\n passKey,\n });\n }\n\n /** B2C - Send money to customer */\n async b2c(request: B2CRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for B2C\");\n const token = await this.getToken();\n return processB2C(this.baseUrl, token, securityCred, initiator, request);\n }\n\n /** B2B - Send money to business */\n async b2b(request: B2BRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for B2B\");\n const token = await this.getToken();\n return processB2B(this.baseUrl, token, securityCred, initiator, request);\n }\n\n /** C2B - Register validation/confirmation URLs */\n async c2bRegisterUrls(request: C2BRegisterUrlRequest) {\n const token = await this.getToken();\n return registerC2BUrls(this.baseUrl, token, request);\n }\n\n /** C2B - Simulate payment (sandbox only) */\n async c2bSimulate(request: C2BSimulateRequest) {\n const token = await this.getToken();\n return simulateC2B(this.baseUrl, token, request);\n }\n\n /** Dynamic QR - Generate LIPA NA M-PESA QR code */\n async qrCode(request: DynamicQRRequest) {\n const token = await this.getToken();\n return generateDynamicQR(this.baseUrl, token, request);\n }\n\n /** Transaction Status - Query transaction status */\n async transactionStatus(request: TransactionStatusRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator)\n throw new Error(\"initiatorName required for Transaction Status\");\n const token = await this.getToken();\n return queryTransactionStatus(\n this.baseUrl,\n token,\n securityCred,\n initiator,\n request\n );\n }\n\n /** Reversal - Reverse a transaction */\n async reversal(request: ReversalRequest) {\n const initiator = this.config.initiatorName ?? \"\";\n const securityCred = await this.getSecurityCredential();\n if (!initiator) throw new Error(\"initiatorName required for Reversal\");\n const token = await this.getToken();\n return processReversal(\n this.baseUrl,\n token,\n securityCred,\n initiator,\n request\n );\n }\n}\n","/**\n * Express-friendly helpers for M-Pesa Express (STK Push) and C2B simulate.\n *\n * NOTE: This module does NOT depend on Express at runtime. You pass in an\n * existing Express Router instance, and we attach handlers to it.\n */\n\nimport type { NextFunction, Request, Response, Router } from \"express\";\n\nimport { Mpesa } from \"../mpesa\";\nimport type { MpesaConfig } from \"../mpesa/types\";\nimport { PesafyError } from \"../utils/errors\";\n\nexport interface MpesaExpressConfig extends MpesaConfig {\n /**\n * Full callback URL that Safaricom will call after STK Push completes.\n * Example (sandbox):\n * https://your-domain.ngrok.io/api/mpesa/express/callback\n */\n callbackUrl: string;\n}\n\nexport function createMpesaExpressClient(config: MpesaExpressConfig): {\n mpesa: Mpesa;\n} {\n if (!config.consumerKey || !config.consumerSecret) {\n throw new PesafyError({\n code: \"INVALID_CREDENTIALS\",\n message: \"consumerKey and consumerSecret are required\",\n });\n }\n\n if (!config.lipaNaMpesaShortCode || !config.lipaNaMpesaPassKey) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message:\n \"lipaNaMpesaShortCode and lipaNaMpesaPassKey are required for STK Push\",\n });\n }\n\n if (!config.callbackUrl) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"callbackUrl is required for STK Push callbacks\",\n });\n }\n\n const mpesa = new Mpesa(config);\n return { mpesa };\n}\n\ninterface StkPushBody {\n amount: number;\n phoneNumber: string;\n accountReference?: string;\n transactionDesc?: string;\n}\n\ninterface StkQueryBody {\n checkoutRequestId: string;\n}\n\nfunction normalizePhone(phone: string): string {\n const digits = phone.replace(/\\D/g, \"\");\n if (digits.startsWith(\"254\")) return digits;\n if (digits.startsWith(\"0\")) return `254${digits.slice(1)}`;\n return digits;\n}\n\nfunction sendError(res: Response, error: unknown): void {\n if (error instanceof PesafyError) {\n const status = error.statusCode ?? 400;\n res.status(status).json({\n error: error.code,\n message: error.message,\n statusCode: status,\n });\n return;\n }\n\n res.status(500).json({\n error: \"REQUEST_FAILED\",\n message: \"Unexpected error while processing M-Pesa request\",\n });\n}\n\nexport function createMpesaExpressRouter(\n router: Router,\n config: MpesaExpressConfig\n): Router {\n const { mpesa } = createMpesaExpressClient(config);\n\n // STK Push – initiate payment on customer phone\n router.post(\n \"/mpesa/express/stk-push\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const body = req.body as StkPushBody;\n\n if (!body || typeof body.amount !== \"number\" || body.amount <= 0) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"amount must be a positive number\",\n });\n }\n\n if (!body.phoneNumber) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"phoneNumber is required\",\n });\n }\n\n const phoneNumber = normalizePhone(body.phoneNumber);\n\n const result = await mpesa.stkPush({\n amount: body.amount,\n phoneNumber,\n callbackUrl: config.callbackUrl,\n accountReference:\n body.accountReference ??\n `PESAFY-${Date.now().toString(36).toUpperCase()}`,\n transactionDesc: body.transactionDesc ?? \"Payment\",\n });\n\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // STK Query – check status of an STK Push\n router.post(\n \"/mpesa/express/stk-query\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const body = req.body as StkQueryBody;\n\n if (!body || !body.checkoutRequestId) {\n throw new PesafyError({\n code: \"VALIDATION_ERROR\",\n message: \"checkoutRequestId is required\",\n });\n }\n\n const result = await mpesa.stkQuery({\n checkoutRequestId: body.checkoutRequestId,\n });\n\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // C2B simulate – sandbox only\n router.post(\n \"/mpesa/c2b/simulate\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const result = await mpesa.c2bSimulate(req.body);\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n // C2B register URLs – sandbox only\n router.post(\n \"/mpesa/c2b/register-url\",\n async (req: Request, res: Response, next: NextFunction) => {\n try {\n const result = await mpesa.c2bRegisterUrls(req.body);\n res.status(200).json(result);\n } catch (error) {\n if (res.headersSent) return next(error);\n sendError(res, error);\n }\n }\n );\n\n return router;\n}\n","/**\n * Webhook retry mechanism with exponential backoff\n * For at-least-once delivery guarantee\n */\n\nexport interface RetryOptions {\n maxRetries?: number;\n initialDelay?: number;\n maxDelay?: number;\n backoffMultiplier?: number;\n maxRetryDuration?: number; // milliseconds (30 days default)\n}\n\nconst DEFAULT_OPTIONS: Required<RetryOptions> = {\n maxRetries: Infinity,\n initialDelay: 1000, // 1 second\n maxDelay: 3600000, // 1 hour\n backoffMultiplier: 2,\n maxRetryDuration: 30 * 24 * 60 * 60 * 1000, // 30 days\n};\n\nexport interface RetryResult<T> {\n success: boolean;\n data?: T;\n attempts: number;\n error?: Error;\n}\n\nexport async function retryWithBackoff<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<RetryResult<T>> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n let delay = opts.initialDelay;\n let attempts = 0;\n const startTime = Date.now();\n\n while (attempts < opts.maxRetries) {\n attempts++;\n\n // Check if we've exceeded max retry duration\n if (Date.now() - startTime > opts.maxRetryDuration) {\n return {\n success: false,\n attempts,\n error: new Error(\"Max retry duration exceeded\"),\n };\n }\n\n try {\n const data = await fn();\n return { success: true, data, attempts };\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n\n // Don't retry on 4xx errors (client errors)\n if (err.message.includes(\"4\")) {\n return { success: false, attempts, error: err };\n }\n\n // Wait before retrying\n if (attempts < opts.maxRetries) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n delay = Math.min(delay * opts.backoffMultiplier, opts.maxDelay);\n }\n }\n }\n\n return {\n success: false,\n attempts,\n error: new Error(\"Max retries exceeded\"),\n };\n}\n","/**\n * Webhook signature verification\n * Note: Daraja API doesn't provide webhook signatures in the same way as Stripe\n * Instead, verify by whitelisting IPs: 196.201.214.200, 196.201.214.206, etc.\n * This utility helps parse and validate webhook payloads\n */\n\nimport type { B2CWebhook, C2BWebhook, StkPushWebhook } from \"./types\";\n\nexport interface WebhookVerificationOptions {\n /** IP whitelist - verify request comes from Safaricom */\n allowedIPs?: string[];\n /** Optional: verify request headers match expected pattern */\n verifyHeaders?: boolean;\n}\n\nconst SAFARICOM_IPS = [\n \"196.201.214.200\",\n \"196.201.214.206\",\n \"196.201.213.114\",\n \"196.201.214.207\",\n \"196.201.214.208\",\n \"196.201.213.44\",\n \"196.201.212.127\",\n \"196.201.212.138\",\n \"196.201.212.129\",\n \"196.201.212.136\",\n \"196.201.212.74\",\n \"196.201.212.69\",\n];\n\nexport function verifyWebhookIP(\n requestIP: string,\n allowedIPs: string[] = SAFARICOM_IPS\n): boolean {\n return allowedIPs.includes(requestIP);\n}\n\nexport function parseStkPushWebhook(body: unknown): StkPushWebhook | null {\n try {\n const parsed = body as StkPushWebhook;\n if (parsed.Body?.stkCallback) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n\nexport function parseB2CWebhook(body: unknown): B2CWebhook | null {\n try {\n const parsed = body as B2CWebhook;\n if (parsed.Result?.ResultCode !== undefined) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n\nexport function parseC2BWebhook(body: unknown): C2BWebhook | null {\n try {\n const parsed = body as C2BWebhook;\n if (parsed.TransID && parsed.TransAmount) return parsed;\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * Webhook event handler utilities\n */\n\nimport {\n parseB2CWebhook,\n parseC2BWebhook,\n parseStkPushWebhook,\n verifyWebhookIP,\n} from \"./signature-verifier\";\nimport type {\n B2CWebhook,\n C2BWebhook,\n StkPushWebhook,\n WebhookEventType,\n} from \"./types\";\n\nexport interface WebhookHandlerOptions {\n /** IP address of incoming request */\n requestIP?: string;\n /** Custom IP whitelist */\n allowedIPs?: string[];\n /** Skip IP verification (for testing) */\n skipIPCheck?: boolean;\n}\n\nexport interface WebhookHandlerResult<T = unknown> {\n success: boolean;\n eventType: WebhookEventType | null;\n data: T | null;\n error?: string;\n}\n\nexport function handleWebhook(\n body: unknown,\n options: WebhookHandlerOptions = {}\n): WebhookHandlerResult {\n // Verify IP if provided\n if (!options.skipIPCheck && options.requestIP) {\n if (!verifyWebhookIP(options.requestIP, options.allowedIPs)) {\n return {\n success: false,\n eventType: null,\n data: null,\n error: \"IP address not whitelisted\",\n };\n }\n }\n\n // Try to parse as STK Push\n const stkPush = parseStkPushWebhook(body);\n if (stkPush) {\n return {\n success: true,\n eventType: \"stk_push\",\n data: stkPush,\n };\n }\n\n // Try to parse as B2C\n const b2c = parseB2CWebhook(body);\n if (b2c) {\n return {\n success: true,\n eventType: \"b2c\",\n data: b2c,\n };\n }\n\n // Try to parse as C2B\n const c2b = parseC2BWebhook(body);\n if (c2b) {\n return {\n success: true,\n eventType: \"c2b\",\n data: c2b,\n };\n }\n\n return {\n success: false,\n eventType: null,\n data: null,\n error: \"Unknown webhook format\",\n };\n}\n\nexport function extractTransactionId(\n webhook: StkPushWebhook | B2CWebhook | C2BWebhook\n): string | null {\n if (\"Body\" in webhook && webhook.Body?.stkCallback) {\n const items = webhook.Body.stkCallback.CallbackMetadata?.Item;\n const mpesaReceipt = items?.find(\n (item) => item.Name === \"MpesaReceiptNumber\"\n );\n return mpesaReceipt ? String(mpesaReceipt.Value) : null;\n }\n if (\"Result\" in webhook && webhook.Result?.TransactionID) {\n return webhook.Result.TransactionID;\n }\n if (\"TransID\" in webhook) {\n return webhook.TransID;\n }\n return null;\n}\n\nexport function extractAmount(\n webhook: StkPushWebhook | B2CWebhook | C2BWebhook\n): number | null {\n if (\"Body\" in webhook && webhook.Body?.stkCallback) {\n const items = webhook.Body.stkCallback.CallbackMetadata?.Item;\n const amount = items?.find((item) => item.Name === \"Amount\");\n return amount ? Number(amount.Value) : null;\n }\n if (\"Result\" in webhook && webhook.Result?.ResultParameters) {\n const params = webhook.Result.ResultParameters.ResultParameter;\n const amount = params?.find((p) => p.Key === \"Amount\");\n return amount ? Number(amount.Value) : null;\n }\n if (\"TransAmount\" in webhook) {\n return Number.parseFloat(webhook.TransAmount);\n }\n return null;\n}\n"]}
|
package/package.json
CHANGED