UNPKG

@adyen/api-library

Version:

The Adyen API Library for NodeJS enables you to work with Adyen APIs.

232 lines 11.8 kB
"use strict"; /* * ###### * ###### * ############ ####( ###### #####. ###### ############ ############ * ############# #####( ###### #####. ###### ############# ############# * ###### #####( ###### #####. ###### ##### ###### ##### ###### * ###### ###### #####( ###### #####. ###### ##### ##### ##### ###### * ###### ###### #####( ###### #####. ###### ##### ##### ###### * ############# ############# ############# ############# ##### ###### * ############ ############ ############# ############ ##### ###### * ###### * ############# * ############ * Adyen NodeJS API Library * Copyright (c) 2020 Adyen B.V. * This file is open source and available under the MIT license. * See the LICENSE file for more info. */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const https_1 = require("https"); const https_proxy_agent_1 = require("https-proxy-agent"); const fs = __importStar(require("fs")); const url_1 = require("url"); const libraryConstants_1 = __importDefault(require("../constants/libraryConstants")); const httpClientException_1 = __importDefault(require("./httpClientException")); const apiException_1 = __importDefault(require("../services/exception/apiException")); const apiConstants_1 = require("../constants/apiConstants"); const checkServerIdentity_1 = __importDefault(require("../helpers/checkServerIdentity")); class HttpURLConnectionClient { /** * Sends an HTTP request to the specified endpoint with the provided JSON payload and configuration. * * This method sets up request headers, including authentication (API key or basic auth), content type, * and timeout. If a certificate path is provided in the config, it installs a certificate verifier. * Throws an ApiException when an error occurs (invalid API key, API error response, etc.). * * @param endpoint - The URL to which the request will be sent. * @param json - The JSON string to be sent as the request body. * @param config - The configuration object containing authentication, timeout, and certificate details. * @param isApiRequired - Indicates whether an API key is required for this request. * @param requestOptions - Additional options for the HTTP request, such as headers and timeout. * @returns A promise that resolves with the response body as a string. * @throws {ApiException} when an error occurs */ request(endpoint, json, config, isApiRequired, requestOptions) { var _a; (_a = requestOptions.headers) !== null && _a !== void 0 ? _a : (requestOptions.headers = {}); requestOptions.timeout = config.connectionTimeoutMillis; if (config.certificatePath) { this.installCertificateVerifier(config.certificatePath); } const apiKey = config.apiKey; if (isApiRequired && !apiKey) { return Promise.reject(new apiException_1.default("Invalid X-API-Key was used", 401)); } if (apiKey) { requestOptions.headers[apiConstants_1.ApiConstants.API_KEY] = apiKey; } else { const authString = `${config.username}:${config.password}`; const authStringEnc = Buffer.from(authString, "utf8").toString("base64"); requestOptions.headers.Authorization = `Basic ${authStringEnc}`; } requestOptions.headers[apiConstants_1.ApiConstants.CONTENT_TYPE] = apiConstants_1.ApiConstants.APPLICATION_JSON_TYPE; const httpConnection = this.createRequest(endpoint, requestOptions, config.applicationName); return this.doRequest(httpConnection, json); } createRequest(endpoint, requestOptions, applicationName) { if (!requestOptions.headers) { requestOptions.headers = {}; } const url = new url_1.URL(endpoint); requestOptions.hostname = url.hostname; requestOptions.protocol = url.protocol; requestOptions.port = url.port; requestOptions.path = url.pathname; if (requestOptions.params) { requestOptions.path += "?" + new url_1.URLSearchParams(requestOptions.params).toString(); } if (requestOptions && requestOptions.idempotencyKey) { requestOptions.headers[apiConstants_1.ApiConstants.IDEMPOTENCY_KEY] = requestOptions.idempotencyKey; delete requestOptions.idempotencyKey; } if (this.proxy && this.proxy.host) { const { host, port, ...options } = this.proxy; requestOptions.agent = new https_proxy_agent_1.HttpsProxyAgent({ host, port: port || 443, ...options }); } else { requestOptions.agent = new https_1.Agent(this.agentOptions); } requestOptions.headers["Cache-Control"] = "no-cache"; if (!requestOptions.method) { requestOptions.method = apiConstants_1.ApiConstants.METHOD_POST; } requestOptions.headers[apiConstants_1.ApiConstants.ACCEPT_CHARSET] = HttpURLConnectionClient.CHARSET; // user-agent header const libInfo = `${libraryConstants_1.default.LIB_NAME}/${libraryConstants_1.default.LIB_VERSION}`; requestOptions.headers[apiConstants_1.ApiConstants.USER_AGENT] = applicationName ? `${applicationName} ${libInfo}` : libInfo; // custom headers requestOptions.headers[apiConstants_1.ApiConstants.ADYEN_LIBRARY_NAME] = libraryConstants_1.default.LIB_NAME; requestOptions.headers[apiConstants_1.ApiConstants.ADYEN_LIBRARY_VERSION] = libraryConstants_1.default.LIB_VERSION; // create a new ClientRequest object const req = (0, https_1.request)(requestOptions); // set the timeout on the ClientRequest instance if (requestOptions.timeout) { req.setTimeout(requestOptions.timeout); } return req; } doRequest(connectionRequest, json) { return new Promise((resolve, reject) => { connectionRequest.flushHeaders(); connectionRequest.on("response", (res) => { const response = { statusCode: res.statusCode, headers: res.headers, body: "" }; // define default exception (in case of error during the handling of the response) const getException = (responseBody) => new httpClientException_1.default({ message: `HTTP Exception: ${response.statusCode}. ${res.statusMessage}`, statusCode: response.statusCode, errorCode: undefined, responseHeaders: response.headers, responseBody, }); let exception = getException(response.body); res.on("data", (chunk) => { response.body += chunk; }); res.on("end", () => { if (!res.complete) { reject(new Error("The connection was terminated while the message was still being sent")); } if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) { // API error handling try { const formattedData = JSON.parse(response.body); const isApiError = "status" in formattedData; const isRequestError = "errors" in formattedData; if (isApiError) { // Adyen API has returned an error exception = new httpClientException_1.default({ message: `HTTP Exception: ${formattedData.status}. ${res.statusMessage}: ${formattedData.message}`, statusCode: formattedData.status, errorCode: formattedData.errorCode, responseHeaders: res.headers, responseBody: response.body, apiError: formattedData, }); } else if (isRequestError) { exception = new Error(response.body); } else { exception = getException(response.body); } } catch (e) { // parsing error exception = new httpClientException_1.default({ message: `HTTP Exception: ${response.statusCode}. Error parsing response: ${e.message}`, statusCode: response.statusCode, responseHeaders: response.headers, responseBody: response.body, }); } return reject(exception); } resolve(response.body); }); res.on("error", reject); }); connectionRequest.on("timeout", () => { connectionRequest.abort(); }); connectionRequest.on("error", (e) => reject(new apiException_1.default(e.message))); connectionRequest.write(Buffer.from(json)); connectionRequest.end(); }); } installCertificateVerifier(terminalCertificatePath) { try { if (terminalCertificatePath == "unencrypted") { this.agentOptions = { rejectUnauthorized: false }; } else { const certificateInput = fs.readFileSync(terminalCertificatePath); this.agentOptions = { ca: certificateInput, checkServerIdentity: checkServerIdentity_1.default, }; } } catch (e) { const message = e instanceof Error ? e.message : "undefined"; return Promise.reject(new httpClientException_1.default({ message: `Error loading certificate from path: ${message}` })); } } } HttpURLConnectionClient.CHARSET = "utf-8"; exports.default = HttpURLConnectionClient; //# sourceMappingURL=httpURLConnectionClient.js.map