UNPKG

mpesa-sdk

Version:

Type safe SDK for M-Pesa API (Mozambique)

313 lines (309 loc) 9.77 kB
// src/core.ts import axios, { AxiosError } from "axios"; // src/utils.ts import crypto from "crypto"; function getBearerToken(apiKey, publicKey) { try { const publicKeyBuffer = Buffer.from(publicKey, "base64"); const pk = crypto.createPublicKey({ key: publicKeyBuffer, format: "der", // Specify the format explicitly type: "spki" // Specify the type explicitly }); const encryptedApiKeyBuffer = crypto.publicEncrypt( { key: pk, padding: crypto.constants.RSA_PKCS1_PADDING }, Buffer.from(apiKey, "utf-8") ); return encryptedApiKeyBuffer.toString("base64"); } catch (error) { return null; } } function getApiBaseUrl(mode) { const urlSandbox = "https://api.sandbox.vm.co.mz"; const urlProduction = "https://api.vm.co.mz"; return mode === "production" ? `${urlProduction}` : `${urlSandbox}`; } // src/error.ts var MpesaResponseError = class extends Error { statusCode; data; constructor(message, statusCode, data) { super(message); this.statusCode = statusCode; this.data = data; } }; // src/core.ts var MPesa = class { configuration; constructor(config) { this.configuration = { mode: config.mode ?? "sandbox", apiKey: config.apiKey, publicKey: config.publicKey, origin: config.origin, serviceProviderCode: config.serviceProviderCode }; } getConfiguration() { return Object.assign({}, this.configuration); } updateConfiguration(config) { this.configuration.mode = config.mode ?? this.configuration.mode; this.configuration.apiKey = config.apiKey ?? this.configuration.apiKey; this.configuration.publicKey = config.publicKey ?? this.configuration.publicKey; this.configuration.origin = config.origin ?? this.configuration.origin; this.configuration.serviceProviderCode = config.serviceProviderCode ?? this.configuration.serviceProviderCode; } async c2bPayment(request) { const url = `${getApiBaseUrl( this.configuration.mode )}:18352/ipg/v1x/c2bPayment/singleStage/`; const token = await getBearerToken( this.configuration.apiKey, this.configuration.publicKey ); const headers = { Authorization: `Bearer ${token}`, "Content-Type": "application/json", Origin: this.configuration.origin }; const body = { input_TransactionReference: request.transactionReference, input_CustomerMSISDN: request.msisdn, input_Amount: request.amount + "", input_ThirdPartyReference: request.thirdPartyReference, input_ServiceProviderCode: this.configuration.serviceProviderCode }; try { const { data } = await axios.request({ method: "POST", url, headers, data: body, timeout: 12e4 }); return data; } catch (error) { if (error instanceof AxiosError) { if (error.response?.status && error.response.status < 500) { return error.response.data; } const message = error.message; const statusCode = error.response?.status ?? 500; const data = error.response?.data; throw new MpesaResponseError(message, statusCode, data); } throw new Error("API error"); } } async b2cPayment(request) { const url = `${getApiBaseUrl( this.configuration.mode )}:18345/ipg/v1x/b2cPayment/`; const token = await getBearerToken( this.configuration.apiKey, this.configuration.publicKey ); const headers = { Authorization: `Bearer ${token}`, "Content-Type": "application/json", Origin: this.configuration.origin }; const body = { input_TransactionReference: request.transactionReference, input_CustomerMSISDN: request.msisdn, input_Amount: request.amount + "", input_ThirdPartyReference: request.thirdPartyReference, input_ServiceProviderCode: this.configuration.serviceProviderCode }; try { const { data } = await axios.request({ method: "POST", url, headers, data: body }); return data; } catch (error) { if (error instanceof AxiosError) { if (error.response?.status && error.response.status < 500) { return error.response.data; } const message = error.message; const statusCode = error.response?.status ?? 500; const data = error.response?.data; throw new MpesaResponseError(message, statusCode, data); } throw new Error("API error"); } } async b2bPayment(request) { const url = `${getApiBaseUrl( this.configuration.mode )}:18349/ipg/v1x/b2bPayment/`; const token = await getBearerToken( this.configuration.apiKey, this.configuration.publicKey ); const headers = { Authorization: `Bearer ${token}`, "Content-Type": "application/json", Origin: this.configuration.origin }; const body = { input_TransactionReference: request.transactionReference, input_Amount: request.amount + "", input_ThirdPartyReference: request.thirdPartyReference, input_PrimaryPartyCode: this.configuration.serviceProviderCode, input_ReceiverPartyCode: request.receiverPartyCode }; try { const { data } = await axios.request({ method: "POST", url, headers, data: body }); return data; } catch (error) { if (error instanceof AxiosError) { if (error.response?.status && error.response.status < 500) { return error.response.data; } const message = error.message; const statusCode = error.response?.status ?? 500; const data = error.response?.data; throw new MpesaResponseError(message, statusCode, data); } throw new Error("API error"); } } async queryTransactionStatus(request) { const url = `${getApiBaseUrl( this.configuration.mode )}:18353/ipg/v1x/queryTransactionStatus/`; const token = await getBearerToken( this.configuration.apiKey, this.configuration.publicKey ); const headers = { Authorization: `Bearer ${token}`, "Content-Type": "application/json", Origin: this.configuration.origin }; const body = { input_ThirdPartyReference: request.thirdPartyReference, input_QueryReference: request.queryReference, input_ServiceProviderCode: this.configuration.serviceProviderCode }; try { const { data } = await axios.request({ method: "GET", url, headers, params: body }); return data; } catch (error) { if (error instanceof AxiosError) { if (error.response?.status && error.response.status < 500) { return error.response.data; } const message = error.message; const statusCode = error.response?.status ?? 500; const data = error.response?.data; throw new MpesaResponseError(message, statusCode, data); } throw new Error("API error"); } } async queryCustomerName(request) { const url = `${getApiBaseUrl( this.configuration.mode )}:19323/ipg/v1x/queryCustomerName/`; const token = await getBearerToken( this.configuration.apiKey, this.configuration.publicKey ); const headers = { Authorization: `Bearer ${token}`, "Content-Type": "application/json", Origin: this.configuration.origin }; const body = { input_CustomerMSISDN: request.msisdn, input_ThirdPartyReference: request.thirdPartyReference, input_ServiceProviderCode: this.configuration.serviceProviderCode }; try { const { data } = await axios.request({ method: "GET", url, headers, params: body }); return data; } catch (error) { if (error instanceof AxiosError) { if (error.response?.status && error.response.status < 500) { return error.response.data; } const message = error.message; const statusCode = error.response?.status ?? 500; const data = error.response?.data; throw new MpesaResponseError(message, statusCode, data); } throw new Error("API error"); } } async reversal(request) { const url = `${getApiBaseUrl( this.configuration.mode )}:18354/ipg/v1x/reversal/`; const token = await getBearerToken( this.configuration.apiKey, this.configuration.publicKey ); const headers = { Authorization: `Bearer ${token}`, "Content-Type": "application/json", Origin: this.configuration.origin }; const body = { input_TransactionID: request.transactionId, input_SecurityCredential: request.securityCredential, input_InitiatorIdentifier: request.initiatorIdentifier, input_ThirdPartyReference: request.thirdPartyReference, input_ServiceProviderCode: this.configuration.serviceProviderCode, input_ReversalAmount: request.reversalAmount ? request.reversalAmount + "" : void 0 }; try { const { data } = await axios.request({ method: "PUT", url, headers, data: body }); return data; } catch (error) { if (error instanceof AxiosError) { if (error.response?.status && error.response.status < 500) { return error.response.data; } const message = error.message; const statusCode = error.response?.status ?? 500; const data = error.response?.data; throw new MpesaResponseError(message, statusCode, data); } throw new Error("API error"); } } }; export { MpesaResponseError, MPesa as default };