UNPKG

mpesalib

Version:

A robust Node.js library for Safaricom's Daraja API with complete TypeScript support and modern async/await patterns

149 lines 5.13 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.HttpClient = void 0; const axios_1 = __importDefault(require("axios")); const utils_1 = require("../utils"); class HttpClient { constructor(config) { this.accessToken = null; this.tokenExpiry = null; this.config = config; const baseURL = utils_1.MpesaUtils.getBaseUrl(config.environment); this.client = axios_1.default.create({ baseURL, timeout: 30000, headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', }, }); // Add request interceptor for authentication this.client.interceptors.request.use(async (config) => { if (config.url !== '/oauth/v1/generate' && !config.headers.Authorization) { const token = await this.getAccessToken(); config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => Promise.reject(error)); // Add response interceptor for error handling this.client.interceptors.response.use((response) => response, (error) => { if (error.response?.status === 401) { // Token expired, clear it this.accessToken = null; this.tokenExpiry = null; } return Promise.reject(this.formatError(error)); }); } /** * Get access token from Safaricom OAuth API */ async getAccessToken() { // Check if we have a valid token if (this.accessToken && this.tokenExpiry && new Date() < this.tokenExpiry) { return this.accessToken; } try { const credentials = Buffer.from(`${this.config.consumerKey}:${this.config.consumerSecret}`).toString('base64'); const response = await this.client.get('/oauth/v1/generate?grant_type=client_credentials', { headers: { Authorization: `Basic ${credentials}`, }, }); this.accessToken = response.data.access_token; // Set expiry to 5 minutes before actual expiry (default is 1 hour) const expiryInMs = (parseInt(response.data.expires_in) - 300) * 1000; this.tokenExpiry = new Date(Date.now() + expiryInMs); return this.accessToken; } catch (error) { throw new Error(`Failed to get access token: ${this.getErrorMessage(error)}`); } } /** * Make GET request */ async get(url, config) { const response = await this.client.get(url, config); return response.data; } /** * Make POST request */ async post(url, data, config) { const response = await this.client.post(url, data, config); return response.data; } /** * Make PUT request */ async put(url, data, config) { const response = await this.client.put(url, data, config); return response.data; } /** * Make DELETE request */ async delete(url, config) { const response = await this.client.delete(url, config); return response.data; } /** * Format error response */ formatError(error) { if (error.response) { // Server responded with error status const { status, data } = error.response; const message = data?.errorMessage || data?.ResponseDescription || error.message; const formattedError = new Error(`HTTP ${status}: ${message}`); formattedError.status = status; formattedError.data = data; return formattedError; } else if (error.request) { // Request was made but no response received return new Error('Network error: No response received from server'); } else { // Something else happened return new Error(`Request error: ${error.message}`); } } /** * Get error message from various error formats */ getErrorMessage(error) { if (error.response?.data?.errorMessage) { return error.response.data.errorMessage; } if (error.response?.data?.ResponseDescription) { return error.response.data.ResponseDescription; } if (error.message) { return error.message; } return 'Unknown error occurred'; } /** * Clear access token (useful for testing or manual token refresh) */ clearToken() { this.accessToken = null; this.tokenExpiry = null; } /** * Get current token info (for debugging) */ getTokenInfo() { return { token: this.accessToken, expiry: this.tokenExpiry, }; } } exports.HttpClient = HttpClient; //# sourceMappingURL=httpClient.js.map