mpesajs
Version:
A Node.js SDK for seamless integration with M-Pesa payment gateway, providing easy-to-use methods for handling transactions, payments, and API interactions
163 lines • 8.27 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RegisterUrl = void 0;
const axios_1 = __importStar(require("axios"));
const ErrorHandlers_1 = require("./errors/ErrorHandlers");
const RateLimiter_1 = require("./utils/RateLimiter");
const env_1 = require("./utils/env");
/**
* Class to handle M-Pesa URL registration functionality
* Allows businesses to register their confirmation and validation URLs
*/
class RegisterUrl {
/**
* Creates an instance of RegisterUrl
* @param apiKey - M-Pesa API key for authentication
* @param sandbox - Whether to use sandbox environment
*/
constructor(apiKey = (0, env_1.getEnvVar)('MPESA_CONSUMER_KEY', ''), sandbox = (0, env_1.getEnvVar)('MPESA_SANDBOX', 'true').toLowerCase() === 'true') {
this.apiKey = apiKey;
this.baseUrl = sandbox
? 'https://apisandbox.safaricom.et/v1/c2b-register-url/register'
: 'https://api.safaricom.et/v1/c2b-register-url/register';
this.rateLimiter = RateLimiter_1.RateLimiter.getInstance();
}
/**
* Validates that both URLs use HTTPS protocol
* @param confirmationUrl - URL for successful transaction notifications
* @param validationUrl - URL for transaction validation
* @throws Error if URLs don't use HTTPS
*/
validateUrls(confirmationUrl, validationUrl) {
if (!confirmationUrl.startsWith('https://') || !validationUrl.startsWith('https://')) {
throw new ErrorHandlers_1.MpesaError('Both confirmation and validation URLs must use HTTPS protocol');
}
}
/**
* Builds the payload for URL registration request
* @param shortCode - Business short code
* @param responseType - Type of response expected
* @param commandId - Command identifier
* @param confirmationUrl - URL for confirmations
* @param validationUrl - URL for validations
* @returns Formatted payload object
*/
buildPayload(shortCode, responseType, commandId, confirmationUrl, validationUrl) {
return {
ShortCode: shortCode,
ResponseType: responseType,
CommandID: commandId,
ConfirmationURL: confirmationUrl,
ValidationURL: validationUrl
};
}
/**
* Parses and validates the API response
* @param response - Raw API response
* @returns Formatted RegisterUrlResponse object
* @throws Error if response format is invalid
*/
parseResponse(response) {
var _a;
if (!((_a = response.data) === null || _a === void 0 ? void 0 : _a.header)) {
ErrorHandlers_1.RegisterUrlErrorHandler.handle(response.data);
}
const { responseCode, responseMessage, customerMessage, timestamp } = response.data.header;
return { responseCode, responseMessage, customerMessage, timestamp };
}
/**
* Registers validation and confirmation URLs with M-Pesa
* @param shortCode - Business short code or PayBill number
* @param responseType - Type of response expected (default: 'Completed')
* @param commandId - Command identifier (default: 'RegisterURL')
* @param confirmationUrl - HTTPS URL to receive successful transaction confirmations
* @param validationUrl - HTTPS URL to validate transactions before processing
* @returns Promise containing registration response details
* @throws RegisterUrlError if registration fails
* @throws NetworkError if network connection fails
* @throws ValidationError if URLs are invalid
* @throws MpesaError for other API errors
*/
register() {
return __awaiter(this, arguments, void 0, function* (shortCode = (0, env_1.getEnvVar)('MPESA_BUSINESS_SHORTCODE', ''), responseType = (0, env_1.getEnvVar)('MPESA_REGISTER_URL_RESPONSE_TYPE', 'Completed'), commandId = (0, env_1.getEnvVar)('MPESA_REGISTER_URL_COMMAND_ID', 'RegisterURL'), confirmationUrl = (0, env_1.getEnvVar)('MPESA_CONFIRMATION_URL', ''), validationUrl = (0, env_1.getEnvVar)('MPESA_VALIDATION_URL', '')) {
return this.rateLimiter.execute(() => __awaiter(this, void 0, void 0, function* () {
var _a;
try {
this.validateUrls(confirmationUrl, validationUrl);
const payload = this.buildPayload(shortCode, responseType, commandId, confirmationUrl, validationUrl);
const response = yield axios_1.default.post(this.baseUrl, payload, {
params: { apikey: this.apiKey }
});
return this.parseResponse(response);
}
catch (error) {
if (error instanceof ErrorHandlers_1.ValidationError) {
throw error;
}
if (error instanceof axios_1.AxiosError) {
// Handle API response errors
if ((_a = error.response) === null || _a === void 0 ? void 0 : _a.data) {
return ErrorHandlers_1.RegisterUrlErrorHandler.handle(error.response.data);
}
// Handle network errors (no response received)
if (error.request || error.code === 'ECONNABORTED') {
throw new ErrorHandlers_1.NetworkError('No response received from the API. Please check your network connection.');
}
// Handle request setup errors
throw new ErrorHandlers_1.MpesaError(`Failed to register URLs: ${error.message}`);
}
// If it's already a RegisterUrlError, rethrow it
if (error instanceof ErrorHandlers_1.RegisterUrlError) {
throw error;
}
// For any other error, wrap it in MpesaError
throw new ErrorHandlers_1.MpesaError(`Failed to register URLs: ${error instanceof Error ? error.message : 'Unknown error occurred'}`);
}
}));
});
}
}
exports.RegisterUrl = RegisterUrl;
//# sourceMappingURL=registerUrl.js.map