diff --git a/.changeset/friendly-candles-visit.md b/.changeset/friendly-candles-visit.md new file mode 100644 index 0000000..2f4cad0 --- /dev/null +++ b/.changeset/friendly-candles-visit.md @@ -0,0 +1,7 @@ +--- +"medusa-payment-paystack": patch +--- + +Use Axios for Paystack API requests to resolve header issues on some platforms. + +Credits: [JaeKralj](https://github.com/JaeKralj) diff --git a/packages/plugin/package.json b/packages/plugin/package.json index b7afc83..435b4f6 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -13,7 +13,8 @@ "@medusajs/medusa": "^1.16.1" }, "dependencies": { - "@medusajs/utils": "^1.9.4" + "@medusajs/utils": "^1.9.4", + "axios": "^1.5.1" }, "devDependencies": { "@medusajs/medusa": "^1.16.1", diff --git a/packages/plugin/src/lib/paystack.ts b/packages/plugin/src/lib/paystack.ts index 33aab31..46a956b 100644 --- a/packages/plugin/src/lib/paystack.ts +++ b/packages/plugin/src/lib/paystack.ts @@ -1,4 +1,4 @@ -import https from "https"; +import axios, { AxiosInstance, AxiosRequestConfig } from "axios"; import { SupportedCurrency } from "../utils/currencyCode"; @@ -36,54 +36,35 @@ export interface PaystackTransactionAuthorisation { export default class Paystack { apiKey: string; + protected readonly axiosInstance: AxiosInstance; + constructor(apiKey: string) { this.apiKey = apiKey; - } - - protected async requestPaystackAPI(request: Request): Promise { - const path = - request.path.replace(/\/$/, "") + - "/?" + - new URLSearchParams(request.query).toString(); - - const options = { - method: request.method, - path, + this.axiosInstance = axios.create({ + baseURL: PAYSTACK_API_PATH, headers: { Authorization: `Bearer ${this.apiKey}`, "Content-Type": "application/json", }, - }; - - return new Promise((resolve, reject) => { - const req = https.request(PAYSTACK_API_PATH, options, res => { - let data: Uint8Array[] = []; - - res.on("data", chunk => { - data.push(chunk); - }); - - res.on("end", () => { - try { - resolve(JSON.parse(Buffer.concat(data).toString()) as T); - } catch (e) { - reject(e); - } - }); - }); - - req.on("error", e => { - reject(e); - }); - - if (request.body && Object.values(request.body).length > 0) { - req.write(JSON.stringify(request.body)); - } - - req.end(); }); } + protected async requestPaystackAPI(request: Request): Promise { + const options = { + method: request.method, + url: request.path, + params: request.query, + data: request.body, + } satisfies AxiosRequestConfig; + + try { + const res = await this.axiosInstance(options); + return res.data; + } catch (error) { + throw "Error from Paystack API: " + error.message; + } + } + transaction = { verify: ({ reference }: { reference: string }) => this.requestPaystackAPI< diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3c04b3b..37e1efc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -138,6 +138,9 @@ importers: '@medusajs/utils': specifier: ^1.9.4 version: 1.9.4 + axios: + specifier: ^1.5.1 + version: 1.5.1 devDependencies: '@medusajs/medusa': specifier: ^1.16.1 @@ -2968,7 +2971,6 @@ packages: /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true /at-least-node@1.0.0: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} @@ -3036,6 +3038,16 @@ packages: - debug dev: false + /axios@1.5.1: + resolution: {integrity: sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==} + dependencies: + follow-redirects: 1.15.2 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + /axobject-query@3.2.1: resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} dependencies: @@ -3684,7 +3696,6 @@ packages: engines: {node: '>= 0.8'} dependencies: delayed-stream: 1.0.0 - dev: true /commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} @@ -4119,7 +4130,6 @@ packages: /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - dev: true /denque@1.5.1: resolution: {integrity: sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==} @@ -5218,6 +5228,15 @@ packages: mime-types: 2.1.35 dev: true + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + /forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -8233,6 +8252,10 @@ packages: resolution: {integrity: sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==} dev: true + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + /pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} dev: false