UNPKG

voko-sdk

Version:
129 lines (128 loc) 4.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseAdapter = void 0; const types_1 = require("../../core/types"); const errors_1 = require("../../core/errors"); const http_client_1 = require("../../utils/http-client"); const logger_1 = require("../../utils/logger"); class BaseAdapter { config; provider; httpClient; logger; baseUrl; constructor(config) { this.config = config; this.provider = config.provider; this.httpClient = new http_client_1.HttpClient({ timeout: config.timeout || 30000, retries: config.retries || 3, }); this.logger = new logger_1.Logger(`${this.provider.toUpperCase()}Adapter`); this.baseUrl = this.getBaseUrl(config.environment); } getContentHeaders() { return { 'Content-Type': 'application/json' }; } getStatusHttpMethod() { return 'GET'; } async initiatePayment(request) { try { const transformedRequest = this.transformRequest(request); const response = await this.makeApiCall(this.getPaymentEndpoint(), transformedRequest, 'POST'); const paymentResponse = this.transformResponse(response, request); return paymentResponse; } catch (error) { this.logger.error('Payment initiation failed', error); throw this.handleError(error); } } async checkPaymentStatus(request) { try { const requestData = this.getStatusRequestData(request); const httpMethod = this.getStatusHttpMethod(); const response = await this.makeApiCall(this.getStatusEndpoint(), requestData, httpMethod); const statusResponse = this.transformStatusResponse(response); return statusResponse; } catch (error) { this.logger.error('Payment status check failed', error); throw this.handleError(error); } } async verifyWebhook(payload, signature) { try { const isValid = this.verifyWebhookSignature(payload, signature); if (!isValid) { return { valid: false, error: 'Invalid webhook signature' }; } const webhookPayload = this.parseWebhookPayload(payload); return { valid: true, payload: webhookPayload }; } catch (error) { this.logger.error('Webhook verification failed', error); return { valid: false, error: 'Webhook verification error' }; } } async makeApiCall(endpoint, data, method = 'POST') { const url = this.buildUrl(endpoint); const headers = this.buildRequestHeaders(); try { const response = await this.httpClient.request({ url, method, headers, data: method === 'POST' ? data : undefined, params: method === 'GET' ? data : undefined, }); return response.data; } catch (error) { throw error; } } buildUrl(endpoint) { const cleanEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`; return `${this.baseUrl}${cleanEndpoint}`; } buildRequestHeaders() { return { ...this.getContentHeaders(), ...this.getAuthHeaders(), }; } handleError(error) { if (error instanceof errors_1.VokoError) { return error; } const errorCode = this.mapErrorCode(error); return errors_1.VokoError.fromProvider(error, errorCode); } generateTransactionId() { const timestamp = Date.now(); const random = Math.random().toString(36).substring(2, 9); return `voko_${timestamp}_${random}`; } parseWebhookPayload(payload) { try { return JSON.parse(payload); } catch (error) { throw new errors_1.VokoError('Invalid webhook payload format', types_1.VokoErrorCode.PROVIDER_ERROR, undefined, 'Unable to parse webhook payload as JSON'); } } getSupportedPaymentMethods() { return [types_1.PaymentMethod.MOBILE_MONEY]; } getSupportedOperators() { return [ types_1.MobileOperator.VODACOM_MPESA, types_1.MobileOperator.AIRTEL_MONEY, types_1.MobileOperator.TIGO_PESA, types_1.MobileOperator.HALO_PESA, ]; } } exports.BaseAdapter = BaseAdapter;