diff --git a/README.md b/README.md index 6393b30b..e8ba74ef 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ let payload = { }; const response = await PAYPAY.QRCodeCreate(payload); -const body = JSON.parse(response.BODY); +const body = response.BODY; console.log(response.STATUS, body.resultInfo.code); ``` @@ -117,7 +117,7 @@ Now that you have created a Code, the next step is to implement polling to get let merchantPaymentId = 'merchantPaymentId'; const response = await PAYPAY.GetCodePaymentDetails([merchantPaymentId]); -const body = JSON.parse(response.BODY); +const body = response.BODY; console.log(body.resultInfo.code); console.log(body.data.status); ``` @@ -139,7 +139,7 @@ Following are the important parameters that you can provide for this method: ```javascript const response = await PAYPAY.QRCodeDelete([codeId]); -const body = JSON.parse(response.BODY); +const body = response.BODY; console.log(body.resultInfo.code); ``` @@ -162,7 +162,7 @@ Following are the important parameters that you can provide for this method: ```javascript const response = await PAYPAY.PaymentCancel([merchantPaymentId]); -const body = JSON.parse(response.BODY); +const body = response.BODY; console.log(body.resultInfo.code); ``` @@ -190,7 +190,7 @@ let payload = { }; const response = await PAYPAY.PaymentRefund(payload); -const body = JSON.parse(response.BODY); +const body = response.BODY; console.log(body.resultInfo.code); ``` @@ -220,7 +220,7 @@ let payload = { }; const response = await PAYPAY.PaymentAuthCapture(payload); -const body = JSON.parse(response.BODY); +const body = response.BODY; console.log(body.resultInfo.code); ``` For details of all the request and response parameters , check our [API Documentation guide](https://www.paypay.ne.jp/opa/doc/v1.0/dynamicqrcode#operation/capturePaymentAuth). @@ -243,7 +243,7 @@ let payload = { }; const response = await PAYPAY.PaymentAuthRevert(payload); -const body = JSON.parse(response.BODY); +const body = response.BODY: console.log(body.resultInfo.code); ``` For List of params refer to the API guide : @@ -260,7 +260,7 @@ So you want to confirm the status of the refund, maybe because the request for t ```javascript let merchantPaymentId = 'merchantRefundId'; const response = await PAYPAY.GetRefundDetails([merchantRefundId]); -const body = JSON.parse(response.BODY); +const body = response.BODY; console.log(body.resultInfo.code); ``` For details of all the request and response parameters , check our [API Documentation guide](https://www.paypay.ne.jp/opa/doc/v1.0/dynamicqrcode#operation/getRefundDetails). @@ -305,7 +305,7 @@ let payload = { }; // Calling the method to create the account linking QR Code const response = await PAYPAY.AccountLinkQRCodeCreate(payload); -const body = JSON.parse(response.BODY); +const body = response.BODY; // Printing if the method call was SUCCESS console.log(body.resultInfo.code); @@ -332,7 +332,7 @@ const userAuthorizationId = jwtResponse["userAuthorizationId"]; ```javascript // Calling the method to unlink a Payment const result = await PAYPAY.unlinkUser([userAuthorizationId]); -const body = JSON.parse(result.BODY); +const body = result.BODY; // Printing if the method call was SUCCESS console.log(body.resultInfo.code); @@ -365,7 +365,7 @@ let payload = { // Calling the method to create a payment const response = await PAYPAY.CreatePayment(payload); -const body = JSON.parse(response.BODY); +const body = response.BODY; // Printing if the method call was SUCCESS console.log(body.resultInfo.code); @@ -424,7 +424,7 @@ Now that you have created a payment, in case the payment request timeout, you ca ```javascript let merchantPaymentId = 'merchantPaymentId'; const response = await PAYPAY.GetPaymentDetails([merchantPaymentId]); -const body = JSON.parse(response.BODY); +const body = response.BODY; // Printing if the method call was SUCCESS, this does not mean the payment was a success console.log(body.resultInfo.code); @@ -454,7 +454,7 @@ Following are the important parameters that you can provide for this method: ```javascript const response = await PAYPAY.PaymentCancel([merchantPaymentId]); -const body = JSON.parse(response.BODY); +const body = response.BODY; // Printing if the method call was SUCCESS console.log(body.resultInfo.code); ``` @@ -475,7 +475,7 @@ So the user has decided to return the goods they have purchased and needs to be |reason | No |integer <= 11 characters |The reason for refund | ```javascript - let payload = { +let payload = { merchantRefundId: 'merchant_refund_id', paymentId: 'paypay_payment_id', amount: { @@ -486,7 +486,7 @@ So the user has decided to return the goods they have purchased and needs to be }; // Calling the method to refund a Payment const response = await PAYPAY.PaymentRefund(payload); -const body = JSON.parse(response.BODY); +const body = response.BODY; // Printing if the method call was SUCCESS console.log(body.resultInfo.code); }); @@ -509,7 +509,7 @@ So you want to confirm the status of the refund, maybe because the request for t ```javascript let merchantPaymentId = 'merchantRefundId' const response = await PAYPAY.GetRefundDetails([merchantRefundId]); -const body = JSON.parse(response.BODY); +const body = response.BODY; // Printing if the method call was SUCCESS console.log(body.resultInfo.code); ``` diff --git a/src/lib/httpsClient.ts b/src/lib/httpsClient.ts index af80483e..0574c742 100644 --- a/src/lib/httpsClient.ts +++ b/src/lib/httpsClient.ts @@ -2,7 +2,7 @@ import * as https from "https"; export interface HttpsClientSuccess { STATUS: number; - BODY: string; + BODY: object | null; } export interface HttpsClientError { @@ -52,7 +52,20 @@ export class HttpsClient { if (status < 200 || status > 299) { this.printDebugMessage(status, body, apiName); } - callback({ STATUS: status, BODY: body }); + let parsed; + try { + parsed = body.match(/\S/) ? JSON.parse(body) : null; + } catch (e: any) { + callback({ STATUS: 500, ERROR: e.message }); + return; + } + + // Make the `BODY.toString()` return the raw JSON. + // This makes the library compatible with calls like `JSON.parse(response.BODY)`, + // which were required prior to version 2. + const responseObject = parsed && Object.assign(Object.create({ toString() { return body; } }), parsed); + + callback({ STATUS: status, BODY: responseObject }); }); }); @@ -66,5 +79,3 @@ export class HttpsClient { req.end(); } } - -export const httpsClient = new HttpsClient(); diff --git a/src/lib/paypay-rest-sdk.ts b/src/lib/paypay-rest-sdk.ts index 87a15656..b4a44fa7 100644 --- a/src/lib/paypay-rest-sdk.ts +++ b/src/lib/paypay-rest-sdk.ts @@ -3,7 +3,7 @@ */ import { Auth } from "./auth"; import { Conf } from "./conf"; -import { httpsClient, HttpsClientError, HttpsClientMessage, HttpsClientSuccess } from "./httpsClient"; +import { HttpsClient, HttpsClientError, HttpsClientMessage, HttpsClientSuccess } from "./httpsClient"; import { HmacSHA256, enc, algo } from "crypto-js"; import { v4 as uuidv4 } from "uuid"; import * as jwt from "jsonwebtoken"; @@ -19,12 +19,20 @@ class PayPayRestSDK { private perfMode: boolean = false; private readonly auth: Auth; private config: Conf; + private httpsClient: HttpsClient = new HttpsClient(); constructor() { this.config = new Conf(this.productionMode, this.perfMode); this.auth = new Auth(); } + /** + * Replace the HttpsClient that this SDK client instance uses for API calls. + */ + setHttpsClient(httpsClient: HttpsClient) { + this.httpsClient = httpsClient; + } + /** * Set authentication passed by end-user * @param clientConfig @@ -130,7 +138,7 @@ class PayPayRestSDK { callback?: HttpsClientMessage): Promise => { const options = this.paypaySetupOptions(endpoint, payload); return new Promise((resolve) => { - httpsClient.httpsCall(options, payload, (result) => { + this.httpsClient.httpsCall(options, payload, (result) => { resolve(result); if (callback !== undefined) { callback(result); diff --git a/test/accountLinkQRCodeCreate.test.ts b/test/accountLinkQRCodeCreate.test.ts index 42463b27..c42837df 100644 --- a/test/accountLinkQRCodeCreate.test.ts +++ b/test/accountLinkQRCodeCreate.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Account Link Create QR code', async () => { const response = { diff --git a/test/cancelPayment.test.ts b/test/cancelPayment.test.ts index e7d6edf8..9e965514 100644 --- a/test/cancelPayment.test.ts +++ b/test/cancelPayment.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Cancel Payment', async () => { const merchantPaymentId = [12393849]; diff --git a/test/cancelPendingOrder.test.ts b/test/cancelPendingOrder.test.ts index 85aeb388..937ffd84 100644 --- a/test/cancelPendingOrder.test.ts +++ b/test/cancelPendingOrder.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Cancel Pending Order', async () => { const merchantPaymentId = [12393849]; diff --git a/test/cashback.test.ts b/test/cashback.test.ts index 7c8ce7c5..49c8b581 100644 --- a/test/cashback.test.ts +++ b/test/cashback.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const { v4: uuidv4 } = require('uuid'); const conf = { @@ -11,6 +11,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Cash Back', async () => { const payload = { diff --git a/test/checkCashBackDetails.test.ts b/test/checkCashBackDetails.test.ts index 1c26fe84..584441ef 100644 --- a/test/checkCashBackDetails.test.ts +++ b/test/checkCashBackDetails.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: 'testId', @@ -10,13 +10,35 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Check cashback details', async () => { const merchantPaymentId = [12393849]; const response = { STATUS: 200, - BODY: '{"resultInfo":{"code":"SUCCESS","message":"Success","codeId":"08100001"},"data":{"status":"SUCCESS","acceptedAt":1611747653,"merchantAlias":"test","amount":{"amount":1,"currency":"JPY"},"requestedAt":1611747650,"metadata":"","cashbackId":"test","merchantCashbackId":"test","userAuthorizationId":"test","orderDescription":"order description","walletType":"PREPAID"}}' - } + BODY: { + "resultInfo": { + "code": "SUCCESS", + "message": "Success", + "codeId": "08100001", + }, + "data": { + "status": "SUCCESS", + "acceptedAt": 1611747653, + "merchantAlias": "test", + "amount": { "amount": 1, "currency": "JPY" }, + "requestedAt": 1611747650, + "metadata": "", + "cashbackId": "test", + "merchantCashbackId": "test", + "userAuthorizationId": "test", + "orderDescription": "order description", + "walletType": "PREPAID", + }, + }, + }; const mockHttpsCall = jest.spyOn(httpsClient, 'httpsCall'); mockHttpsCall.mockImplementation(jest.fn((_options: any, _payload = '', _callback: any) => { diff --git a/test/checkCashBackReversalDetails.test.ts b/test/checkCashBackReversalDetails.test.ts index cf1a23cd..f94dd790 100644 --- a/test/checkCashBackReversalDetails.test.ts +++ b/test/checkCashBackReversalDetails.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: 'test', @@ -10,13 +10,33 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Check cashback reversal details', async () => { const merchantPaymentId = [12393849]; const response = { STATUS: 200, - BODY: '{"resultInfo":{"code":"SUCCESS","message":"Success","codeId":"08100001"},"data":{"status":"SUCCESS","acceptedAt":1611747702,"merchantAlias":"test","amount":{"amount":1,"currency":"JPY"},"requestedAt":1611747699,"metadata":"","cashbackReversalId":"test","merchantCashbackReversalId":"test","merchantCashbackId":"test"}}' - } + BODY: { + "resultInfo": { + "code": "SUCCESS", + "message": "Success", + "codeId": "08100001", + }, + "data": { + "status": "SUCCESS", + "acceptedAt": 1611747702, + "merchantAlias": "test", + "amount": { "amount": 1, "currency": "JPY" }, + "requestedAt": 1611747699, + "metadata": "", + "cashbackReversalId": "test", + "merchantCashbackReversalId": "test", + "merchantCashbackId": "test", + }, + }, + }; const mockHttpsCall = jest.spyOn(httpsClient, 'httpsCall'); mockHttpsCall.mockImplementation(jest.fn((_options: any, _payload = '', _callback: any) => { diff --git a/test/createPayment.test.ts b/test/createPayment.test.ts index 9f2f8476..63528088 100644 --- a/test/createPayment.test.ts +++ b/test/createPayment.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const { v4: uuidv4 } = require('uuid'); const conf = { @@ -11,6 +11,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Create Payment', async () => { const payload = { @@ -39,7 +42,7 @@ test('Unit Test - Create Payment', async () => { "assumeMerchant": "1609155081" } } - const expected = { STATUS: 200, BODY: JSON.stringify(response) }; + const expected = { STATUS: 200, BODY: response }; const mockHttpsCall = jest.spyOn(httpsClient, 'httpsCall'); mockHttpsCall.mockImplementation(jest.fn((_options: any, _payload = '', _callback: any) => { @@ -85,7 +88,7 @@ test('Unit Test - Create Payment with agreeSimilarTransaction=false', async () = "assumeMerchant": "1609155081" } } - const expected = { STATUS: 200, BODY: JSON.stringify(response) }; + const expected = { STATUS: 200, BODY: response }; const mockHttpsCall = jest.spyOn(httpsClient, 'httpsCall'); mockHttpsCall.mockImplementation(jest.fn((_options: any, _payload = '', _callback: any) => { @@ -131,7 +134,7 @@ test('Unit Test - Create Payment with agreeSimilarTransaction=true', async () => "assumeMerchant": "1609155081" } } - const expected = { STATUS: 200, BODY: JSON.stringify(response) }; + const expected = { STATUS: 200, BODY: response }; const mockHttpsCall = jest.spyOn(httpsClient, 'httpsCall'); mockHttpsCall.mockImplementation(jest.fn((_options: any, _payload = '', _callback: any) => { diff --git a/test/createPendingPayment.test.ts b/test/createPendingPayment.test.ts index 16772b6f..6beea37f 100644 --- a/test/createPendingPayment.test.ts +++ b/test/createPendingPayment.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Create Pending Payment', async () => { const payload = { diff --git a/test/getCodePaymentDetails.test.ts b/test/getCodePaymentDetails.test.ts index 4a841cd4..d87880ba 100644 --- a/test/getCodePaymentDetails.test.ts +++ b/test/getCodePaymentDetails.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Get Code Payment Details', async () => { const merchantPaymentId = [12393849]; diff --git a/test/getPaymentDetails.test.ts b/test/getPaymentDetails.test.ts index 52d3057d..68404153 100644 --- a/test/getPaymentDetails.test.ts +++ b/test/getPaymentDetails.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Get Payment Details', async () => { const merchantPaymentId = [12393849]; diff --git a/test/getPendingPaymentDetails.test.ts b/test/getPendingPaymentDetails.test.ts index 61b2d9a7..b34ac7f7 100644 --- a/test/getPendingPaymentDetails.test.ts +++ b/test/getPendingPaymentDetails.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Get Pending Order Details', async () => { const merchantPaymentId = [12393849]; diff --git a/test/getRefundDetails.test.ts b/test/getRefundDetails.test.ts index ea72def3..f6282725 100644 --- a/test/getRefundDetails.test.ts +++ b/test/getRefundDetails.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Get Refund Details', async () => { const merchantRefundId = [34243242]; diff --git a/test/getUserAuthorizationStatus.test.ts b/test/getUserAuthorizationStatus.test.ts index 2a2a4d4b..49b78251 100644 --- a/test/getUserAuthorizationStatus.test.ts +++ b/test/getUserAuthorizationStatus.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Get User Authorization Status', async () => { const userAuthorizationId = [6787435345]; const response = { @@ -20,14 +23,14 @@ test('Unit Test - Get User Authorization Status', async () => { }, "data": { "userAuthorizationId": "6787435345", - "referenceIds": [ ], + "referenceIds": [], "status": "ACTIVE", "scopes": [ - "continuous_payments" + "continuous_payments" ], "expireAt": 34534543534, "issuedAt": 45353535343 - } + } }; const mockHttpsCall = jest.spyOn(httpsClient, 'httpsCall'); diff --git a/test/httpsClient.test.ts b/test/httpsClient.test.ts index 987a3ebd..3116e795 100644 --- a/test/httpsClient.test.ts +++ b/test/httpsClient.test.ts @@ -1,4 +1,6 @@ -import { httpsClient } from "../src/lib/httpsClient"; +import { HttpsClient } from "../src/lib/httpsClient"; + +const httpsClient = new HttpsClient(); jest.mock("https", () => ({ __esModule: true, @@ -13,12 +15,67 @@ jest.mock("https", () => ({ var httpsRequestMock: any; +test("httpsClient.httpsCall 200 handle empty response", () => { + jest.clearAllMocks(); + + const options = { apiKey: "options", path: "/some/path", method: "POST" }; + const payload = { payload: true }; + + const expectedBodyChunks: string[] = []; + const expected = { STATUS: 200, BODY: null }; + + const callback = jest.fn(); + + httpsClient.httpsCall(options, payload, callback); + + expect(httpsRequestMock).toHaveBeenCalledWith({ path: "/some/path", method: "POST" }, expect.anything()); + expect("apiKey" in options).toEqual(false); + + const req = httpsRequestMock.mock.results[0].value; + + // Error listener must be set up. + expect(req.on).toHaveBeenCalledWith("error", expect.anything()); + expect(req.write).toHaveBeenCalledWith(JSON.stringify(payload)); + expect(req.end).toHaveBeenCalled(); + + const res = { + statusCode: 200, + setEncoding: jest.fn(), + on: jest.fn(), + }; + const resCallback = httpsRequestMock.mock.calls[0][1]; + resCallback(res); + + expect(res.setEncoding).toHaveBeenCalledWith("utf8"); + expect(res.on).toHaveBeenCalledWith("data", expect.anything()); + expect(res.on).toHaveBeenCalledWith("end", expect.anything()); + + // The data is received chunk-by-chunk. + const onDataCallback = res.on.mock.calls[0]; + expect(onDataCallback[0]).toEqual("data"); + for (const chunk of expectedBodyChunks) { + onDataCallback[1](chunk); + + // The callback is not invoked until the response is completed. + expect(callback).toHaveBeenCalledTimes(0); + } + + const onEndCallback = res.on.mock.calls[1]; + expect(onEndCallback[0]).toEqual("end"); + onEndCallback[1](); + + // The passed callback is invoked after the on-end event. + expect(callback).toHaveBeenCalledWith(expected); +}); + test("httpsClient.httpsCall POST 200", () => { + jest.clearAllMocks(); + const options = { apiKey: "options", path: "/some/path", method: "POST" }; const payload = { payload: true }; - const expectedBodyChunks = ["ab", "cdef", "g", "hij"]; - const expected = { STATUS: 200, BODY: expectedBodyChunks.join("") }; + const expectedBodyChunks = ["{", "\"", "k", "\": ", "1}"]; + const expected = { STATUS: 200, BODY: { k: 1 } }; const callback = jest.fn(); @@ -62,4 +119,72 @@ test("httpsClient.httpsCall POST 200", () => { // The passed callback is invoked after the on-end event. expect(callback).toHaveBeenCalledWith(expected); + + // Prior to version 2, the SDK returned a string instead of an object. + // For compatibility, ensure that `JSON.parse(response.BODY)` still works. + const call = callback.mock.calls[0]; + expect(JSON.parse(call[0].BODY)).toEqual(expected.BODY); +}); + +test("httpsClient.httpsCall POST 400", () => { + jest.clearAllMocks(); + + const consoleLogSpy = jest.spyOn(console, "log").mockImplementation(() => { }); + + const options = { apiKey: "options", path: "/some/path", method: "POST" }; + const payload = { payload: true }; + + const expectedBodyChunks = [`{"resultInfo": {"code": "CODE", "codeId": "CODEID"}}`]; + const expected = { + STATUS: 400, + BODY: { "resultInfo": { "code": "CODE", "codeId": "CODEID" } }, + }; + + const callback = jest.fn(); + + httpsClient.httpsCall(options, payload, callback); + + expect(httpsRequestMock).toHaveBeenCalledWith({ path: "/some/path", method: "POST" }, expect.anything()); + expect("apiKey" in options).toEqual(false); + + const req = httpsRequestMock.mock.results[0].value; + + // Error listener must be set up. + expect(req.on).toHaveBeenCalledWith("error", expect.anything()); + expect(req.write).toHaveBeenCalledWith(JSON.stringify(payload)); + expect(req.end).toHaveBeenCalled(); + + const res = { + statusCode: 400, + setEncoding: jest.fn(), + on: jest.fn(), + }; + const resCallback = httpsRequestMock.mock.calls[0][1]; + resCallback(res); + + expect(res.setEncoding).toHaveBeenCalledWith("utf8"); + expect(res.on).toHaveBeenCalledWith("data", expect.anything()); + expect(res.on).toHaveBeenCalledWith("end", expect.anything()); + + // The data is received chunk-by-chunk. + const onDataCallback = res.on.mock.calls[0]; + expect(onDataCallback[0]).toEqual("data"); + for (const chunk of expectedBodyChunks) { + onDataCallback[1](chunk); + + // The callback is not invoked until the response is completed. + expect(callback).toHaveBeenCalledTimes(0); + } + + const onEndCallback = res.on.mock.calls[1]; + expect(onEndCallback[0]).toEqual("end"); + onEndCallback[1](); + + // The passed callback is invoked after the on-end event. + expect(callback).toHaveBeenCalledWith(expected); + + // Expect a console log to have been produced. + expect(consoleLogSpy).toHaveBeenCalled(); + expect(consoleLogSpy.mock.calls[0][0]).toContain("https://developer.paypay.ne.jp/develop/resolve?api_name=options&code=CODE&code_id=CODEID"); + consoleLogSpy.mockRestore(); }); diff --git a/test/paymentAuthCapture.test.ts b/test/paymentAuthCapture.test.ts index 693e84ad..d08fe2ce 100644 --- a/test/paymentAuthCapture.test.ts +++ b/test/paymentAuthCapture.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Payment Auth Capture', async () => { const payload = { @@ -20,7 +23,7 @@ test('Unit Test - Payment Auth Capture', async () => { }, merchantCaptureId: "3432424", requestedAt: 324234234, - orderDescription: "Test Description" + orderDescription: "Test Description", }; const response = { diff --git a/test/paymentAuthRevert.test.ts b/test/paymentAuthRevert.test.ts index b6d79cd5..01621af9 100644 --- a/test/paymentAuthRevert.test.ts +++ b/test/paymentAuthRevert.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Payment Auth Revert', async () => { const payload = { diff --git a/test/paymentPreauthorize.test.ts b/test/paymentPreauthorize.test.ts index 3aeab59e..c7405bba 100644 --- a/test/paymentPreauthorize.test.ts +++ b/test/paymentPreauthorize.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const { v4: uuidv4 } = require('uuid'); const conf = { @@ -11,6 +11,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Preauthorize Payment', async () => { const payload = { @@ -42,10 +45,10 @@ test('Unit Test - Preauthorize Payment', async () => { const mockHttpsCall = jest.spyOn(httpsClient, 'httpsCall'); mockHttpsCall.mockImplementation(jest.fn((_options: any, _payload = '', _callback: any) => { - _callback({ STATUS: 200, BODY: JSON.stringify(response) }); + _callback({ STATUS: 200, BODY: response }); })); - const expected = { STATUS: 200, BODY: JSON.stringify(response) }; + const expected = { STATUS: 200, BODY: response }; const promiseResult = await payPayRestSDK.paymentPreauthorize(payload, (result: any) => { expect(result).toEqual(expected); }); @@ -88,10 +91,10 @@ test('Unit Test - Preauthorize Payment with agreeSimilarTransaction=false', asyn const mockHttpsCall = jest.spyOn(httpsClient, 'httpsCall'); mockHttpsCall.mockImplementation(jest.fn((_options: any, _payload = '', _callback: any) => { - _callback({ STATUS: 200, BODY: JSON.stringify(response) }); + _callback({ STATUS: 200, BODY: response }); })); - const expected = { STATUS: 200, BODY: JSON.stringify(response) }; + const expected = { STATUS: 200, BODY: response }; const promiseResult = await payPayRestSDK.paymentPreauthorize(payload, false, (result: any) => { expect(result).toEqual(expected); }); @@ -134,10 +137,10 @@ test('Unit Test - Preauthorize Payment with agreeSimilarTransaction=true', async const mockHttpsCall = jest.spyOn(httpsClient, 'httpsCall'); mockHttpsCall.mockImplementation(jest.fn((_options: any, _payload = '', _callback: any) => { - _callback({ STATUS: 200, BODY: JSON.stringify(response) }); + _callback({ STATUS: 200, BODY: response }); })); - const expected = { STATUS: 200, BODY: JSON.stringify(response) }; + const expected = { STATUS: 200, BODY: response }; const promiseResult = await payPayRestSDK.paymentPreauthorize(payload, true, (result: any) => { expect(result).toEqual(expected); }); diff --git a/test/paymentSubscription.test.ts b/test/paymentSubscription.test.ts index 98693e2e..bf2eb96c 100644 --- a/test/paymentSubscription.test.ts +++ b/test/paymentSubscription.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Payment Subscription', async () => { const payload = { diff --git a/test/qrCodeCreate.test.ts b/test/qrCodeCreate.test.ts index ec13bc75..12b4ab1c 100644 --- a/test/qrCodeCreate.test.ts +++ b/test/qrCodeCreate.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Create QR code', async () => { const payload = { diff --git a/test/qrCodeCreateWithMerchantNotSpecified.test.ts b/test/qrCodeCreateWithMerchantNotSpecified.test.ts index 023f5e1f..e726cd21 100644 --- a/test/qrCodeCreateWithMerchantNotSpecified.test.ts +++ b/test/qrCodeCreateWithMerchantNotSpecified.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -9,6 +9,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Create QR code without specifying the merchant id', async () => { const payload = { diff --git a/test/qrCodeDelete.test.ts b/test/qrCodeDelete.test.ts index 65663d46..3bb89537 100644 --- a/test/qrCodeDelete.test.ts +++ b/test/qrCodeDelete.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Delete QR code', async () => { const qrCodeId = [874878]; diff --git a/test/refundPayment.test.ts b/test/refundPayment.test.ts index b4507824..17c28895 100644 --- a/test/refundPayment.test.ts +++ b/test/refundPayment.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Refund Payment', async () => { const payload = { diff --git a/test/refundPendingPayment.test.ts b/test/refundPendingPayment.test.ts index 24329569..11abfd0c 100644 --- a/test/refundPendingPayment.test.ts +++ b/test/refundPendingPayment.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Refund Pending Payment', async () => { const payload = { diff --git a/test/reversalCashBack.test.ts b/test/reversalCashBack.test.ts index 103f4a0e..94b566ff 100644 --- a/test/reversalCashBack.test.ts +++ b/test/reversalCashBack.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const { v4: uuidv4 } = require('uuid'); const conf = { @@ -11,6 +11,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Reversal Cash Back', async () => { const payload = { diff --git a/test/unlinkUser.test.ts b/test/unlinkUser.test.ts index b851e833..918888f5 100644 --- a/test/unlinkUser.test.ts +++ b/test/unlinkUser.test.ts @@ -1,5 +1,5 @@ import { payPayRestSDK } from "../src/lib/paypay-rest-sdk"; -import { httpsClient } from '../src/lib/httpsClient'; +import { HttpsClient } from '../src/lib/httpsClient'; const conf = { clientId: '5345435fsdfsr54353454', @@ -10,6 +10,9 @@ const conf = { payPayRestSDK.configure(conf); +const httpsClient = new HttpsClient(); +payPayRestSDK.setHttpsClient(httpsClient); + test('Unit Test - Unlink user', async () => { const userAuthorizationId = [6787435345]; const response = {