pesafy 0.3.13 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +109 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +188 -1
- package/dist/index.d.ts +188 -1
- package/dist/index.js +107 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -561,6 +561,66 @@ function getCallbackValue(callback, name) {
|
|
|
561
561
|
return inner.CallbackMetadata.Item.find((i) => i.Name === name)?.Value;
|
|
562
562
|
}
|
|
563
563
|
|
|
564
|
+
// src/mpesa/tax-remittance/remit-tax.ts
|
|
565
|
+
var KRA_SHORTCODE = "572572";
|
|
566
|
+
var TAX_COMMAND_ID = "PayTaxToKRA";
|
|
567
|
+
async function remitTax(baseUrl, accessToken, securityCredential, initiatorName, request) {
|
|
568
|
+
const amount = Math.round(request.amount);
|
|
569
|
+
if (!Number.isFinite(amount) || amount < 1) {
|
|
570
|
+
throw createError({
|
|
571
|
+
code: "VALIDATION_ERROR",
|
|
572
|
+
message: `amount must be a whole number \u2265 1 (got ${request.amount} which rounds to ${amount}).`
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
if (!request.partyA) {
|
|
576
|
+
throw createError({
|
|
577
|
+
code: "VALIDATION_ERROR",
|
|
578
|
+
message: "partyA is required \u2014 your M-PESA business shortcode from which tax is deducted."
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
if (!request.accountReference?.trim()) {
|
|
582
|
+
throw createError({
|
|
583
|
+
code: "VALIDATION_ERROR",
|
|
584
|
+
message: "accountReference is required \u2014 the Payment Registration Number (PRN) issued by KRA."
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
if (!request.resultUrl?.trim()) {
|
|
588
|
+
throw createError({
|
|
589
|
+
code: "VALIDATION_ERROR",
|
|
590
|
+
message: "resultUrl is required \u2014 Safaricom POSTs the tax remittance result here."
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
if (!request.queueTimeOutUrl?.trim()) {
|
|
594
|
+
throw createError({
|
|
595
|
+
code: "VALIDATION_ERROR",
|
|
596
|
+
message: "queueTimeOutUrl is required \u2014 Safaricom calls this on request timeout."
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
const payload = {
|
|
600
|
+
Initiator: initiatorName,
|
|
601
|
+
SecurityCredential: securityCredential,
|
|
602
|
+
CommandID: TAX_COMMAND_ID,
|
|
603
|
+
SenderIdentifierType: "4",
|
|
604
|
+
RecieverIdentifierType: "4",
|
|
605
|
+
Amount: String(amount),
|
|
606
|
+
PartyA: String(request.partyA),
|
|
607
|
+
PartyB: request.partyB ?? KRA_SHORTCODE,
|
|
608
|
+
AccountReference: request.accountReference,
|
|
609
|
+
Remarks: request.remarks ?? "Tax Remittance",
|
|
610
|
+
QueueTimeOutURL: request.queueTimeOutUrl,
|
|
611
|
+
ResultURL: request.resultUrl
|
|
612
|
+
};
|
|
613
|
+
const { data } = await httpRequest(
|
|
614
|
+
`${baseUrl}/mpesa/b2b/v1/remittax`,
|
|
615
|
+
{
|
|
616
|
+
method: "POST",
|
|
617
|
+
headers: { Authorization: `Bearer ${accessToken}` },
|
|
618
|
+
body: payload
|
|
619
|
+
}
|
|
620
|
+
);
|
|
621
|
+
return data;
|
|
622
|
+
}
|
|
623
|
+
|
|
564
624
|
// src/mpesa/transaction-status/query.ts
|
|
565
625
|
async function queryTransactionStatus(baseUrl, token, securityCredential, initiator, request) {
|
|
566
626
|
if (!request.transactionId) {
|
|
@@ -850,6 +910,52 @@ var Mpesa = class {
|
|
|
850
910
|
const token = await this.getToken();
|
|
851
911
|
return simulateC2B(this.baseUrl, token, request);
|
|
852
912
|
}
|
|
913
|
+
// ── Tax Remittance ────────────────────────────────────────────────────────
|
|
914
|
+
/**
|
|
915
|
+
* Tax Remittance — remits tax to Kenya Revenue Authority (KRA) via M-PESA.
|
|
916
|
+
*
|
|
917
|
+
* Requires:
|
|
918
|
+
* - initiatorName in config
|
|
919
|
+
* - initiatorPassword + certificate (or pre-computed securityCredential)
|
|
920
|
+
*
|
|
921
|
+
* This is ASYNCHRONOUS. The synchronous response only confirms receipt.
|
|
922
|
+
* Final details are POSTed to your resultUrl.
|
|
923
|
+
*
|
|
924
|
+
* Prerequisites (from Daraja docs):
|
|
925
|
+
* - Prior integration with KRA for tax declaration.
|
|
926
|
+
* - A Payment Registration Number (PRN) from KRA.
|
|
927
|
+
* - Initiator with "Tax Remittance ORG API" role on M-PESA org portal.
|
|
928
|
+
*
|
|
929
|
+
* Fixed values (set automatically — do NOT override unless Safaricom changes them):
|
|
930
|
+
* CommandID: "PayTaxToKRA"
|
|
931
|
+
* SenderIdentifierType: "4"
|
|
932
|
+
* RecieverIdentifierType: "4"
|
|
933
|
+
* PartyB: "572572" (KRA shortcode)
|
|
934
|
+
*
|
|
935
|
+
* @example
|
|
936
|
+
* await mpesa.remitTax({
|
|
937
|
+
* amount: 5000,
|
|
938
|
+
* partyA: "888880",
|
|
939
|
+
* accountReference: "PRN1234XN", // PRN from KRA
|
|
940
|
+
* resultUrl: "https://yourdomain.com/mpesa/tax/result",
|
|
941
|
+
* queueTimeOutUrl: "https://yourdomain.com/mpesa/tax/timeout",
|
|
942
|
+
* remarks: "Monthly PAYE remittance",
|
|
943
|
+
* });
|
|
944
|
+
*/
|
|
945
|
+
async remitTax(request) {
|
|
946
|
+
const initiator = this.config.initiatorName ?? "";
|
|
947
|
+
if (!initiator) {
|
|
948
|
+
throw new PesafyError({
|
|
949
|
+
code: "VALIDATION_ERROR",
|
|
950
|
+
message: "initiatorName is required for Tax Remittance"
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
const [token, securityCred] = await Promise.all([
|
|
954
|
+
this.getToken(),
|
|
955
|
+
this.buildSecurityCredential()
|
|
956
|
+
]);
|
|
957
|
+
return remitTax(this.baseUrl, token, securityCred, initiator, request);
|
|
958
|
+
}
|
|
853
959
|
/** Force the cached OAuth token to be refreshed on the next API call */
|
|
854
960
|
clearTokenCache() {
|
|
855
961
|
this.tokenManager.clearCache();
|
|
@@ -975,9 +1081,11 @@ function isSuccessfulCallback(webhook) {
|
|
|
975
1081
|
}
|
|
976
1082
|
|
|
977
1083
|
exports.DARAJA_BASE_URLS = DARAJA_BASE_URLS;
|
|
1084
|
+
exports.KRA_SHORTCODE = KRA_SHORTCODE;
|
|
978
1085
|
exports.Mpesa = Mpesa;
|
|
979
1086
|
exports.PesafyError = PesafyError;
|
|
980
1087
|
exports.SAFARICOM_IPS = SAFARICOM_IPS;
|
|
1088
|
+
exports.TAX_COMMAND_ID = TAX_COMMAND_ID;
|
|
981
1089
|
exports.acceptC2BValidation = acceptC2BValidation;
|
|
982
1090
|
exports.acknowledgeC2BConfirmation = acknowledgeC2BConfirmation;
|
|
983
1091
|
exports.createError = createError;
|
|
@@ -1001,6 +1109,7 @@ exports.isSuccessfulCallback = isSuccessfulCallback;
|
|
|
1001
1109
|
exports.parseStkPushWebhook = parseStkPushWebhook;
|
|
1002
1110
|
exports.registerC2BUrls = registerC2BUrls;
|
|
1003
1111
|
exports.rejectC2BValidation = rejectC2BValidation;
|
|
1112
|
+
exports.remitTax = remitTax;
|
|
1004
1113
|
exports.retryWithBackoff = retryWithBackoff;
|
|
1005
1114
|
exports.simulateC2B = simulateC2B;
|
|
1006
1115
|
exports.verifyWebhookIP = verifyWebhookIP;
|