UNPKG

@payunit/nodejs-sdk

Version:

PayUnit Payment Processor SDK

173 lines 9.23 kB
"use strict"; 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()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PayunitClient = void 0; const axios_1 = __importDefault(require("axios")); const index_1 = require("./validators/index"); const config_1 = require("./types/config"); class PayunitClient { constructor(config) { try { // Validate configuration const { error, value } = config_1.configSchema.validate(config, { abortEarly: true, allowUnknown: false, stripUnknown: true, }); if (error) { const errorMessages = error.details.map((detail) => detail.message).join('; '); throw new Error(`Invalid configuration: ${errorMessages}`); } this.config = value; // Store sensitive data in a separate object that won't be serialized this.credentials = { auth: Buffer.from(`${this.config.apiUsername}:${this.config.apiPassword}`).toString('base64'), apiKey: this.config.apiKey, }; this.axiosInstance = axios_1.default.create({ baseURL: `${this.config.baseURL.replace(/\/+$/, '')}/api`, headers: { 'Content-Type': 'application/json', 'User-Agent': 'PayUnit-Node-SDK/1.0', }, timeout: this.config.timeout, maxRedirects: 0, validateStatus: (status) => status >= 200 && status < 400, }); // Add request interceptor for auth headers this.axiosInstance.interceptors.request.use((config) => { const headers = new axios_1.default.AxiosHeaders(Object.assign(Object.assign({}, config.headers), { 'Content-Type': 'application/json', 'User-Agent': 'PayUnit-Node-SDK/1.0', Authorization: `Basic ${this.credentials.auth}`, 'x-api-key': this.credentials.apiKey, mode: this.config.mode })); return Object.assign(Object.assign({}, config), { headers }); }); // Add response interceptor for error handling this.axiosInstance.interceptors.response.use((response) => response, (error) => { var _a, _b; if (axios_1.default.isAxiosError(error)) { const status = (_a = error.response) === null || _a === void 0 ? void 0 : _a.status; const data = (_b = error.response) === null || _b === void 0 ? void 0 : _b.data; console.log({ status, data, message: error === null || error === void 0 ? void 0 : error.message, }); if (status === 401) { return Promise.reject(new Error(`Authentication failed. Please check your credentials or authorisations needed. ${data === null || data === void 0 ? void 0 : data.message}`)); } if (status === 403) { return Promise.reject(new Error(`Access denied. Please check your API key and permissions needed'. ${data === null || data === void 0 ? void 0 : data.message}`)); } const message = (data === null || data === void 0 ? void 0 : data.message) || error.message || 'An unknown error occurred'; return Promise.reject(new Error(`API request failed: ${message}`)); } return Promise.reject(error); }); } catch (error) { const safeError = new Error('Failed to initialize PayUnit client'); safeError.originalError = error instanceof Error ? error.message : 'Unknown error'; throw safeError; } // Import the actual implementations const { Collections } = require('./Collections'); const { Checkout } = require('./Checkout'); const { Invoice } = require('./Invoice'); const { Disbursement } = require('./Disbursement'); // Initialize services with the current client instance this.collections = new Collections(this); this.checkout = new Checkout(this); this.invoice = new Invoice(this); this.disbursement = new Disbursement(this); } request(method_1, endpoint_1) { return __awaiter(this, arguments, void 0, function* (method, endpoint, data = null, params) { if (!endpoint || typeof endpoint !== 'string') { throw new Error('Endpoint must be a non-empty string'); } // Sanitize endpoint to prevent path traversal const sanitizedEndpoint = endpoint.replace(/\.{2,}/g, '').replace(/^\/+/g, ''); const response = yield this.axiosInstance.request({ method, url: sanitizedEndpoint, data: data !== null ? data : undefined, params, }); return response.data; }); } makeRequest(method, endpoint, requestSchema, data, errorMessage, params) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g; try { // For GET requests, validate the data but don't send it as request body if (method === 'GET') { // Validate the data (usually URL parameters) against schema const { error } = requestSchema.validate(data, { abortEarly: false, allowUnknown: true, stripUnknown: true, }); if (error) { throw index_1.ValidationError.fromJoiError(error); } // Make the GET request without body data const response = yield this.axiosInstance.request({ method, url: endpoint, params, }); // Check for API-level errors if (response.data && response.data.status === 'FAILED') { throw index_1.ValidationError.fromApiError(response.data); } // Return the data if it exists, otherwise the full response return (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : response.data; } // For POST requests, validate and send data as request body const { error, value } = requestSchema.validate(data, { abortEarly: false, allowUnknown: true, stripUnknown: true, }); if (error) { throw index_1.ValidationError.fromJoiError(error); } // Make the request with validated data const response = yield this.axiosInstance.request({ method, url: endpoint, data: value, params, }); // Check for API-level errors if (response.data && response.data.status === 'FAILED') { throw index_1.ValidationError.fromApiError(response.data); } // Return the data if it exists, otherwise the full response return (_d = (_c = response.data) === null || _c === void 0 ? void 0 : _c.data) !== null && _d !== void 0 ? _d : response.data; } catch (error) { if (error instanceof index_1.ValidationError) { throw error; } if (axios_1.default.isAxiosError(error)) { // Error is already processed by the interceptor throw new Error((_g = (_f = (_e = error.response) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.message) !== null && _g !== void 0 ? _g : `${errorMessage} ${error.message}`); } throw new Error(error instanceof Error ? error.message : 'An unknown error occurred'); } }); } } exports.PayunitClient = PayunitClient; //# sourceMappingURL=PayunitClient.js.map