pesafy 0.0.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.js ADDED
@@ -0,0 +1 @@
1
+ import{readFile as e}from"node:fs/promises";import{constants as t,publicEncrypt as n}from"node:crypto";import{z as r}from"zod";var i=class e extends Error{code;statusCode;response;requestId;cause;retryable;constructor(t){super(t.message),Object.defineProperty(this,`name`,{value:`PesafyError`}),this.code=t.code,this.statusCode=t.statusCode,this.response=t.response,this.requestId=t.requestId,this.cause=t.cause,this.retryable=t.retryable??(t.code===`NETWORK_ERROR`||t.code===`TIMEOUT`||t.code===`RATE_LIMITED`||t.code===`REQUEST_FAILED`),Error.captureStackTrace&&Error.captureStackTrace(this,e)}get isValidation(){return this.code===`VALIDATION_ERROR`}get isAuth(){return this.code===`AUTH_FAILED`||this.code===`INVALID_CREDENTIALS`}toJSON(){return{name:this.name,code:this.code,message:this.message,statusCode:this.statusCode,requestId:this.requestId,retryable:this.retryable}}};function a(e){return new i(e)}function o(e){return e instanceof i}function s(e,t){return t?.idempotency?{...e,idempotency:t.idempotency}:e}const c=new Set([429,500,502,503,504]);function l(e){return new Promise(t=>setTimeout(t,e))}function u(e){let t=e*.25;return e+(Math.random()*t*2-t)}async function d(e,t){let n=t.retries??4,r=t.retryDelay??2e3,a=t.timeout??3e4,o={"Content-Type":`application/json`,Accept:`application/json`,...t.headers},s=t.idempotency,d=t.idempotencyKey;if(t.method===`POST`&&s?.enabled){d=s.reserve(d);let e=s.headerName;o[e]=d}else d&&(o[`Idempotency-Key`]=d);let f={method:t.method,headers:o,...t.body===void 0?{}:{body:JSON.stringify(t.body)}},p=null;for(let o=0;o<=n;o++){if(o>0){let i=u(r*2**(o-1));console.warn(`[pesafy] Retry ${o}/${n} → ${t.method} ${e} in ${Math.round(i)} ms`),await l(i)}let m=new AbortController,h=setTimeout(()=>m.abort(),a),g;try{g=await fetch(e,{...f,signal:m.signal})}catch(t){if(clearTimeout(h),p=t instanceof Error&&t.name===`AbortError`?new i({code:`TIMEOUT`,message:`Request to ${e} timed out after ${a} ms`,cause:t,retryable:!0}):new i({code:`NETWORK_ERROR`,message:`Network error: ${t instanceof Error?t.message:String(t)}`,cause:t,retryable:!0}),o<n)continue;throw d&&s?.enabled&&s.release(d),p}finally{clearTimeout(h)}let _=``,v=null,y=g.headers.get(`content-type`)??``;try{_=await g.text(),_&&(v=y.includes(`application/json`)?JSON.parse(_):_)}catch{v=_||null}let b={};if(g.headers.forEach((e,t)=>{b[t]=e}),g.ok)return d&&s?.enabled&&s.complete(d),{data:v,status:g.status,headers:b};let x=c.has(g.status),S=typeof v==`object`&&v?v:{},ee=S.errorMessage??S.ResponseDescription??S.resultDesc??_??`HTTP ${g.status}`;if(p=new i({code:x?`REQUEST_FAILED`:`API_ERROR`,message:ee,statusCode:g.status,response:v,retryable:x,...typeof S.requestId==`string`?{requestId:S.requestId}:{}}),!(x&&o<n))throw d&&s?.enabled&&s.release(d),p}throw d&&s?.enabled&&s.release(d),p}const f={INVALID_AUTH_TYPE:`400.008.01`,INVALID_GRANT_TYPE:`400.008.02`};var p=class{consumerKey;consumerSecret;baseUrl;cachedToken=null;tokenExpiresAt=0;constructor(e,t,n){this.consumerKey=e,this.consumerSecret=t,this.baseUrl=n}getBasicAuthHeader(){let e=`${this.consumerKey}:${this.consumerSecret}`;return`Basic ${Buffer.from(e,`utf-8`).toString(`base64`)}`}mapAuthError(e){if(e instanceof i){if(e.code===`AUTH_FAILED`)throw e;let t=e.response;if(t&&typeof t==`object`){let n=t.errorCode??t.error_code;if(n===f.INVALID_AUTH_TYPE)throw new i({code:`AUTH_FAILED`,message:`Invalid authentication type (400.008.01). Use Basic authentication: Authorization: Basic <Base64(consumerKey:consumerSecret)>.`,...e.statusCode!==void 0&&{statusCode:e.statusCode},response:e.response});if(n===f.INVALID_GRANT_TYPE)throw new i({code:`AUTH_FAILED`,message:`Invalid grant type (400.008.02). Set grant_type=client_credentials in the request query parameters.`,...e.statusCode!==void 0&&{statusCode:e.statusCode},response:e.response})}throw e}throw e}async getAccessToken(){let e=Date.now()/1e3;if(this.cachedToken&&this.tokenExpiresAt>e+60)return this.cachedToken;let t=`${this.baseUrl}/oauth/v1/generate?grant_type=client_credentials`;try{let n=await d(t,{method:`GET`,headers:{Authorization:this.getBasicAuthHeader()}}),{access_token:r,expires_in:a}=n.data;if(!r)throw new i({code:`AUTH_FAILED`,message:`Daraja did not return an access token. Verify your consumer key and consumer secret.`,response:n.data});return this.cachedToken=r,this.tokenExpiresAt=e+(a??3600),this.cachedToken}catch(e){return this.mapAuthError(e)}}clearCache(){this.cachedToken=null,this.tokenExpiresAt=0}};function m(e,r){try{let i=Buffer.from(e,`utf-8`);return n({key:r,padding:t.RSA_PKCS1_PADDING},i).toString(`base64`)}catch(e){throw new i({code:`ENCRYPTION_FAILED`,message:`Failed to encrypt security credential. Ensure the certificate PEM is valid and matches the environment (sandbox/production).`,cause:e})}}function h(e){let t=crypto.randomUUID();return e?`${e}-${t}`:t}function g(){return h(`pesafy`)}function _(){return crypto.randomUUID()}var v=class{entries=new Map;get(e){return this.entries.get(e)}set(e,t){this.entries.set(e,t)}delete(e){this.entries.delete(e)}prune(e){let t=Date.now()-e;for(let[e,n]of this.entries)n.createdAt<t&&this.entries.delete(e)}},y=class{enabled;headerName;ttlMs;store;generateKey;constructor(e={}){this.enabled=e.enabled!==!1,this.headerName=e.headerName??`Idempotency-Key`,this.ttlMs=e.ttlMs??864e5,this.store=e.store??new v,this.generateKey=e.generateKey??h}reserve(e){if(!this.enabled)return e??this.generateKey();this.pruneExpired();let t=e??this.generateKey(),n=this.store.get(t);if(n){if(Date.now()-n.createdAt<this.ttlMs)throw new i({code:`IDEMPOTENCY_ERROR`,message:`Duplicate request detected for idempotency key "${t}".`});this.store.delete(t)}return this.store.set(t,{key:t,createdAt:Date.now()}),t}complete(e){if(!this.enabled)return;let t=this.store.get(e);t&&this.store.set(e,{...t,completedAt:Date.now()})}release(e){this.enabled&&this.store.delete(e)}pruneExpired(){this.store instanceof v&&this.store.prune(this.ttlMs)}};function b(e){let t=Math.round(e);if(!Number.isFinite(t)||t<1)throw TypeError(`KesAmount must be a whole number ≥ 1, got ${e}`);return t}function x(e){let t=e.replace(/\D/g,``),n;if(t.startsWith(`254`)&&t.length===12)n=t;else if(t.startsWith(`0`)&&t.length===10)n=`254${t.slice(1)}`;else if(t.length===9)n=`254${t}`;else throw TypeError(`Cannot normalise "${e}" to 254XXXXXXXXX. Use 07XX…, 2547XX…, or +2547XX….`);if(n.length!==12)throw TypeError(`Phone "${e}" normalised to "${n}" — expected 12 digits.`);return n}function S(e){return String(e)}function ee(e){return String(e)}function te(e){return String(e)}function C(e){return{ok:!0,data:e}}function w(e){return{ok:!1,error:e}}function ne(e){if(!e.trim())throw TypeError(`String must not be empty`);return e}function re(e,t=`Request`){return new i({code:`VALIDATION_ERROR`,message:`${t} validation failed: ${e.issues.map(e=>`${e.path.join(`.`)}: ${e.message}`).join(`; `)}`,cause:e})}function T(e,t,n){let r=e.safeParse(t);if(!r.success)throw re(r.error,n);return r.data}const ie=r.enum([`sandbox`,`production`]),ae=r.string().min(10).regex(/^254\d{9}$/,`Must be Safaricom format 2547XXXXXXXX`),E=r.number().finite().positive().refine(e=>Math.round(e)>=1,{message:`amount must round to at least 1 KES`}),D=r.string().trim().min(1),O=r.string().url(),oe=r.object({errorMessage:r.string().optional(),ResponseDescription:r.string().optional(),resultDesc:r.string().optional(),requestId:r.string().optional()}).passthrough(),se=r.enum([`1`,`2`,`4`]),k=r.object({ConversationID:r.string().optional(),OriginatorConversationID:r.string().optional(),ResponseCode:r.string(),ResponseDescription:r.string()}).passthrough(),ce=r.object({transactionId:r.string().optional(),originalConversationId:r.string().optional(),partyA:D,identifierType:se,resultUrl:O,queueTimeOutUrl:O,commandId:r.literal(`TransactionStatusQuery`).optional(),remarks:r.string().optional(),occasion:r.string().optional()}).superRefine((e,t)=>{!e.transactionId?.trim()&&!e.originalConversationId?.trim()&&t.addIssue({code:`custom`,message:`Either transactionId (M-Pesa Receipt Number) or originalConversationId is required`,path:[`transactionId`]})}),le=k,ue=r.object({partyA:D,identifierType:se,resultUrl:O,queueTimeOutUrl:O,remarks:r.string().optional()}),de=k,fe=r.object({transactionId:D,receiverParty:D,receiverIdentifierType:r.literal(`11`).optional(),amount:E,resultUrl:O,queueTimeOutUrl:O,remarks:r.string().optional(),occasion:r.string().optional()}).superRefine((e,t)=>{e.receiverIdentifierType!==void 0&&e.receiverIdentifierType!==`11`&&t.addIssue({code:`custom`,message:`receiverIdentifierType must be "11" for the Reversals API`,path:[`receiverIdentifierType`]});let n=e.remarks??`Transaction Reversal`;(n.length<2||n.length>100)&&t.addIssue({code:`custom`,message:`remarks must be between 2 and 100 characters`,path:[`remarks`]})}),pe=k,me=r.object({amount:E,partyA:D,partyB:r.string().optional(),accountReference:D,resultUrl:O,queueTimeOutUrl:O,remarks:r.string().optional()}),he=k,ge=r.object({merchantName:D,refNo:D,amount:E,trxCode:r.enum([`BG`,`WA`,`PB`,`SM`,`SB`]),cpi:D,size:r.number().int().min(1).max(1e3).optional()}),_e=r.object({ResponseCode:r.string(),RequestID:r.string().optional(),ResponseDescription:r.string(),QRCode:r.string().optional()}).passthrough();async function ve(e,t,n,r,i,a){let o=T(ue,i,`Account Balance request`),c={Initiator:r,SecurityCredential:n,CommandID:`AccountBalance`,PartyA:String(o.partyA.trim()),IdentifierType:o.identifierType,ResultURL:o.resultUrl,QueueTimeOutURL:o.queueTimeOutUrl,Remarks:o.remarks??`Account Balance Query`},{data:l}=await d(`${e}/mpesa/accountbalance/v1/query`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:c},a));return T(de,l,`Account Balance response`)}const ye={DUPLICATE_DETECTED:15,INTERNAL_FAILURE:17,INITIATOR_CREDENTIAL_CHECK_FAILURE:18,MESSAGE_SEQUENCING_FAILURE:19,UNRESOLVED_INITIATOR:20,INITIATOR_TO_PRIMARY_PARTY_PERMISSION_FAILURE:21,INITIATOR_TO_RECEIVER_PARTY_PERMISSION_FAILURE:22,MISSING_MANDATORY_FIELDS:24,SYSTEM_OVERLOAD:100000001,THROTTLING_ERROR:100000002,INTERNAL_SERVER_ERROR:100000004,INVALID_INPUT_VALUE:100000005,SERVICE_ABNORMAL:100000007,API_STATUS_ABNORMAL:100000009,INSUFFICIENT_PERMISSIONS:100000010,REQUEST_RATE_EXCEEDED:100000011};function be(e){if(!e.trim())return[];let t=e.split(`|`),n=[];for(let e=0;e+2<t.length;e++){let r=t[e]?.trim(),i=t[e+1]?.trim(),a=t[e+2]?.trim();r&&i&&a!==void 0&&isNaN(Number(r))&&r.length>0&&n.push({name:r,currency:i,amount:a})}return n}function A(e,t){let n=e.Result.ResultParameters?.ResultParameter;if(n)return(Array.isArray(n)?n:[n]).find(e=>e.Key===t)?.Value}function xe(e){return e.Result.TransactionID}function Se(e){return e.Result.ConversationID}function Ce(e){return e.Result.OriginatorConversationID}function we(e){let t=A(e,`BOCompletedTime`);return t==null?null:String(t)}function Te(e){let t=A(e,`AccountBalance`);return t==null?null:String(t)}function Ee(e){let t=e.Result.ReferenceData;if(!t)return null;let n=t.ReferenceItem;return n?Array.isArray(n)?n[0]??null:n:null}function De(e){let t=e.Result.ResultCode;return t===0||t===`0`}const Oe=r.object({ConversationID:r.string(),OriginatorConversationID:r.string(),ResponseCode:r.string(),ResponseDescription:r.string()}).passthrough(),ke=r.object({amount:E,partyA:D,partyB:D,accountReference:D,requester:r.string().optional(),remarks:r.string().optional(),resultUrl:O,queueTimeOutUrl:O,occasion:r.string().optional()}),Ae=ke.extend({commandId:r.literal(`BusinessBuyGoods`)}),je=ke.extend({commandId:r.literal(`BusinessPayBill`)}),Me=Oe,Ne=Oe,Pe=r.object({primaryShortCode:D,receiverShortCode:D,amount:E,paymentRef:D,callbackUrl:O,partnerName:D,requestRefId:D.optional()}),Fe=r.object({code:r.string(),status:r.string()}).passthrough(),Ie=r.object({ConversationID:r.string().optional(),OriginatorConversationID:r.string().optional(),ResponseCode:r.string(),ResponseDescription:r.string()}).passthrough();async function Le(e,t,n,r){let i=T(Pe,n,`B2B Express Checkout request`),a=Math.round(i.amount),o={primaryShortCode:String(i.primaryShortCode),receiverShortCode:String(i.receiverShortCode),amount:String(a),paymentRef:i.paymentRef,callbackUrl:i.callbackUrl,partnerName:i.partnerName,RequestRefID:i.requestRefId??_()},{data:c}=await d(`${e}/v1/ussdpush/get-msisdn`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:o},r));return T(Fe,c,`B2B Express Checkout response`)}const j={SUCCESS:`0`,CANCELLED:`4001`,KYC_FAIL:`4102`,NO_NOMINATED_NUMBER:`4104`,USSD_NETWORK_ERROR:`4201`,USSD_EXCEPTION_ERROR:`4203`};new Set(Object.values(j));function Re(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.resultCode==`string`&&typeof t.requestId==`string`&&typeof t.amount==`string`}function M(e){return e.resultCode===j.SUCCESS}function ze(e){return e.resultCode===j.CANCELLED}function Be(e){return e.requestId}function Ve(e){return Number(e.amount)}function He(e){return M(e)?e.transactionId??null:null}function Ue(e){return M(e)?e.conversationID??null:null}async function N(e,t,n,r,i,a){let o=T(Ae,i,`B2B Buy Goods request`),c=Math.round(o.amount),l={Initiator:r,SecurityCredential:n,CommandID:o.commandId,SenderIdentifierType:`4`,RecieverIdentifierType:`4`,Amount:String(c),PartyA:String(o.partyA),PartyB:String(o.partyB),AccountReference:o.accountReference.slice(0,13),Remarks:o.remarks??`Business Buy Goods`,QueueTimeOutURL:o.queueTimeOutUrl,ResultURL:o.resultUrl};o.requester?.trim()&&(l.Requester=String(o.requester)),o.occasion?.trim()&&(l.Occassion=o.occasion);let{data:u}=await d(`${e}/mpesa/b2b/v1/paymentrequest`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:l},a));return T(Me,u,`B2B Buy Goods response`)}const We={SUCCESS:0,INSUFFICIENT_FUNDS:1,AMOUNT_TOO_SMALL:2,AMOUNT_TOO_LARGE:3,DAILY_LIMIT_EXCEEDED:4,MAX_BALANCE_EXCEEDED:8,INVALID_INITIATOR_INFO:2001,ACCOUNT_INACTIVE:2006,PRODUCT_NOT_PERMITTED:2028,CUSTOMER_NOT_REGISTERED:2040},Ge={INVALID_ACCESS_TOKEN:`400.003.01`,BAD_REQUEST:`400.003.02`,INTERNAL_SERVER_ERROR:`500.003.1001`,QUOTA_VIOLATION:`500.003.03`,SPIKE_ARREST:`500.003.02`,NOT_FOUND:`404.003.01`,INVALID_AUTH_HEADER:`404.001.04`,INVALID_PAYLOAD:`400.002.05`},Ke=new Set(Object.values(We));function qe(e){if(!e||typeof e!=`object`)return!1;let t=e;if(!t.Result||typeof t.Result!=`object`)return!1;let n=t.Result;return(typeof n.ResultCode==`number`||typeof n.ResultCode==`string`)&&typeof n.ConversationID==`string`&&typeof n.OriginatorConversationID==`string`}function Je(e){let t=e.Result.ResultCode;return t===0||t===`0`}function Ye(e){return!Je(e)}function Xe(e){if(typeof e!=`number`&&typeof e!=`string`||typeof e==`string`&&e.trim()===``)return!1;let t=Number(e);return Number.isFinite(t)&&Ke.has(t)}function Ze(e){return e.Result.TransactionID}function Qe(e){return e.Result.ConversationID}function $e(e){return e.Result.OriginatorConversationID}function et(e){return e.Result.ResultDesc}function tt(e){return e.Result.ResultCode}function nt(e){let t=P(e,`Amount`);if(t===void 0)return null;let n=Number(t);return Number.isFinite(n)?n:null}function rt(e){let t=P(e,`TransCompletedTime`)??P(e,`BOCompletedTime`);return t===void 0?null:String(t)}function it(e){let t=P(e,`ReceiverPartyPublicName`);return t===void 0?null:String(t)}function at(e){let t=P(e,`DebitPartyCharges`);return t===void 0||t===``?null:String(t)}function ot(e){let t=P(e,`Currency`);return t===void 0||t===``?`KES`:String(t)}function st(e){let t=P(e,`DebitPartyAffectedAccountBalance`);return t===void 0?null:String(t)}function ct(e){let t=P(e,`DebitAccountBalance`);return t===void 0?null:String(t)}function lt(e){let t=P(e,`InitiatorAccountCurrentBalance`);return t===void 0?null:String(t)}function ut(e){let t=e.Result.ReferenceData?.ReferenceItem;return t?(Array.isArray(t)?t:[t]).find(e=>e.Key===`BillReferenceNumber`)?.Value??null:null}function dt(e){let t=e.Result.ReferenceData?.ReferenceItem;return t?(Array.isArray(t)?t:[t]).find(e=>e.Key===`QueueTimeoutURL`)?.Value??null:null}function P(e,t){let n=e.Result.ResultParameters?.ResultParameter;if(n)return(Array.isArray(n)?n:[n]).find(e=>e.Key===t)?.Value}async function ft(e,t,n,r,i,a){let o=T(je,i,`B2B Pay Bill request`),c=Math.round(o.amount),l={Initiator:r,SecurityCredential:n,CommandID:o.commandId,SenderIdentifierType:`4`,RecieverIdentifierType:`4`,Amount:String(c),PartyA:String(o.partyA),PartyB:String(o.partyB),AccountReference:o.accountReference.slice(0,13),Remarks:o.remarks??`Business Pay Bill`,QueueTimeOutURL:o.queueTimeOutUrl,ResultURL:o.resultUrl};o.requester?.trim()&&(l.Requester=String(o.requester)),o.occasion?.trim()&&(l.Occassion=o.occasion);let{data:u}=await d(`${e}/mpesa/b2b/v1/paymentrequest`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:l},a));return T(Ne,u,`B2B Pay Bill response`)}const pt={SUCCESS:0,INSUFFICIENT_FUNDS:1,AMOUNT_TOO_SMALL:2,AMOUNT_TOO_LARGE:3,DAILY_LIMIT_EXCEEDED:4,MAX_BALANCE_EXCEEDED:8,INVALID_INITIATOR_INFO:2001,ACCOUNT_INACTIVE:2006,PRODUCT_NOT_PERMITTED:2028,CUSTOMER_NOT_REGISTERED:2040},mt={INVALID_ACCESS_TOKEN:`400.003.01`,BAD_REQUEST:`400.003.02`,INTERNAL_SERVER_ERROR:`500.003.1001`,QUOTA_VIOLATION:`500.003.03`,SPIKE_ARREST:`500.003.02`,NOT_FOUND:`404.003.01`,INVALID_AUTH_HEADER:`404.001.04`,INVALID_PAYLOAD:`400.002.05`},ht=new Set(Object.values(pt));function gt(e){if(!e||typeof e!=`object`)return!1;let t=e;if(!t.Result||typeof t.Result!=`object`)return!1;let n=t.Result;return(typeof n.ResultCode==`number`||typeof n.ResultCode==`string`)&&typeof n.ConversationID==`string`&&typeof n.OriginatorConversationID==`string`}function _t(e){let t=e.Result.ResultCode;return t===0||t===`0`}function vt(e){return!_t(e)}function yt(e){if(typeof e!=`number`&&typeof e!=`string`||typeof e==`string`&&e.trim()===``)return!1;let t=Number(e);return Number.isFinite(t)&&ht.has(t)}function bt(e){return e.Result.TransactionID}function xt(e){return e.Result.ConversationID}function St(e){return e.Result.OriginatorConversationID}function Ct(e){return e.Result.ResultDesc}function wt(e){return e.Result.ResultCode}function Tt(e){let t=F(e,`Amount`);if(t===void 0)return null;let n=Number(t);return Number.isFinite(n)?n:null}function Et(e){let t=F(e,`TransCompletedTime`)??F(e,`BOCompletedTime`);return t===void 0?null:String(t)}function Dt(e){let t=F(e,`ReceiverPartyPublicName`);return t===void 0?null:String(t)}function Ot(e){let t=F(e,`DebitPartyCharges`);return t===void 0||t===``?null:String(t)}function kt(e){let t=F(e,`Currency`);return t===void 0||t===``?`KES`:String(t)}function At(e){let t=F(e,`DebitPartyAffectedAccountBalance`);return t===void 0?null:String(t)}function jt(e){let t=F(e,`DebitAccountCurrentBalance`);return t===void 0?null:String(t)}function Mt(e){let t=F(e,`InitiatorAccountCurrentBalance`);return t===void 0?null:String(t)}function Nt(e){let t=e.Result.ReferenceData?.ReferenceItem;return t?(Array.isArray(t)?t:[t]).find(e=>e.Key===`BillReferenceNumber`)?.Value??null:null}function F(e,t){let n=e.Result.ResultParameters?.ResultParameter;if(n)return(Array.isArray(n)?n:[n]).find(e=>e.Key===t)?.Value}const Pt=r.object({ConversationID:r.string(),OriginatorConversationID:r.string(),ResponseCode:r.string(),ResponseDescription:r.string()}).passthrough(),Ft=r.object({commandId:r.literal(`BusinessPayToBulk`),amount:E,partyA:D,partyB:D,accountReference:D,requester:r.string().optional(),remarks:r.string().optional(),resultUrl:O,queueTimeOutUrl:O}),It=Pt,Lt=r.object({commandId:r.enum([`BusinessPayment`,`SalaryPayment`,`PromotionPayment`]),amount:r.number().finite().positive(),partyA:D,partyB:D,remarks:D,queueTimeOutUrl:O,resultUrl:O,originatorConversationId:D.optional(),occasion:r.string().optional()}),Rt=Pt;async function zt(e,t,n,r,i,a){let o=T(Ft,i,`B2C request`),c=Math.round(o.amount),l={Initiator:r,SecurityCredential:n,CommandID:o.commandId,SenderIdentifierType:`4`,RecieverIdentifierType:`4`,Amount:String(c),PartyA:String(o.partyA),PartyB:String(o.partyB),AccountReference:o.accountReference,Remarks:o.remarks??`B2C Account Top Up`,QueueTimeOutURL:o.queueTimeOutUrl,ResultURL:o.resultUrl};o.requester?.trim()&&(l.Requester=String(o.requester));let{data:u}=await d(`${e}/mpesa/b2b/v1/paymentrequest`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:l},a));return T(It,u,`B2C response`)}const Bt={INTERNAL_SERVER_ERROR:`500.003.1001`,INVALID_ACCESS_TOKEN:`400.003.01`,BAD_REQUEST:`400.003.02`,QUOTA_VIOLATION:`500.003.03`,SPIKE_ARREST:`500.003.02`,NOT_FOUND:`404.003.01`,INVALID_AUTH_HEADER:`404.001.04`,INVALID_PAYLOAD:`400.002.05`},Vt={SUCCESS:0,INVALID_INITIATOR:2001};function Ht(e){if(!e||typeof e!=`object`)return!1;let t=e;if(!t.Result||typeof t.Result!=`object`)return!1;let n=t.Result;return(typeof n.ResultCode==`number`||typeof n.ResultCode==`string`)&&typeof n.ConversationID==`string`&&typeof n.OriginatorConversationID==`string`}function Ut(e){let t=e.Result.ResultCode;return t===0||t===`0`}function Wt(e){return!Ut(e)}function Gt(e){if(typeof e!=`number`&&typeof e!=`string`||typeof e==`string`&&e.trim()===``)return!1;let t=Number(e);return Object.values(Vt).includes(t)}function Kt(e){return e.Result.TransactionID??null}function qt(e){return e.Result.ConversationID}function Jt(e){return e.Result.OriginatorConversationID}function Yt(e){return e.Result.ResultDesc}function Xt(e){let t=I(e,`Amount`);if(t===void 0)return null;let n=Number(t);return Number.isFinite(n)?n:null}function Zt(e){let t=I(e,`Currency`);return t===void 0||t===``?`KES`:String(t)}function Qt(e){let t=I(e,`ReceiverPartyPublicName`);return t===void 0?null:String(t)}function $t(e){let t=I(e,`TransactionCompletedTime`);return t===void 0?null:String(t)}function en(e){let t=I(e,`DebitAccountBalance`);return t===void 0?null:String(t)}function tn(e){let t=I(e,`DebitPartyCharges`);return t===void 0||t===``?null:String(t)}function I(e,t){let n=e.Result.ResultParameters?.ResultParameter;if(n)return(Array.isArray(n)?n:[n]).find(e=>e.Key===t)?.Value}const nn=new Set([`BusinessPayment`,`SalaryPayment`,`PromotionPayment`]);async function rn(e,t,n,r,i,o){let c=i.originatorConversationId?.trim()||g(),l=T(Lt,{...i,originatorConversationId:c},`B2C Disbursement request`);if(!l.commandId||!nn.has(l.commandId))throw a({code:`VALIDATION_ERROR`,message:`commandId must be one of: BusinessPayment, SalaryPayment, PromotionPayment. Got "${l.commandId}".`});let u=Math.round(l.amount);if(!Number.isFinite(u)||u<10)throw a({code:`VALIDATION_ERROR`,message:`amount must be ≥ 10 KES (got ${l.amount} which rounds to ${u}).`});if(!l.partyA?.trim())throw a({code:`VALIDATION_ERROR`,message:`partyA is required — the sending organisation shortcode.`});if(!l.partyB?.trim())throw a({code:`VALIDATION_ERROR`,message:`partyB is required — the receiving customer MSISDN (2547XXXXXXXX).`});if(!l.remarks?.trim())throw a({code:`VALIDATION_ERROR`,message:`remarks is required (2–100 characters).`});if(!l.resultUrl?.trim())throw a({code:`VALIDATION_ERROR`,message:`resultUrl is required — Safaricom POSTs the async result here.`});if(!l.queueTimeOutUrl?.trim())throw a({code:`VALIDATION_ERROR`,message:`queueTimeOutUrl is required — Safaricom calls this on request timeout.`});let f={OriginatorConversationID:c,InitiatorName:r,SecurityCredential:n,CommandID:l.commandId,Amount:u,PartyA:String(l.partyA),PartyB:String(l.partyB),Remarks:l.remarks,QueueTimeOutURL:l.queueTimeOutUrl,ResultURL:l.resultUrl};l.occasion?.trim()&&(f.Occassion=l.occasion);let{data:p}=await d(`${e}/mpesa/b2c/v3/paymentrequest`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:f},o));return T(Rt,p,`B2C Disbursement response`)}const L={SUCCESS:0,INSUFFICIENT_BALANCE:1,AMOUNT_TOO_SMALL:2,AMOUNT_TOO_LARGE:3,DAILY_LIMIT_EXCEEDED:4,MAX_BALANCE_EXCEEDED:8,DEBIT_PARTY_INVALID:11,INITIATOR_NOT_ALLOWED:21,INVALID_INITIATOR_INFO:2001,ACCOUNT_INACTIVE:2006,PRODUCT_NOT_PERMITTED:2028,CUSTOMER_NOT_REGISTERED:2040,SECURITY_CREDENTIAL_LOCKED:8006,OPERATOR_DOES_NOT_EXIST:`SFC_IC0003`};function an(e){if(!e||typeof e!=`object`)return!1;let t=e;if(!t.Result||typeof t.Result!=`object`)return!1;let n=t.Result;return(typeof n.ResultCode==`number`||typeof n.ResultCode==`string`)&&typeof n.ConversationID==`string`&&typeof n.OriginatorConversationID==`string`}function on(e){let t=e.Result.ResultCode;return t===0||t===`0`}function sn(e){return!on(e)}function cn(e){if(e==null||typeof e!=`number`&&typeof e!=`string`)return!1;if(typeof e==`string`&&e===L.OPERATOR_DOES_NOT_EXIST)return!0;if(typeof e==`string`&&e.trim()===``)return!1;let t=Number(e);return Object.values(L).filter(e=>typeof e==`number`).includes(t)}function ln(e){return e.Result.TransactionID??null}function un(e){return e.Result.ConversationID}function dn(e){return e.Result.OriginatorConversationID}function fn(e){return e.Result.ResultDesc}function pn(e){return e.Result.ResultCode}function R(e,t){let n=e.Result.ResultParameters?.ResultParameter;if(n)return(Array.isArray(n)?n:[n]).find(e=>e.Key===t)?.Value}function mn(e){let t=R(e,`TransactionAmount`);if(t===void 0)return null;let n=Number(t);return Number.isFinite(n)?n:null}function hn(e){let t=R(e,`TransactionReceipt`);return t===void 0?null:String(t)}function gn(e){let t=R(e,`ReceiverPartyPublicName`);return t===void 0?null:String(t)}function _n(e){let t=R(e,`TransactionCompletedDateTime`);return t===void 0?null:String(t)}function vn(e){let t=R(e,`B2CUtilityAccountAvailableFunds`);if(t===void 0)return null;let n=Number(t);return Number.isFinite(n)?n:null}function yn(e){let t=R(e,`B2CWorkingAccountAvailableFunds`);if(t===void 0)return null;let n=Number(t);return Number.isFinite(n)?n:null}function bn(e){let t=R(e,`B2CRecipientIsRegisteredCustomer`);return t===void 0?null:String(t).toUpperCase()===`Y`}const xn=r.enum([`0`,`1`]),z=r.object({shortcode:D,email:D,officialContact:D,sendReminders:xn,logo:r.string().optional(),callbackUrl:O}),Sn=r.object({app_key:r.string().optional(),resmsg:r.string(),rescode:r.string()}).passthrough(),Cn=z,wn=r.object({resmsg:r.string(),rescode:r.string()}).passthrough(),Tn=r.object({itemName:D,amount:E}),B=r.object({externalReference:D,billedFullName:D,billedPhoneNumber:D,billedPeriod:D,invoiceName:D,dueDate:D,accountReference:D,amount:E,invoiceItems:r.array(Tn).optional()}),En=r.object({Status_Message:r.string().optional(),resmsg:r.string(),rescode:r.string()}).passthrough(),Dn=r.object({invoices:r.array(B).min(1).max(1e3)}),On=r.object({Status_Message:r.string().optional(),resmsg:r.string(),rescode:r.string()}).passthrough(),kn=r.object({externalReference:D}),An=r.object({Status_Message:r.string().optional(),resmsg:r.string(),rescode:r.string(),errors:r.array(r.unknown()).optional()}).passthrough(),jn=r.object({externalReferences:r.array(D).min(1)}),Mn=r.object({Status_Message:r.string().optional(),resmsg:r.string(),rescode:r.string(),errors:r.array(r.unknown()).optional()}).passthrough(),Nn=r.object({paymentDate:D,paidAmount:D,accountReference:D,transactionId:D,phoneNumber:D,fullName:D,invoiceName:D,externalReference:D}),Pn=r.object({resmsg:r.string(),rescode:r.string()}).passthrough();async function Fn(e,t,n,r){let i=T(z,n,`Bill Manager opt-in request`),a={shortcode:i.shortcode,email:i.email,officialContact:i.officialContact,sendReminders:i.sendReminders,logo:i.logo??``,callbackurl:i.callbackUrl},{data:o}=await d(`${e}/v1/billmanager-invoice/optin`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:a},r));return T(Sn,o,`Bill Manager opt-in response`)}async function In(e,t,n,r){let i=T(Cn,n,`Bill Manager update opt-in request`),a={shortcode:i.shortcode,email:i.email,officialContact:i.officialContact,sendReminders:i.sendReminders,logo:i.logo??``,callbackurl:i.callbackUrl},{data:o}=await d(`${e}/v1/billmanager-invoice/change-optin-details`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:a},r));return T(wn,o,`Bill Manager update opt-in response`)}async function Ln(e,t,n,r){let i=T(B,n,`Bill Manager single invoice request`),a=Math.round(i.amount),o={externalReference:i.externalReference,billedFullName:i.billedFullName,billedPhoneNumber:i.billedPhoneNumber,billedPeriod:i.billedPeriod,invoiceName:i.invoiceName,dueDate:i.dueDate,accountReference:i.accountReference,amount:String(a),invoiceItems:i.invoiceItems?.map(e=>({itemName:e.itemName,amount:String(Math.round(e.amount))}))??[]},{data:c}=await d(`${e}/v1/billmanager-invoice/single-invoicing`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:o},r));return T(En,c,`Bill Manager single invoice response`)}async function V(e,t,n,r){let i=T(Dn,n,`Bill Manager bulk invoice request`).invoices.map(e=>({externalReference:e.externalReference,billedFullName:e.billedFullName,billedPhoneNumber:e.billedPhoneNumber,billedPeriod:e.billedPeriod,invoiceName:e.invoiceName,dueDate:e.dueDate,accountReference:e.accountReference,amount:String(Math.round(e.amount)),invoiceItems:e.invoiceItems?.map(e=>({itemName:e.itemName,amount:String(Math.round(e.amount))}))??[]})),{data:a}=await d(`${e}/v1/billmanager-invoice/bulk-invoicing`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:i},r));return T(On,a,`Bill Manager bulk invoice response`)}async function Rn(e,t,n,r){let i=T(kn,n,`Bill Manager cancel invoice request`),{data:a}=await d(`${e}/v1/billmanager-invoice/cancel-single-invoice`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:{externalReference:i.externalReference}},r));return T(An,a,`Bill Manager cancel invoice response`)}async function zn(e,t,n,r){let i=T(jn,n,`Bill Manager cancel bulk invoices request`).externalReferences.map(e=>({externalReference:e})),{data:a}=await d(`${e}/v1/billmanager-invoice/cancel-bulk-invoices`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:i},r));return T(Mn,a,`Bill Manager cancel bulk invoices response`)}async function Bn(e,t,n,r){let i=T(Nn,n,`Bill Manager reconciliation request`),a={paymentDate:i.paymentDate,paidAmount:i.paidAmount,accountReference:i.accountReference,transactionId:i.transactionId,phoneNumber:i.phoneNumber,fullName:i.fullName,invoiceName:i.invoiceName,externalReference:i.externalReference},{data:o}=await d(`${e}/v1/billmanager-invoice/reconciliation`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:a},r));return T(Pn,o,`Bill Manager reconciliation response`)}const Vn=r.object({shortCode:D,responseType:r.enum([`Completed`,`Cancelled`]),confirmationUrl:O,validationUrl:O,apiVersion:r.enum([`v1`,`v2`]).optional()}),H=r.object({OriginatorCoversationID:r.string(),ResponseCode:r.string(),ResponseDescription:r.string()}).passthrough(),Hn=H,Un=H,Wn=r.object({shortCode:r.union([D,r.number()]),commandId:r.enum([`CustomerPayBillOnline`,`CustomerBuyGoodsOnline`]),amount:E,msisdn:r.union([D,r.number()]),billRefNumber:r.union([D,r.null()]).optional(),apiVersion:r.enum([`v1`,`v2`]).optional()}).superRefine((e,t)=>{e.commandId===`CustomerPayBillOnline`&&!e.billRefNumber?.trim()&&t.addIssue({code:`custom`,message:`billRefNumber is required for CustomerPayBillOnline`,path:[`billRefNumber`]})}),Gn=r.object({TransactionType:r.string(),TransID:r.string(),TransTime:r.string(),TransAmount:r.union([r.string(),r.number()]),BusinessShortCode:r.string(),BillRefNumber:r.string().optional(),MSISDN:r.string()}).passthrough(),Kn=[`mpesa`,`safaricom`,`exec`,`exe`,`cme`,`cmd`,`sql`,`query`];function qn(e,t){if(!e||!e.trim())throw a({code:`VALIDATION_ERROR`,message:`${t} is required`});let n=e.toLowerCase();for(let e of Kn)if(n.includes(e))throw a({code:`VALIDATION_ERROR`,message:`${t} must not contain the keyword "${e}". Daraja rejects URLs containing: mpesa, safaricom, exe, exec, cme (and variants: cmd, sql, query).`})}async function Jn(e,t,n,r){let i=T(Vn,n,`C2B Register URL request`);qn(i.confirmationUrl,`confirmationUrl`),qn(i.validationUrl,`validationUrl`);let a=i.apiVersion??`v2`,o={ShortCode:String(i.shortCode),ResponseType:i.responseType,ConfirmationURL:i.confirmationUrl,ValidationURL:i.validationUrl},{data:c}=await d(`${e}/mpesa/c2b/${a}/registerurl`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:o},r));return T(Hn,c,`C2B Register URL response`)}async function Yn(e,t,n,r){let i=T(Wn,n,`C2B Simulate request`);if(!e.includes(`sandbox`))throw a({code:`VALIDATION_ERROR`,message:`C2B simulate is only available in the Sandbox environment (per Daraja docs). In production, customers initiate payments directly via M-PESA App, USSD, or SIM Toolkit.`});let o=Math.round(i.amount),c=i.commandId===`CustomerBuyGoodsOnline`,l=i.apiVersion??`v2`,u={ShortCode:Number(i.shortCode),CommandID:i.commandId,Amount:o,Msisdn:Number(i.msisdn)};c||(u.BillRefNumber=i.billRefNumber.trim());let{data:f}=await d(`${e}/mpesa/c2b/${l}/simulate`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:u},r));return T(Un,f,`C2B Simulate response`)}const Xn={INTERNAL_SERVER_ERROR:`500.003.1001`,INVALID_ACCESS_TOKEN:`400.003.01`,BAD_REQUEST:`400.003.02`,QUOTA_VIOLATION:`500.003.03`,SPIKE_ARREST:`500.003.02`,RESOURCE_NOT_FOUND:`404.003.01`,INVALID_AUTH_HEADER:`404.001.04`,INVALID_REQUEST_PAYLOAD:`400.002.05`},Zn={ACCEPT:`0`,INVALID_MSISDN:`C2B00011`,INVALID_ACCOUNT_NUMBER:`C2B00012`,INVALID_AMOUNT:`C2B00013`,INVALID_KYC_DETAILS:`C2B00014`,INVALID_SHORTCODE:`C2B00015`,OTHER_ERROR:`C2B00016`};function Qn(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.TransID==`string`&&typeof t.BusinessShortCode==`string`&&typeof t.TransAmount==`string`}function $n(e){return{ResultCode:`0`,ResultDesc:`Accepted`,...e?{ThirdPartyTransID:e}:{}}}function er(e=`C2B00016`){return{ResultCode:e,ResultDesc:`Rejected`}}function tr(){return{ResultCode:0,ResultDesc:`Success`}}function nr(e){return Number(e.TransAmount)}function rr(e){return e.TransID}function ir(e){return e.BillRefNumber}function ar(e){return[e.FirstName,e.MiddleName,e.LastName].filter(Boolean).join(` `).trim()}function or(e){return e.TransactionType===`Pay Bill`}function sr(e){return e.TransactionType===`Buy Goods`}const U=[`BG`,`WA`,`PB`,`SM`,`SB`],cr=1,lr=1e3,ur=1,dr=300;function fr(e){return typeof e!=`string`||e.trim().length===0?`merchantName is required and must be a non-empty string`:null}function pr(e){return typeof e!=`string`||e.trim().length===0?`refNo (transaction reference) is required and must be a non-empty string`:null}function mr(e){return typeof e!=`number`||!Number.isFinite(e)?`amount must be a finite number`:Math.round(e)<1?`amount must be at least 1 KES (got ${e})`:null}function hr(e){return U.includes(e)?null:`trxCode must be one of: ${U.join(`, `)} (BG=Buy Goods, WA=Withdraw Cash, PB=Paybill, SM=Send Money, SB=Send to Business)`}function gr(e){return typeof e!=`string`||e.trim().length===0?`cpi (Credit Party Identifier) is required and must be a non-empty string`:null}function _r(e){return e==null?null:typeof e!=`number`||!Number.isFinite(e)?`size must be a finite number when provided`:!Number.isInteger(e)||e<1?`size must be a positive integer (minimum 1)`:e>1e3?`size must not exceed ${lr} pixels (got ${e})`:null}function vr(e){if(typeof e!=`object`||!e)return{valid:!1,errors:{payload:`request payload must be a non-null object`}};let t=e,n={},r=fr(t.merchantName);r&&(n.merchantName=r);let i=pr(t.refNo);i&&(n.refNo=i);let a=mr(t.amount);a&&(n.amount=a);let o=hr(t.trxCode);o&&(n.trxCode=o);let s=gr(t.cpi);s&&(n.cpi=s);let c=_r(t.size);return c&&(n.size=c),Object.keys(n).length>0?{valid:!1,errors:n}:{valid:!0}}function yr(e,t){switch(e){case`404.001.04`:return new i({code:`AUTH_FAILED`,message:`Daraja rejected the request due to an invalid authentication header. Ensure the Dynamic QR endpoint is called with POST and that the Authorization: Bearer <token> header is present. Daraja: "${t}"`,statusCode:404});case`400.003.01`:return new i({code:`AUTH_FAILED`,message:`The M-PESA access token is invalid or has expired. Call clearTokenCache() on the Mpesa instance to force a token refresh and retry the request. Daraja: "${t}"`,statusCode:401});case`400.002.05`:return new i({code:`VALIDATION_ERROR`,message:`Daraja rejected the request payload as malformed. Verify that all required fields (MerchantName, RefNo, Amount, TrxCode, CPI, Size) are present and have correct types. Daraja: "${t}"`,statusCode:400});default:return new i({code:`REQUEST_FAILED`,message:`Dynamic QR request failed (${e}): ${t}`,statusCode:400})}}function br(e){return typeof e==`object`&&!!e&&`errorCode`in e&&typeof e.errorCode==`string`}function xr(e){return typeof e==`object`&&!!e&&`ResponseCode`in e&&`QRCode`in e&&typeof e.QRCode==`string`&&e.QRCode.length>0}async function Sr(e,t,n,r){let a=T(ge,n,`Dynamic QR request`);if(!t||typeof t!=`string`||t.trim().length===0)throw new i({code:`AUTH_FAILED`,message:`accessToken is required. Obtain one via the Daraja Authorization API (GET /oauth/v1/generate?grant_type=client_credentials).`});let o=a.size??300,c=Math.round(a.amount),l={MerchantName:a.merchantName.trim(),RefNo:a.refNo.trim(),Amount:c,TrxCode:a.trxCode,CPI:a.cpi.trim(),Size:String(o)},{data:u}=await d(`${e}/mpesa/qrcode/v1/generate`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:l},r));if(br(u))throw yr(u.errorCode,u.errorMessage);if(!xr(u))throw new i({code:`REQUEST_FAILED`,message:`Daraja returned an unexpected response structure for the Dynamic QR request. The response was missing required fields (ResponseCode, QRCode). Raw response: ${JSON.stringify(u).slice(0,300)}`});return T(_e,u,`Dynamic QR response`)}const Cr=`TransactionReversal`,wr=`11`,W={SUCCESS:0,INSUFFICIENT_BALANCE:1,DEBIT_PARTY_INVALID_STATE:11,INITIATOR_NOT_ALLOWED:21,INITIATOR_INFORMATION_INVALID:2001,DECLINED_ACCOUNT_RULE:2006,NOT_PERMITTED:2028,SECURITY_CREDENTIAL_LOCKED:8006,ALREADY_REVERSED:`R000001`,INVALID_TRANSACTION_ID:`R000002`},Tr={INVALID_ACCESS_TOKEN:`404.001.03`,BAD_REQUEST:`400.002.02`,RESOURCE_NOT_FOUND:`404.001.01`,INTERNAL_SERVER_ERROR:`500.001.1001`,SPIKE_ARREST:`500.003.02`,QUOTA_VIOLATION:`500.003.03`};function Er(e){if(!e||typeof e!=`object`)return!1;let t=e;if(!t.Result||typeof t.Result!=`object`)return!1;let n=t.Result;return n.ResultCode!==void 0&&typeof n.ResultDesc==`string`&&typeof n.ConversationID==`string`}function Dr(e){return e.Result.ResultCode===W.SUCCESS}function Or(e){return!Dr(e)}function kr(e){return Object.values(W).includes(e)}function Ar(e){return e.Result.TransactionID??null}function jr(e){return e.Result.ConversationID}function Mr(e){return e.Result.OriginatorConversationID}function Nr(e){return e.Result.ResultCode}function Pr(e){return e.Result.ResultDesc}function G(e,t){let n=e.Result.ResultParameters?.ResultParameter;if(n)return n.find(e=>e.Key===t)?.Value}function Fr(e){let t=G(e,`Amount`);return t===void 0?void 0:Number(t)}function Ir(e){let t=G(e,`OriginalTransactionID`);return t===void 0?void 0:String(t)}function Lr(e){let t=G(e,`CreditPartyPublicName`);return t===void 0?void 0:String(t)}function Rr(e){let t=G(e,`DebitPartyPublicName`);return t===void 0?void 0:String(t)}function zr(e){let t=G(e,`DebitAccountBalance`);return t===void 0?void 0:String(t)}function Br(e){let t=G(e,`TransCompletedTime`);return t===void 0?void 0:Number(t)}function Vr(e){let t=G(e,`Charge`);return t===void 0?void 0:Number(t)}async function Hr(e,t,n,r,i,a){let o=T(fe,i,`Reversal request`),c=Math.round(o.amount),l=o.remarks??`Transaction Reversal`,u={Initiator:r,SecurityCredential:n,CommandID:Cr,TransactionID:o.transactionId,Amount:String(c),ReceiverParty:String(o.receiverParty),RecieverIdentifierType:`11`,ResultURL:o.resultUrl,QueueTimeOutURL:o.queueTimeOutUrl,Remarks:l};o.occasion!==void 0&&o.occasion!==null&&(u.Occasion=o.occasion);let{data:f}=await d(`${e}/mpesa/reversal/v1/request`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:u},a));return T(pe,f,`Reversal response`)}const Ur=r.enum([`CustomerPayBillOnline`,`CustomerBuyGoodsOnline`]),Wr=r.object({amount:r.number().finite({message:`amount must be a finite number (not NaN or Infinity)`}),phoneNumber:D,shortCode:D,passKey:D,callbackUrl:O,accountReference:D,transactionDesc:D,transactionType:Ur.optional(),partyB:r.string().optional()}),Gr=r.object({MerchantRequestID:r.string(),CheckoutRequestID:r.string(),ResponseCode:r.string(),ResponseDescription:r.string(),CustomerMessage:r.string().optional()}).passthrough(),Kr=r.object({checkoutRequestId:D,shortCode:D,passKey:D}),qr=r.object({ResponseCode:r.string(),ResponseDescription:r.string(),MerchantRequestID:r.string().optional(),CheckoutRequestID:r.string().optional(),ResultCode:r.union([r.string(),r.number()]).optional(),ResultDesc:r.string().optional()}).passthrough(),Jr=r.object({Body:r.object({stkCallback:r.object({MerchantRequestID:r.string(),CheckoutRequestID:r.string(),ResultCode:r.number(),ResultDesc:r.string(),CallbackMetadata:r.object({Item:r.array(r.object({Name:r.string(),Value:r.union([r.string(),r.number()])}))}).optional()}).passthrough()})}),K={MIN_AMOUNT:1,MAX_AMOUNT:25e4},q={SUCCESS:0,INSUFFICIENT_BALANCE:1,CANCELLED_BY_USER:1032,PHONE_UNREACHABLE:1037,INVALID_PIN:2001};function Yr(e){return Object.values(q).includes(e)}function Xr(e){return e.ResultCode===q.SUCCESS}function Zr(e,t){let n=e.Body.stkCallback;if(Xr(n))return n.CallbackMetadata.Item.find(e=>e.Name===t)?.Value}function J(e){let t=e.replace(/\D/g,``),n;if(t.startsWith(`254`)&&t.length===12)n=t;else if(t.startsWith(`0`)&&t.length===10)n=`254${t.slice(1)}`;else if(t.length===9)n=`254${t}`;else throw new i({code:`INVALID_PHONE`,message:`Cannot parse "${e}". Use 07XXXXXXXX, 2547XXXXXXXX, 2541XXXXXXXX (Airtel), or +2547XXXXXXXX.`});if(n.length!==12)throw new i({code:`INVALID_PHONE`,message:`"${e}" normalised to "${n}" — expected 12 digits.`});return n}function Qr(e,t,n){return btoa(`${e}${t}${n}`)}function Y(){let e=new Date,t=e=>e.toString().padStart(2,`0`);return[e.getFullYear(),t(e.getMonth()+1),t(e.getDate()),t(e.getHours()),t(e.getMinutes()),t(e.getSeconds())].join(``)}async function $r(e,t,n,r){let a=T(Wr,n,`STK Push request`);if(!Number.isFinite(a.amount))throw new i({code:`VALIDATION_ERROR`,message:`amount must be a finite number (got ${a.amount}).`});let o=Math.round(a.amount);if(o<K.MIN_AMOUNT)throw new i({code:`VALIDATION_ERROR`,message:`Amount must be at least KES ${K.MIN_AMOUNT} (got ${a.amount} which rounds to ${o}).`});if(o>K.MAX_AMOUNT)throw new i({code:`VALIDATION_ERROR`,message:`Amount must not exceed KES ${K.MAX_AMOUNT.toLocaleString()} per transaction as per Safaricom Daraja limits (got ${a.amount} which rounds to ${o}).`});let c=Y(),l=a.partyB??a.shortCode,u={BusinessShortCode:a.shortCode,Password:Qr(a.shortCode,a.passKey,c),Timestamp:c,TransactionType:a.transactionType??`CustomerPayBillOnline`,Amount:o,PartyA:J(a.phoneNumber),PartyB:l,PhoneNumber:J(a.phoneNumber),CallBackURL:a.callbackUrl,AccountReference:a.accountReference.slice(0,12),TransactionDesc:a.transactionDesc.slice(0,13)},{data:f}=await d(`${e}/mpesa/stkpush/v1/processrequest`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:u,retries:5,retryDelay:3e3},r));return T(Gr,f,`STK Push response`)}async function ei(e,t,n,r){let i=T(Kr,n,`STK Query request`),a=Y(),o={BusinessShortCode:i.shortCode,Password:Qr(i.shortCode,i.passKey,a),Timestamp:a,CheckoutRequestID:i.checkoutRequestId},{data:c}=await d(`${e}/mpesa/stkpushquery/v1/query`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:o},r));return T(qr,c,`STK Query response`)}const ti=`572572`,ni=`PayTaxToKRA`;async function ri(e,t,n,r,i,a){let o=T(me,i,`Tax Remittance request`),c=Math.round(o.amount),l={Initiator:r,SecurityCredential:n,CommandID:ni,SenderIdentifierType:`4`,RecieverIdentifierType:`4`,Amount:String(c),PartyA:String(o.partyA),PartyB:o.partyB??`572572`,AccountReference:o.accountReference,Remarks:o.remarks??`Tax Remittance`,QueueTimeOutURL:o.queueTimeOutUrl,ResultURL:o.resultUrl},{data:u}=await d(`${e}/mpesa/b2b/v1/remittax`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:l},a));return T(he,u,`Tax Remittance response`)}function ii(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function ai(e){return typeof e==`string`?Number(e):e}function oi(e){if(!ii(e))return!1;let t=e;if(!ii(t.Result))return!1;let n=t.Result;return n.ResultCode!==void 0&&n.ResultCode!==null&&typeof n.ConversationID==`string`&&typeof n.OriginatorConversationID==`string`}function si(e){return ai(e.Result.ResultCode)===0}function ci(e){return!si(e)}function X(e,t){let n=e.Result.ResultParameters?.ResultParameter;if(n==null)return;if(Array.isArray(n))return n.find(e=>e.Key===t)?.Value;let r=n;return r.Key===t?r.Value:void 0}function li(e){return e.Result.ResultCode}function ui(e){return e.Result.ResultDesc}function di(e){return e.Result.TransactionID}function fi(e){return e.Result.ConversationID}function pi(e){return e.Result.OriginatorConversationID}function mi(e){let t=X(e,`Amount`);if(t==null)return null;let n=typeof t==`number`?t:parseFloat(String(t));return Number.isNaN(n)?null:n}function hi(e){let t=X(e,`TransactionCompletedTime`);return t===void 0?null:String(t)}function gi(e){let t=X(e,`ReceiverPartyPublicName`);return t===void 0?null:String(t)}async function _i(e,t,n,r,i,a){let o=T(ce,i,`Transaction Status request`),c={Initiator:r,SecurityCredential:n,CommandID:o.commandId??`TransactionStatusQuery`,TransactionID:o.transactionId??``,OriginalConversationID:o.originalConversationId??``,PartyA:o.partyA,IdentifierType:o.identifierType,ResultURL:o.resultUrl,QueueTimeOutURL:o.queueTimeOutUrl,Remarks:o.remarks??`Transaction Status Query`,Occasion:o.occasion??``},{data:l}=await d(`${e}/mpesa/transactionstatus/v1/query`,s({method:`POST`,headers:{Authorization:`Bearer ${t}`},body:c},a));return T(le,l,`Transaction Status response`)}const vi={INVALID_ACCESS_TOKEN:`400.003.01`,BAD_REQUEST:`400.003.02`,INTERNAL_SERVER_ERROR:`500.003.1001`,QUOTA_VIOLATION:`500.003.03`,SPIKE_ARREST:`500.003.02`,NOT_FOUND:`404.003.01`,INVALID_AUTH_HEADER:`404.001.04`,INVALID_PAYLOAD:`400.002.05`},yi={SUCCESS:0,INVALID_INITIATOR:2001},bi=new Set(Object.values(yi));function xi(e){if(!e||typeof e!=`object`)return!1;let t=e;if(!t.Result||typeof t.Result!=`object`)return!1;let n=t.Result;return(typeof n.ResultCode==`number`||typeof n.ResultCode==`string`)&&typeof n.ConversationID==`string`&&typeof n.OriginatorConversationID==`string`}function Si(e){let t=e.Result.ResultCode;return t===0||t===`0`}function Ci(e){return!Si(e)}function wi(e){if(typeof e!=`number`&&typeof e!=`string`||typeof e==`string`&&e.trim()===``)return!1;let t=Number(e);return Number.isFinite(t)&&bi.has(t)}function Ti(e){return e.Result.TransactionID}function Ei(e){return e.Result.ConversationID}function Di(e){return e.Result.OriginatorConversationID}function Oi(e){return e.Result.ResultDesc}function ki(e){return e.Result.ResultCode}function Ai(e){let t=Z(e,`Amount`);if(t===void 0)return null;let n=Number(t);return Number.isFinite(n)?n:null}function ji(e){let t=Z(e,`ReceiptNo`);return t===void 0?null:String(t)}function Mi(e){let t=Z(e,`TransactionStatus`);return t===void 0?null:String(t)}function Ni(e){let t=Z(e,`DebitPartyName`);return t===void 0?null:String(t)}function Pi(e){let t=Z(e,`CreditPartyName`);return t===void 0?null:String(t)}function Fi(e){let t=Z(e,`DebitAccountBalance`);return t===void 0?null:String(t)}function Ii(e){let t=Z(e,`TransactionDate`);return t===void 0?null:String(t)}function Z(e,t){let n=e.Result.ResultParameters?.ResultParameter;if(n)return(Array.isArray(n)?n:[n]).find(e=>e.Key===t)?.Value}const Li={sandbox:`https://sandbox.safaricom.co.ke`,production:`https://api.safaricom.co.ke`},Ri={maxRetries:1/0,initialDelay:1e3,maxDelay:36e5,backoffMultiplier:2,maxRetryDuration:720*60*60*1e3};async function zi(e,t={}){let n={...Ri,...t},r=n.initialDelay,i=0,a=Date.now();for(;i<=n.maxRetries;){if(i++,Date.now()-a>n.maxRetryDuration)return{success:!1,attempts:i,error:Error(`Max retry duration exceeded`)};try{return{success:!0,data:await e(),attempts:i}}catch(e){let t=e instanceof Error?e:Error(String(e));if(t.message.includes(`4`))return{success:!1,attempts:i,error:t};i<=n.maxRetries&&(await new Promise(e=>setTimeout(e,r)),r=Math.min(r*n.backoffMultiplier,n.maxDelay))}}return{success:!1,attempts:i,error:Error(`Max retries exceeded`)}}const Bi={sha256:`SHA-256`,sha512:`SHA-512`};function Vi(e){let t=e.trim();if(!/^[0-9a-fA-F]+$/.test(t)||t.length%2!=0)return null;let n=new Uint8Array(t.length/2);for(let e=0;e<n.length;e++)n[e]=Number.parseInt(t.slice(e*2,e*2+2),16);return n}function Hi(e){return[...new Uint8Array(e)].map(e=>e.toString(16).padStart(2,`0`)).join(``)}function Ui(e,t){if(e.length!==t.length)return!1;let n=0;for(let r=0;r<e.length;r++)n|=e[r]^t[r];return n===0}async function Wi(e,t,n,r=`sha256`){if(!n||!t)return!1;let i=globalThis.crypto?.subtle;if(!i)return!1;let a=typeof e==`string`?new TextEncoder().encode(e):e instanceof Uint8Array?e:new Uint8Array(e),o=Vi(t);if(!o)return!1;try{let e=await i.importKey(`raw`,new TextEncoder().encode(n),{name:`HMAC`,hash:Bi[r]},!1,[`sign`]),t=Vi(Hi(await i.sign(`HMAC`,e,a)));return t?Ui(o,t):!1}catch{return!1}}const Q=[`196.201.214.200`,`196.201.214.206`,`196.201.213.114`,`196.201.214.207`,`196.201.214.208`,`196.201.213.44`,`196.201.212.127`,`196.201.212.138`,`196.201.212.129`,`196.201.212.136`,`196.201.212.74`,`196.201.212.69`];function $(e,t=Q){return t.includes(e)}function Gi(e){return Jr.safeParse(e).success?e:null}async function Ki(e){let t=[],n=e.allowedIPs??Q,r=e.skipIPCheck===!0||$(e.requestIP,n);r||t.push(`Request IP is not in the Safaricom allowlist.`);let i=!0;return e.secret&&e.signature&&e.rawBody!==void 0?(i=await Wi(e.rawBody,e.signature,e.secret,e.hmacAlgorithm),i||t.push(`Webhook HMAC signature verification failed.`)):e.requireHMAC&&(i=!1,t.push(`HMAC verification required but secret, signature, or rawBody missing.`)),{valid:r&&i,ipValid:r,hmacValid:i,errors:t}}function qi(e,t={}){if(!t.skipIPCheck&&t.requestIP&&!$(t.requestIP,t.allowedIPs))return{success:!1,eventType:null,data:null,error:`IP address ${t.requestIP} is not in the Safaricom whitelist`};let n=Gi(e);return n?{success:!0,eventType:`stk_push`,data:n}:{success:!1,eventType:null,data:null,error:`Unknown or malformed webhook payload`}}function Ji(e){let t=(e.Body?.stkCallback?.CallbackMetadata?.Item)?.find(e=>e.Name===`MpesaReceiptNumber`);return t?String(t.Value):null}function Yi(e){let t=(e.Body?.stkCallback?.CallbackMetadata?.Item)?.find(e=>e.Name===`Amount`);return t?Number(t.Value):null}function Xi(e){let t=(e.Body?.stkCallback?.CallbackMetadata?.Item)?.find(e=>e.Name===`PhoneNumber`);return t?String(t.Value):null}function Zi(e){return e.Body?.stkCallback?.ResultCode===0}var Qi=class{config;tokenManager;baseUrl;idempotencyManager;constructor(e){if(!e.consumerKey||!e.consumerSecret)throw new i({code:`INVALID_CREDENTIALS`,message:`consumerKey and consumerSecret are required.`});this.config=e,this.baseUrl=Li[e.environment],this.tokenManager=new p(e.consumerKey,e.consumerSecret,this.baseUrl),this.idempotencyManager=new y(e.idempotency)}darajaHttp(){return{idempotency:this.idempotencyManager}}getToken(){return this.tokenManager.getAccessToken()}async buildSecurityCredential(){if(this.config.securityCredential)return this.config.securityCredential;if(!this.config.initiatorPassword)throw new i({code:`INVALID_CREDENTIALS`,message:`Provide securityCredential (pre-encrypted) OR (initiatorPassword + certificatePath/certificatePem).`});let t;if(this.config.certificatePem)t=this.config.certificatePem;else if(this.config.certificatePath)t=await e(this.config.certificatePath,`utf-8`);else throw new i({code:`INVALID_CREDENTIALS`,message:`certificatePath or certificatePem is required to encrypt the initiator password.`});return m(this.config.initiatorPassword,t)}requireInitiator(e){let t=this.config.initiatorName??``;if(!t)throw new i({code:`VALIDATION_ERROR`,message:`initiatorName is required for ${e}.`});return t}async stkPushSafe(e){try{return C(await this.stkPush(e))}catch(e){return w(e)}}async accountBalanceSafe(e){try{return C(await this.accountBalance(e))}catch(e){return w(e)}}async stkPush(e){let t=this.config.lipaNaMpesaShortCode??``,n=this.config.lipaNaMpesaPassKey??``;if(!t||!n)throw new i({code:`VALIDATION_ERROR`,message:`lipaNaMpesaShortCode and lipaNaMpesaPassKey are required for STK Push.`});let r=await this.getToken();return $r(this.baseUrl,r,{...e,shortCode:t,passKey:n},this.darajaHttp())}async stkQuery(e){let t=this.config.lipaNaMpesaShortCode??``,n=this.config.lipaNaMpesaPassKey??``;if(!t||!n)throw new i({code:`VALIDATION_ERROR`,message:`lipaNaMpesaShortCode and lipaNaMpesaPassKey are required for STK Query.`});let r=await this.getToken();return ei(this.baseUrl,r,{...e,shortCode:t,passKey:n},this.darajaHttp())}async transactionStatus(e){let t=this.requireInitiator(`Transaction Status`),[n,r]=await Promise.all([this.getToken(),this.buildSecurityCredential()]);return _i(this.baseUrl,n,r,t,e,this.darajaHttp())}async accountBalance(e){let t=this.requireInitiator(`Account Balance`),[n,r]=await Promise.all([this.getToken(),this.buildSecurityCredential()]);return ve(this.baseUrl,n,r,t,e,this.darajaHttp())}async reverseTransaction(e){let t=this.requireInitiator(`Reversal`),[n,r]=await Promise.all([this.getToken(),this.buildSecurityCredential()]);return Hr(this.baseUrl,n,r,t,e,this.darajaHttp())}async generateDynamicQR(e){let t=await this.getToken();return Sr(this.baseUrl,t,e,this.darajaHttp())}async registerC2BUrls(e){let t=await this.getToken();return Jn(this.baseUrl,t,e,this.darajaHttp())}async simulateC2B(e){let t=await this.getToken();return Yn(this.baseUrl,t,e,this.darajaHttp())}async remitTax(e){let t=this.requireInitiator(`Tax Remittance`),[n,r]=await Promise.all([this.getToken(),this.buildSecurityCredential()]);return ri(this.baseUrl,n,r,t,e,this.darajaHttp())}async b2bExpressCheckout(e){let t=await this.getToken();return Le(this.baseUrl,t,e,this.darajaHttp())}async b2bBuyGoods(e){let t=this.requireInitiator(`B2B Buy Goods`),[n,r]=await Promise.all([this.getToken(),this.buildSecurityCredential()]);return N(this.baseUrl,n,r,t,e,this.darajaHttp())}async b2bPayBill(e){let t=this.requireInitiator(`B2B Pay Bill`),[n,r]=await Promise.all([this.getToken(),this.buildSecurityCredential()]);return ft(this.baseUrl,n,r,t,e,this.darajaHttp())}async b2cPayment(e){let t=this.requireInitiator(`B2C Payment`),[n,r]=await Promise.all([this.getToken(),this.buildSecurityCredential()]);return zt(this.baseUrl,n,r,t,e,this.darajaHttp())}async b2cDisbursement(e){let t=this.requireInitiator(`B2C Disbursement`),n={...e,originatorConversationId:e.originatorConversationId??g()},[r,i]=await Promise.all([this.getToken(),this.buildSecurityCredential()]);return rn(this.baseUrl,r,i,t,n,this.darajaHttp())}async billManagerOptIn(e){let t=await this.getToken();return Fn(this.baseUrl,t,e,this.darajaHttp())}async updateOptIn(e){let t=await this.getToken();return In(this.baseUrl,t,e,this.darajaHttp())}async sendInvoice(e){let t=await this.getToken();return Ln(this.baseUrl,t,e,this.darajaHttp())}async sendBulkInvoices(e){let t=await this.getToken();return V(this.baseUrl,t,e,this.darajaHttp())}async cancelInvoice(e){let t=await this.getToken();return Rn(this.baseUrl,t,e,this.darajaHttp())}async cancelBulkInvoices(e){let t=await this.getToken();return zn(this.baseUrl,t,e,this.darajaHttp())}async reconcilePayment(e){let t=await this.getToken();return Bn(this.baseUrl,t,e,this.darajaHttp())}clearTokenCache(){this.tokenManager.clearCache()}get environment(){return this.config.environment}};const $i=r.object({Result:r.object({ResultType:r.number(),ResultCode:r.number(),ResultDesc:r.string(),OriginatorConversationID:r.string().optional(),ConversationID:r.string().optional(),TransactionID:r.string().optional()})}).passthrough(),ea=r.object({TransID:r.string(),TransAmount:r.union([r.string(),r.number()]),MSISDN:r.string(),BusinessShortCode:r.string()}).passthrough();export{ye as ACCOUNT_BALANCE_ERROR_CODES,f as AUTH_ERROR_CODES,ue as AccountBalanceRequestSchema,de as AccountBalanceResponseSchema,k as AsyncApiResponseSchema,Ae as B2BBuyGoodsRequestSchema,Me as B2BBuyGoodsResponseSchema,Pe as B2BExpressCheckoutRequestSchema,Fe as B2BExpressCheckoutResponseSchema,je as B2BPayBillRequestSchema,Ne as B2BPayBillResponseSchema,Ie as B2BResponseSchema,Ge as B2B_BUY_GOODS_ERROR_CODES,We as B2B_BUY_GOODS_RESULT_CODES,mt as B2B_PAY_BILL_ERROR_CODES,pt as B2B_PAY_BILL_RESULT_CODES,j as B2B_RESULT_CODES,Lt as B2CDisbursementRequestSchema,Rt as B2CDisbursementResponseSchema,Ft as B2CRequestSchema,It as B2CResponseSchema,$i as B2CResultWebhookSchema,L as B2C_DISBURSEMENT_RESULT_CODES,Bt as B2C_ERROR_CODES,Vt as B2C_RESULT_CODES,Dn as BillManagerBulkInvoiceRequestSchema,On as BillManagerBulkInvoiceResponseSchema,jn as BillManagerCancelBulkInvoiceRequestSchema,Mn as BillManagerCancelBulkInvoiceResponseSchema,kn as BillManagerCancelInvoiceRequestSchema,An as BillManagerCancelInvoiceResponseSchema,Tn as BillManagerInvoiceItemSchema,z as BillManagerOptInRequestSchema,Sn as BillManagerOptInResponseSchema,Nn as BillManagerReconciliationRequestSchema,Pn as BillManagerReconciliationResponseSchema,B as BillManagerSingleInvoiceRequestSchema,En as BillManagerSingleInvoiceResponseSchema,Cn as BillManagerUpdateOptInRequestSchema,wn as BillManagerUpdateOptInResponseSchema,H as C2BBaseResponseSchema,ea as C2BConfirmationWebhookSchema,Vn as C2BRegisterUrlRequestSchema,Hn as C2BRegisterUrlResponseSchema,Wn as C2BSimulateRequestSchema,Un as C2BSimulateResponseSchema,Gn as C2BValidationWebhookSchema,Xn as C2B_REGISTER_URL_ERROR_CODES,Zn as C2B_VALIDATION_RESULT_CODES,Li as DARAJA_BASE_URLS,dr as DEFAULT_QR_SIZE,oe as DarajaErrorResponseSchema,ge as DynamicQRRequestSchema,_e as DynamicQRResponseSchema,ie as EnvironmentSchema,y as IdempotencyManager,v as InMemoryIdempotencyStore,ti as KRA_SHORTCODE,E as KesAmountSchema,lr as MAX_QR_SIZE,cr as MIN_AMOUNT,ur as MIN_QR_SIZE,Qi as Mpesa,ae as MsisdnSchema,D as NonEmptyStringSchema,i as PesafyError,U as QR_TRANSACTION_CODES,Cr as REVERSAL_COMMAND_ID,Tr as REVERSAL_ERROR_CODES,wr as REVERSAL_RECEIVER_IDENTIFIER_TYPE,W as REVERSAL_RESULT_CODES,fe as ReversalRequestSchema,pe as ReversalResponseSchema,Q as SAFARICOM_IPS,K as STK_PUSH_LIMITS,q as STK_RESULT_CODES,Wr as StkPushRequestSchema,Gr as StkPushResponseSchema,Jr as StkPushWebhookSchema,Kr as StkQueryRequestSchema,qr as StkQueryResponseSchema,ni as TAX_COMMAND_ID,vi as TRANSACTION_STATUS_ERROR_CODES,yi as TRANSACTION_STATUS_RESULT_CODES,me as TaxRemittanceRequestSchema,he as TaxRemittanceResponseSchema,p as TokenManager,ce as TransactionStatusRequestSchema,le as TransactionStatusResponseSchema,Ur as TransactionTypeSchema,O as UrlSchema,$n as acceptC2BValidation,tr as acknowledgeC2BConfirmation,Fn as billManagerOptIn,zn as cancelBulkInvoices,Rn as cancelInvoice,a as createError,m as encryptSecurityCredential,w as err,Yi as extractAmount,Xi as extractPhoneNumber,Ji as extractTransactionId,J as formatPhoneNumber,J as formatSafaricomPhone,Sr as generateDynamicQR,h as generateIdempotencyKey,g as generateOriginatorConversationId,_ as generateRequestRefId,we as getAccountBalanceCompletedTime,Se as getAccountBalanceConversationId,Ce as getAccountBalanceOriginatorConversationId,A as getAccountBalanceParam,Te as getAccountBalanceRawBalance,Ee as getAccountBalanceReferenceItem,xe as getAccountBalanceTransactionId,Ve as getB2BAmount,nt as getB2BBuyGoodsAmount,ut as getB2BBuyGoodsBillReferenceNumber,rt as getB2BBuyGoodsCompletedTime,Qe as getB2BBuyGoodsConversationId,ot as getB2BBuyGoodsCurrency,ct as getB2BBuyGoodsDebitAccountBalance,st as getB2BBuyGoodsDebitPartyAffectedBalance,at as getB2BBuyGoodsDebitPartyCharges,lt as getB2BBuyGoodsInitiatorBalance,$e as getB2BBuyGoodsOriginatorConversationId,dt as getB2BBuyGoodsQueueTimeoutUrl,it as getB2BBuyGoodsReceiverName,tt as getB2BBuyGoodsResultCode,et as getB2BBuyGoodsResultDesc,P as getB2BBuyGoodsResultParam,Ze as getB2BBuyGoodsTransactionId,Ue as getB2BConversationId,Tt as getB2BPayBillAmount,Nt as getB2BPayBillBillReferenceNumber,Et as getB2BPayBillCompletedTime,xt as getB2BPayBillConversationId,kt as getB2BPayBillCurrency,jt as getB2BPayBillDebitAccountBalance,At as getB2BPayBillDebitPartyAffectedBalance,Ot as getB2BPayBillDebitPartyCharges,Mt as getB2BPayBillInitiatorBalance,St as getB2BPayBillOriginatorConversationId,Dt as getB2BPayBillReceiverName,wt as getB2BPayBillResultCode,Ct as getB2BPayBillResultDesc,F as getB2BPayBillResultParam,bt as getB2BPayBillTransactionId,Be as getB2BRequestId,He as getB2BTransactionId,Xt as getB2CAmount,qt as getB2CConversationId,Zt as getB2CCurrency,en as getB2CDebitAccountBalance,tn as getB2CDebitPartyCharges,mn as getB2CDisbursementAmount,_n as getB2CDisbursementCompletedTime,un as getB2CDisbursementConversationId,dn as getB2CDisbursementOriginatorConversationId,hn as getB2CDisbursementReceiptNumber,gn as getB2CDisbursementReceiverName,pn as getB2CDisbursementResultCode,fn as getB2CDisbursementResultDesc,R as getB2CDisbursementResultParam,ln as getB2CDisbursementTransactionId,vn as getB2CDisbursementUtilityBalance,yn as getB2CDisbursementWorkingBalance,Jt as getB2COriginatorConversationId,Qt as getB2CReceiverPublicName,Yt as getB2CResultDesc,I as getB2CResultParam,$t as getB2CTransactionCompletedTime,Kt as getB2CTransactionId,ir as getC2BAccountRef,nr as getC2BAmount,ar as getC2BCustomerName,rr as getC2BTransactionId,Zr as getCallbackValue,Fr as getReversalAmount,Vr as getReversalCharge,Br as getReversalCompletedTime,jr as getReversalConversationId,Lr as getReversalCreditPartyPublicName,zr as getReversalDebitAccountBalance,Rr as getReversalDebitPartyPublicName,Ir as getReversalOriginalTransactionId,Mr as getReversalOriginatorConversationId,Nr as getReversalResultCode,Pr as getReversalResultDesc,G as getReversalResultParam,Ar as getReversalTransactionId,mi as getTaxAmount,hi as getTaxCompletedTime,fi as getTaxConversationId,pi as getTaxOriginatorConversationId,gi as getTaxReceiverName,li as getTaxResultCode,ui as getTaxResultDesc,X as getTaxResultParam,di as getTaxTransactionId,Y as getTimestamp,Ai as getTransactionStatusAmount,Ei as getTransactionStatusConversationId,Pi as getTransactionStatusCreditPartyName,Fi as getTransactionStatusDebitAccountBalance,Ni as getTransactionStatusDebitPartyName,Di as getTransactionStatusOriginatorConversationId,ji as getTransactionStatusReceiptNo,ki as getTransactionStatusResultCode,Oi as getTransactionStatusResultDesc,Z as getTransactionStatusResultParam,Mi as getTransactionStatusStatus,Ii as getTransactionStatusTransactionDate,Ti as getTransactionStatusTransactionId,qi as handleWebhook,d as httpRequest,N as initiateB2BBuyGoods,Le as initiateB2BExpressCheckout,ft as initiateB2BPayBill,rn as initiateB2CDisbursement,zt as initiateB2CPayment,De as isAccountBalanceSuccess,Ye as isB2BBuyGoodsFailure,qe as isB2BBuyGoodsResult,Je as isB2BBuyGoodsSuccess,Re as isB2BCheckoutCallback,ze as isB2BCheckoutCancelled,M as isB2BCheckoutSuccess,vt as isB2BPayBillFailure,gt as isB2BPayBillResult,_t as isB2BPayBillSuccess,sn as isB2CDisbursementFailure,bn as isB2CDisbursementRecipientRegistered,an as isB2CDisbursementResult,on as isB2CDisbursementSuccess,Wt as isB2CFailure,Ht as isB2CResult,Ut as isB2CSuccess,sr as isBuyGoodsPayment,Qn as isC2BPayload,Xe as isKnownB2BBuyGoodsResultCode,yt as isKnownB2BPayBillResultCode,cn as isKnownB2CDisbursementResultCode,Gt as isKnownB2CResultCode,kr as isKnownReversalResultCode,Yr as isKnownStkResultCode,wi as isKnownTransactionStatusResultCode,or as isPaybillPayment,o as isPesafyError,Or as isReversalFailure,Er as isReversalResult,Dr as isReversalSuccess,Xr as isStkCallbackSuccess,Zi as isSuccessfulCallback,ci as isTaxRemittanceFailure,oi as isTaxRemittanceResult,si as isTaxRemittanceSuccess,Ci as isTransactionStatusFailure,xi as isTransactionStatusResult,Si as isTransactionStatusSuccess,C as ok,be as parseAccountBalance,Gi as parseStkPushWebhook,ve as queryAccountBalance,_i as queryTransactionStatus,Bn as reconcilePayment,Jn as registerC2BUrls,er as rejectC2BValidation,ri as remitTax,Hr as requestReversal,zi as retryWithBackoff,V as sendBulkInvoices,Ln as sendSingleInvoice,Yn as simulateC2B,b as toKesAmount,x as toMsisdn,ne as toNonEmpty,S as toPaybill,te as toShortCode,ee as toTill,In as updateOptIn,mr as validateAmount,gr as validateCpi,vr as validateDynamicQRRequest,fr as validateMerchantName,pr as validateRefNo,_r as validateSize,hr as validateTrxCode,Ki as verifyWebhook,Wi as verifyWebhookHMAC,$ as verifyWebhookIP};
package/dist/phone.mjs ADDED
@@ -0,0 +1,23 @@
1
+ import { t as PesafyError } from "./errors.mjs";
2
+
3
+ //#region src/utils/phone/index.ts
4
+ /** Normalises any common Kenyan phone format to 254XXXXXXXXX (12 digits) */
5
+ function formatSafaricomPhone(phone) {
6
+ const digits = phone.replace(/\D/g, "");
7
+ let n;
8
+ if (digits.startsWith("254") && digits.length === 12) n = digits;
9
+ else if (digits.startsWith("0") && digits.length === 10) n = `254${digits.slice(1)}`;
10
+ else if (digits.length === 9) n = `254${digits}`;
11
+ else throw new PesafyError({
12
+ code: "INVALID_PHONE",
13
+ message: `Cannot parse "${phone}". Use 07XXXXXXXX, 2547XXXXXXXX, 2541XXXXXXXX (Airtel), or +2547XXXXXXXX.`
14
+ });
15
+ if (n.length !== 12) throw new PesafyError({
16
+ code: "INVALID_PHONE",
17
+ message: `"${phone}" normalised to "${n}" — expected 12 digits.`
18
+ });
19
+ return n;
20
+ }
21
+
22
+ //#endregion
23
+ export { formatSafaricomPhone };
@@ -0,0 +1 @@
1
+ export { };
File without changes