diff --git a/.env b/.env index 2d77749..d40080e 100644 --- a/.env +++ b/.env @@ -28,6 +28,7 @@ PAYMENT_GATEWAY_SAVED_CARD_LIMIT_FRAME = PAYMENT_GATEWAY_DECISION_SYNC = PAYMENT_GATEWAY_DECISION_MANAGER = +PAYMENT_GATEWAY_ENABLE_MOTO = PAYMENT_GATEWAY_RUN_SYNC = PAYMENT_GATEWAY_DECISION_SYNC_MULTI_MID = PAYMENT_GATEWAY_NETWORK_TOKEN_MULTI_MID = diff --git a/docs/Commercetools-Setup.md b/docs/Commercetools-Setup.md index 8497254..6bdc084 100644 --- a/docs/Commercetools-Setup.md +++ b/docs/Commercetools-Setup.md @@ -142,7 +142,6 @@ Fields | isv_payerEnrollStatus | String | false || | isv_payerEnrollHttpCode | Number | false || | isv_saleEnabled | Boolean | false || -| isv_enabledMoto | Boolean | false || | isv_walletType | String | false || | isv_accountNumber | String | false || | isv_accountType | String | false || diff --git a/docs/PayPal-setup.md b/docs/PayPal-setup.md index 510fa7f..b431c42 100644 --- a/docs/PayPal-setup.md +++ b/docs/PayPal-setup.md @@ -33,4 +33,4 @@ Once your merchant Id is configured with Cybersource, you can integrate PayPal a - Display PayPal as a payment option during the checkout process.You can get the PayPal payment Logo from [PayPal Logo Centre](https://www.paypal.com/in/webapps/mpp/logo-center) -After selecting PayPal as the payment method, you can continue to theĀ [Process a Payment (PayPal)](Process-a-Payment-PayPal.md) process. +After selecting PayPal as the payment method, you can continue to theĀ [Process a Payment (PayPal)](Process-a-Payment-PayPal.md) process. \ No newline at end of file diff --git a/docs/Process-a-Payment-MOTO.md b/docs/Process-a-Payment-MOTO.md index 61b4f93..646d914 100644 --- a/docs/Process-a-Payment-MOTO.md +++ b/docs/Process-a-Payment-MOTO.md @@ -82,19 +82,17 @@ For the Commercetools Extension to support MOTO transaction, follow the steps me - [Process a Payment With eCheck](./Process-a-Payment-eCheck.md) - and add the following properties - | Property | Value | Required | Notes | - | ----------------------------- | -------------------------------- | -------- | ------------------------------------------------------------------------------------------------------- | - | custom.fields.isv_enabledMoto | Flag Indicating MOTO transaction | Yes | Boolean value. Used by the extention to identify whether it is a normal transaction or MOTO transaction | + and ensure the environment variable `PAYMENT_GATEWAY_ENABLE_MOTO` is set to `true` in your server configuration to enable MOTO transaction processing. + 5. Add the payment to the cart -6. Update the Commercetools payment () with the fields mentioned in the step 5 of [Process a Card Payment Without Payer Authentication](./Process-a-Card-Payment-Without-Payer-Authentication.md) along with the below data - | Property | Value | Required | Notes | - | ----------------------------- | -------------------------------- | -------- | ------------------------------------------------------------------------------------------------------- | - | custom.fields.isv_enabledMoto | Flag Indicating MOTO transaction | Yes | Boolean value. Used by the extention to identify whether it is a normal transaction or MOTO transaction | +6. Update the Commercetools payment () with the fields mentioned in the step 5 of [Process a Card Payment Without Payer Authentication](./Process-a-Card-Payment-Without-Payer-Authentication.md) + + > **_NOTE:_** MOTO transactions are controlled server-side via the `PAYMENT_GATEWAY_ENABLE_MOTO` environment variable. Set this to `true` in your deployment configuration to enable MOTO processing. + 7. Add a transaction to the payment diff --git a/package.json b/package.json index a1ca9cd..246ed54 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "commercetools-extension", - "version": "25.3.0", + "version": "25.3.1", "description": "Payment Services Commercetools Extension", "main": "build/main/index.js", "typings": "build/main/index.d.ts", @@ -84,6 +84,7 @@ "jsonwebtoken": "^9.0.2", "jwk-to-pem": "^2.0.5", "jwt-decode": "^4.0.0", + "node-fetch": "^3.3.2", "moment": "^2.30.1", "npm-run-all": "^4.1.5", "nyc": "^15.1.0", @@ -100,6 +101,7 @@ "@types/jsdom": "^21.1.7", "@types/memory-cache": "^0.2.6", "@types/node-forge": "^1.3.11", + "@types/node": "^20.11.30", "@typescript-eslint/eslint-plugin": "^7.9.0", "@typescript-eslint/parser": "^7.9.0", "ava": "6.3.0", diff --git a/src/apiController.ts b/src/apiController.ts index 92ef7a6..7865b39 100644 --- a/src/apiController.ts +++ b/src/apiController.ts @@ -8,7 +8,7 @@ import captureContext from './service/payment/CaptureContextService'; import flexKeys from './service/payment/FlexKeys'; import getCardByInstrument from './service/payment/GetCardByInstrumentId'; import keyVerification from './service/payment/GetPublicKeys'; -import { ActionResponseType, AmountPlannedType } from './types/Types'; +import { ActionResponseType, AmountPlannedType, CustomerTokensType } from './types/Types'; import { ApiError, errorHandler, PaymentProcessingError } from './utils/ErrorHandler'; import paymentActions from './utils/PaymentActions'; import paymentHandler from './utils/PaymentHandler'; @@ -18,6 +18,81 @@ import orderManagementHelper from './utils/helpers/OrderManagementHelper'; import payerAuthHelper from './utils/helpers/PayerAuthHelper'; import paymentHelper from './utils/helpers/PaymentHelper'; +/* START GENAI */ +/** + * Allowed fields for the CustomerTokensType schema. + * Only these string fields are expected in a valid token object. + */ +const ALLOWED_TOKEN_FIELDS: (keyof CustomerTokensType)[] = [ + 'alias', 'value', 'paymentToken', 'instrumentIdentifier', + 'cardType', 'cardName', 'cardNumber', 'cardExpiryMonth', + 'cardExpiryYear', 'addressId', 'timestamp', 'address', +]; + +/** + * Validates the parsed token object against the expected CustomerTokensType schema. + * Ensures the object is a plain object, contains only allowed fields, + * and that required fields (paymentToken, value) are non-empty strings. + * + * @param {any} tokenObj - The parsed token object to validate. + * @returns {boolean} - True if the object conforms to the expected schema. + */ +const isValidTokenSchema = (tokenObj: any): tokenObj is Partial => { + if (!tokenObj || typeof tokenObj !== 'object' || Array.isArray(tokenObj)) { + return false; + } + const tokenKeys = Object.keys(tokenObj); + for (const key of tokenKeys) { + if (!ALLOWED_TOKEN_FIELDS.includes(key as keyof CustomerTokensType)) { + return false; + } + } + if (!tokenObj.paymentToken || typeof tokenObj.paymentToken !== 'string' || tokenObj.paymentToken.trim().length === 0) { + return false; + } + if (!tokenObj.value || typeof tokenObj.value !== 'string' || tokenObj.value.trim().length === 0) { + return false; + } + for (const key of tokenKeys) { + if (key !== 'address' && tokenObj[key] !== undefined && typeof tokenObj[key] !== 'string') { + return false; + } + } + return true; +}; + +/** + * Verifies that the token identified by paymentToken belongs to the customer + * by fetching the customer's authoritative isv_tokens from the server-side + * commercetools API and validating the paymentToken against that source. + * + * @param {string} paymentToken - The paymentToken to verify ownership of. + * @param {string} customerId - The customer ID to fetch authoritative data for. + * @returns {Promise} - True if the paymentToken is found in the customer's server-side tokens. + */ +const isTokenOwnedByCustomer = async (paymentToken: string, customerId: string): Promise => { + if (!paymentToken || !customerId) { + return false; + } + const customerInfo = await commercetoolsApi.getCustomer(customerId); + const serverTokens = customerInfo?.custom?.fields?.isv_tokens; + if (!serverTokens || !Array.isArray(serverTokens) || serverTokens.length === 0) { + return false; + } + for (const tokenStr of serverTokens) { + try { + const token = JSON.parse(tokenStr); + if (token && token.paymentToken === paymentToken) { + return true; + } + } catch { + continue; + } + } + return false; +}; +/* END GENAI */ + /** @@ -115,11 +190,19 @@ const customerUpdateApi = async (customerObj: any): Promise response = await paymentHandler.handleCardAddition(customerObj.id, customerAddress, customerObj); } else if (isv_tokens && 0 < isv_tokens?.length) { const tokensToUpdate = JSON.parse(customerObj.custom.fields.isv_tokens[0]); + /* START GENAI */ + if (Constants.ISV_TOKEN_ACTION_DELETE === isv_tokenAction || Constants.ISV_TOKEN_ACTION_UPDATE === isv_tokenAction) { + if (!isValidTokenSchema(tokensToUpdate) || !(await isTokenOwnedByCustomer(tokensToUpdate.paymentToken as string, customerObj.id))) { + paymentUtils.logData(__filename, FunctionConstant.FUNC_CUSTOMER_UPDATE_API, Constants.LOG_ERROR, '', CustomMessages.ERROR_MSG_INVALID_TOKEN_DATA); + return response; + } + } + /* END GENAI */ switch (isv_tokenAction) { - case 'delete': + case Constants.ISV_TOKEN_ACTION_DELETE: response = await paymentHandler.handleCardDeletion(tokensToUpdate, customerObj.id); break; - case 'update': + case Constants.ISV_TOKEN_ACTION_UPDATE: response = await paymentHandler.handleUpdateCard(tokensToUpdate, customerObj.id, customerObj); break; default: @@ -238,16 +321,35 @@ const orderManagementApi = async (paymentId: string, transactionAmount: number | pendingAmount = orderManagementHelper.getCapturedAmount(paymentObject); break; } - if (0 === transactionAmount) { + /* START GENAI */ + if (Constants.CT_TRANSACTION_TYPE_CANCEL_AUTHORIZATION === transactionType) { + amountPlanned = { ...paymentObject.amountPlanned }; + const transactionObject = paymentUtils.createTransactionObject(paymentObject.version, amountPlanned, transactionType, Constants.CT_TRANSACTION_STATE_INITIAL, undefined, undefined); + /* END GENAI */ + const addTransaction = await commercetoolsApi.addTransaction(transactionObject, paymentId); + if (addTransaction && addTransaction.transactions?.length) { + const transactionLength = addTransaction.transactions.length; + const latestTransaction = addTransaction.transactions[transactionLength - 1]; + if (latestTransaction && Constants.CT_TRANSACTION_STATE_SUCCESS === latestTransaction.state) { + if (latestTransaction?.type) { + apiResponse.successMessage = paymentUtils.handleOmSuccessMessage(latestTransaction.type); + } + } else { + apiResponse.errorMessage = paymentUtils.handleOMErrorMessage(2, transactionType); + } + } else { + apiResponse.errorMessage = CustomMessages.ERROR_MSG_ADD_TRANSACTION_DETAILS; + } + /* START GENAI */ + } else if (!transactionAmount || transactionAmount <= 0) { apiResponse.errorMessage = paymentUtils.handleOMErrorMessage(0, transactionType); - } else if (pendingAmount && transactionAmount && transactionAmount > pendingAmount) { + } else if (pendingAmount && transactionAmount > pendingAmount) { apiResponse.errorMessage = paymentUtils.handleOMErrorMessage(1, transactionType); } else { - if (transactionAmount) { - amountPlanned = paymentObject.amountPlanned; - amountPlanned.centAmount = paymentUtils.convertAmountToCent(transactionAmount, fractionDigits) - } - const transactionObject = paymentUtils.createTransactionObject(paymentObject.version, paymentObject.amountPlanned, transactionType, Constants.CT_TRANSACTION_STATE_INITIAL, undefined, undefined); + amountPlanned = { ...paymentObject.amountPlanned }; + amountPlanned.centAmount = paymentUtils.convertAmountToCent(transactionAmount, fractionDigits); + const transactionObject = paymentUtils.createTransactionObject(paymentObject.version, amountPlanned, transactionType, Constants.CT_TRANSACTION_STATE_INITIAL, undefined, undefined); + /* END GENAI */ const addTransaction = await commercetoolsApi.addTransaction(transactionObject, paymentId); if (addTransaction && addTransaction.transactions?.length) { const transactionLength = addTransaction.transactions.length; @@ -368,4 +470,6 @@ export default { captureContextApi, notificationApi, orderManagementApi, + isValidTokenSchema, + isTokenOwnedByCustomer, }; diff --git a/src/constants/customMessages.ts b/src/constants/customMessages.ts index 9a7e576..168eac9 100644 --- a/src/constants/customMessages.ts +++ b/src/constants/customMessages.ts @@ -61,6 +61,10 @@ export abstract class CustomMessages { static readonly ERROR_MSG_ADD_TRANSACTION_DETAILS = 'There was an error while adding transaction details, please try again'; static readonly ERROR_MSG_APPLICATION_DETAILS = 'Unable to fetch transaction application details'; static readonly ERROR_MSG_APPLE_PAY_CERTIFICATES = 'Please provide certificates paths for Apple Pay in configuration file'; + /* START GENAI */ + static readonly ERROR_MSG_APPLE_PAY_INVALID_VALIDATION_URL = 'The Apple Pay validation URL is not allowed. Only Apple Pay gateway endpoints are permitted.'; + static readonly ERROR_MSG_INVALID_TOKEN_DATA = 'Invalid token data: the token object does not conform to the expected schema or does not belong to this customer.'; + /* END GENAI */ static readonly ERROR_MSG_ACCESSING_CERTIFICATES = 'An error occurred while accessing ApplePay Certificates'; static readonly ERROR_MSG_ENV_VARIABLES_NOT_FOUND = 'Missing configurations for merchant id '; static readonly ERROR_MSG_EMPTY_PAYMENT_DATA = 'There was an error while fetching payment details'; diff --git a/src/constants/paymentConstants.ts b/src/constants/paymentConstants.ts index 2ec9c24..e01f644 100644 --- a/src/constants/paymentConstants.ts +++ b/src/constants/paymentConstants.ts @@ -35,7 +35,7 @@ export abstract class Constants { static readonly PAYMENT_GATEWAY_PRODUCT_ID = 'ctNetworkTokenSubscription'; static readonly PAYMENT_GATEWAY_NETWORK_TOKEN_EVENT_TYPE = 'tms.networktoken.updated'; static readonly PAYMENT_GATEWAY_APPLICATION_NAME = 'Commercetools(REST)'; - static readonly PAYMENT_GATEWAY_APPLICATION_VERSION = '25.3.0'; + static readonly PAYMENT_GATEWAY_APPLICATION_VERSION = '25.3.1'; static readonly PAYMENT_GATEWAY_AP_SESSIONS = 'AP_SESSIONS'; static readonly PAYMENT_GATEWAY_AP_STATUS = 'AP_STATUS'; static readonly PAYMENT_GATEWAY_AP_ORDER = 'AP_ORDER'; @@ -155,6 +155,8 @@ export abstract class Constants { static readonly NETWORK_TOKEN_EVENT = 'tms.networktoken.updated'; static readonly ADDITIONAL_CUSTOM_TYPE_FILE_PATH = 'src/resources/isv_additonal_custom_type.json'; static readonly CERTIFICATE_PATH = '../certificates'; + static readonly CACHE_CERTIFICATE_FROM_P12_FILE = 'certificateFromP12File'; + static readonly CACHE_CERTIFICATE_LAST_MODIFIED_TIMESTAMP = 'certificateLastModifideTimeStamp'; static readonly STRING_TEST = 'test'; static readonly STRING_GOOGLE_PAY = 'googlePay'; static readonly STRING_VISA = 'visa'; @@ -198,6 +200,8 @@ export abstract class Constants { static readonly ISV_ADDRESS_ID = 'isv_addressId'; static readonly ISV_TRANSACTION_DATA = 'isv_transaction_data'; static readonly ISV_TOKEN_ACTION = 'isv_tokenAction'; + static readonly ISV_TOKEN_ACTION_DELETE = 'delete'; + static readonly ISV_TOKEN_ACTION_UPDATE = 'update'; static readonly ISV_CARD_NEW_EXPIRY_MONTH = 'isv_cardNewExpiryMonth'; static readonly ISV_CARD_NEW_EXPIRY_YEAR = 'isv_cardNewExpiryYear'; static readonly ISV_FAILED_TOKENS = 'isv_failedTokens'; diff --git a/src/index.ts b/src/index.ts index 0d23350..57cf507 100644 --- a/src/index.ts +++ b/src/index.ts @@ -72,7 +72,9 @@ async function authentication(req: http.IncomingMessage, res: http.ServerRespons parsedUrl = url.parse(requestUrl, true); } if (process.env.PAYMENT_GATEWAY_SERVERLESS_DEPLOYMENT === Constants.STRING_GCP) { - if ((req.url && Constants.STATIC_FILE_REGEX.test(req.url)) || parsedUrl?.pathname === '/') { + /* START GENAI */ + if (Constants.STATIC_FILE_REGEX.test(parsedUrl?.pathname || '') || parsedUrl?.pathname === '/') { + /* END GENAI */ app.server.emit('request', req, res); return; } @@ -103,7 +105,16 @@ async function authentication(req: http.IncomingMessage, res: http.ServerRespons body += chunk.toString(); }); req.on('end', async () => { - notificationBody = JSON.parse(body); + /* START GENAI */ + try { + notificationBody = JSON.parse(body); + } catch { + errorHandler.logError(new ValidationError(CustomMessages.ERROR_MSG_INVALID_NOTIFICATION_DATA, '', FunctionConstant.FUNC_AUTHENTICATION), __filename, ''); + res.statusCode = Constants.HTTP_BAD_REQUEST_STATUS_CODE; + res.end(); + return; + } + /* END GENAI */ const vcSignature = req?.headers['v-c-signature']; if (vcSignature && notificationBody) { isValidNotification = await authenticationHelper.authenticateNetToken(vcSignature, notificationBody); @@ -149,13 +160,21 @@ async function authentication(req: http.IncomingMessage, res: http.ServerRespons const pathName = parsedUrl?.pathname; if (authHeader && pathName && Constants.EXTENSION_SERVICE_END_POINTS.includes(pathName)) { const base64Credentials = authHeader.split(' ')[1]; - base64Credentials === process.env.PAYMENT_GATEWAY_EXTENSION_HEADER_VALUE + /* START GENAI */ + const expectedValue = process.env.PAYMENT_GATEWAY_EXTENSION_HEADER_VALUE || ''; + const credentialMatch = base64Credentials && expectedValue && base64Credentials.length === expectedValue.length && crypto.timingSafeEqual(Buffer.from(base64Credentials), Buffer.from(expectedValue)); + credentialMatch + /* END GENAI */ ? handleRequest(req, res) : route.sendResponse(res, Constants.HTTP_UNAUTHORIZED_STATUS_CODE, Constants.CONTENT_TYPE_JSON, JSON.stringify({ message: CustomMessages.ERROR_MSG_INVALID_AUTHENTICATION_CREDENTIALS })); } else if (Constants.PAYMENT_CREATE_DESTINATION_URL === requestUrl || Constants.PAYMENT_UPDATE_DESTINATION_URL === requestUrl || Constants.CUSTOMER_UPDATE_DESTINATION_URL === requestUrl || '/captureContext' === requestUrl) { const encodedCredentials = authHeader.split(' ')[1]; const decrypt = authenticationHelper.decryption(encodedCredentials); - decrypt && decrypt === process.env.PAYMENT_GATEWAY_EXTENSION_HEADER_VALUE ? handleRequest(req, res) : route.sendResponse(res, Constants.HTTP_UNAUTHORIZED_STATUS_CODE, Constants.CONTENT_TYPE_JSON, JSON.stringify({ message: CustomMessages.ERROR_MSG_MISSING_AUTHORIZATION_HEADER })); + /* START GENAI */ + const expectedVal = process.env.PAYMENT_GATEWAY_EXTENSION_HEADER_VALUE || ''; + const decryptMatch = decrypt && expectedVal && decrypt.length === expectedVal.length && crypto.timingSafeEqual(Buffer.from(decrypt), Buffer.from(expectedVal)); + decryptMatch ? handleRequest(req, res) : route.sendResponse(res, Constants.HTTP_UNAUTHORIZED_STATUS_CODE, Constants.CONTENT_TYPE_JSON, JSON.stringify({ message: CustomMessages.ERROR_MSG_MISSING_AUTHORIZATION_HEADER })); + /* END GENAI */ } else { route.sendResponse(res, Constants.HTTP_UNAUTHORIZED_STATUS_CODE, Constants.CONTENT_TYPE_JSON, JSON.stringify({ message: CustomMessages.ERROR_MSG_MISSING_AUTHORIZATION_HEADER })); } @@ -402,7 +421,8 @@ const handlePaymentUpdate = async (req: any, res: any): Promise => { errorHandler.logError(new PaymentProcessingError(CustomMessages.EXCEPTION_UPDATE_PAYMENT_API, exception, FunctionConstant.FUNC_HANDLE_PAYMENT_UPDATE), __filename, encodeURI(paymentId)); updateResponse = paymentUtils.invalidOperationResponse(); } - const paymentUpdateResponse = JSON.stringify(updateResponse); + const validatedResponse = paymentUtils.validateActionResponse(updateResponse); + const paymentUpdateResponse = JSON.stringify(validatedResponse); res.end(paymentUpdateResponse); }; @@ -547,7 +567,15 @@ const handleRefund = async (req: any, res: any): Promise => { orderErrorMessage = CustomMessages.EXCEPTION_MSG_FETCH_PAYMENT_DETAILS; } res.statusCode = Constants.HTTP_REDIRECT_STATUS_CODE; - res.setHeader('Location', paymentUtils.validateRedirectPaths(viewData)); + const redirectPath = paymentUtils.validateRedirectPaths(viewData); + + if (typeof redirectPath === 'string' && redirectPath.startsWith('/')) { + res.setHeader('Location', redirectPath); + } else { + res.setHeader('Location', '/orders'); //fallback + } + + res.end(); }; diff --git a/src/models/payment-methods/PayPalPaymentMethod.ts b/src/models/payment-methods/PayPalPaymentMethod.ts index 94d3886..8526d4d 100644 --- a/src/models/payment-methods/PayPalPaymentMethod.ts +++ b/src/models/payment-methods/PayPalPaymentMethod.ts @@ -1,68 +1,68 @@ -import { Payment } from "@commercetools/platform-sdk"; -import { PtsV2PaymentsPost201Response } from "cybersource-rest-client"; - -import { CustomMessages } from "../../constants/customMessages"; -import { FunctionConstant } from "../../constants/functionConstant"; -import { Constants } from "../../constants/paymentConstants"; -import { ActionResponseType } from "../../types/Types"; -import { errorHandler, PaymentProcessingError } from "../../utils/ErrorHandler"; -import paymentUtils from "../../utils/PaymentUtils"; -import cartHelper from "../../utils/helpers/CartHelper"; -import { AbstractPaymentMethod } from "../AbstractPaymentMethod"; - -/** - * Implementation of the PayPal payment method - */ -export class PayPalPaymentMethod extends AbstractPaymentMethod { - constructor() { - super(Constants.PAYPAL); - } - - /** - * @inheritdoc - */ - protected getPaymentType(): string { - return Constants.PAYPAL; - } - - /** - * @inheritdoc - */ - public async handlePostAuthorization( - authResponse: ActionResponseType, - paymentResponse: PtsV2PaymentsPost201Response | any, - updatePaymentObj: Payment - ): Promise { - const paymentId = updatePaymentObj?.id || ''; - - try { - // Handle PayPal-specific post-authorization logic - if (Constants.HTTP_SUCCESS_STATUS_CODE === paymentResponse.httpCode) { - // Update cart with PayPal address details if available - if (paymentResponse?.data?.orderInformation?.billTo) { - try { - const cartObj = await paymentUtils.getCartObject(updatePaymentObj); - if (cartObj && cartObj.results && cartObj.results.length > 0) { - await cartHelper.updateCartWithPayPalAddress(updatePaymentObj, cartObj.results[0], paymentResponse.data); - } - } catch (error) { - errorHandler.logError(new PaymentProcessingError(CustomMessages.ERROR_MSG_PAYPAL_ADDRESS_DETAILS, Constants.LOG_ERROR, FunctionConstant.FUNC_HANDLE_POST_AUTHORIZATION), __filename, 'PaymentId : ' + paymentId); - } - } - // Clear PayPal session data after successful authorization - if (updatePaymentObj?.custom?.fields?.isv_payPalUrl) { - const isv_payPalUrl = ''; - authResponse.actions.push(...paymentUtils.setCustomFieldToNull({ isv_payPalUrl })); - } - if (updatePaymentObj?.custom?.fields?.isv_payPalRequestId) { - const isv_payPalRequestId = ''; - authResponse.actions.push(...paymentUtils.setCustomFieldToNull({ isv_payPalRequestId })); - } - } - } catch (error) { - errorHandler.logError(new PaymentProcessingError(CustomMessages.EXCEPTION_MSG_PROCESSING_REQUEST, Constants.LOG_ERROR, FunctionConstant.FUNC_HANDLE_POST_AUTHORIZATION), __filename, 'PaymentId : ' + paymentId); - } - - return authResponse; - } -} +import { Payment } from "@commercetools/platform-sdk"; +import { PtsV2PaymentsPost201Response } from "cybersource-rest-client"; + +import { CustomMessages } from "../../constants/customMessages"; +import { FunctionConstant } from "../../constants/functionConstant"; +import { Constants } from "../../constants/paymentConstants"; +import { ActionResponseType } from "../../types/Types"; +import { errorHandler, PaymentProcessingError } from "../../utils/ErrorHandler"; +import paymentUtils from "../../utils/PaymentUtils"; +import cartHelper from "../../utils/helpers/CartHelper"; +import { AbstractPaymentMethod } from "../AbstractPaymentMethod"; + +/** + * Implementation of the PayPal payment method + */ +export class PayPalPaymentMethod extends AbstractPaymentMethod { + constructor() { + super(Constants.PAYPAL); + } + + /** + * @inheritdoc + */ + protected getPaymentType(): string { + return Constants.PAYPAL; + } + + /** + * @inheritdoc + */ + public async handlePostAuthorization( + authResponse: ActionResponseType, + paymentResponse: PtsV2PaymentsPost201Response | any, + updatePaymentObj: Payment + ): Promise { + const paymentId = updatePaymentObj?.id || ''; + + try { + // Handle PayPal-specific post-authorization logic + if (Constants.HTTP_SUCCESS_STATUS_CODE === paymentResponse.httpCode) { + // Update cart with PayPal address details if available + if (paymentResponse?.data?.orderInformation?.billTo) { + try { + const cartObj = await paymentUtils.getCartObject(updatePaymentObj); + if (cartObj && cartObj.results && cartObj.results.length > 0) { + await cartHelper.updateCartWithPayPalAddress(updatePaymentObj, cartObj.results[0], paymentResponse.data); + } + } catch (error) { + errorHandler.logError(new PaymentProcessingError(CustomMessages.ERROR_MSG_PAYPAL_ADDRESS_DETAILS, Constants.LOG_ERROR, FunctionConstant.FUNC_HANDLE_POST_AUTHORIZATION), __filename, 'PaymentId : ' + paymentId); + } + } + // Clear PayPal session data after successful authorization + if (updatePaymentObj?.custom?.fields?.isv_payPalUrl) { + const isv_payPalUrl = ''; + authResponse.actions.push(...paymentUtils.setCustomFieldToNull({ isv_payPalUrl })); + } + if (updatePaymentObj?.custom?.fields?.isv_payPalRequestId) { + const isv_payPalRequestId = ''; + authResponse.actions.push(...paymentUtils.setCustomFieldToNull({ isv_payPalRequestId })); + } + } + } catch (error) { + errorHandler.logError(new PaymentProcessingError(CustomMessages.EXCEPTION_MSG_PROCESSING_REQUEST, Constants.LOG_ERROR, FunctionConstant.FUNC_HANDLE_POST_AUTHORIZATION), __filename, 'PaymentId : ' + paymentId); + } + + return authResponse; + } +} diff --git a/src/requestBuilder/LineItemMapper.ts b/src/requestBuilder/LineItemMapper.ts index f5e8344..7f1d3c8 100644 --- a/src/requestBuilder/LineItemMapper.ts +++ b/src/requestBuilder/LineItemMapper.ts @@ -54,6 +54,9 @@ class LineItemMapper { orderInformationLineItem.unitPrice = unitPrice; orderInformationLineItem.quantity = quantity; orderInformationLineItem.discountAmount = discountAmount; + if (functionName === FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE) { + (orderInformationLineItem as Ptsv2paymentsOrderInformationLineItems).taxAmount = taxRate ? String(taxRate * lineItemTotalAmount) : undefined; + } paymentValidator.setObjectValue(orderInformationLineItem, 'taxRate', taxRate, '', Constants.STR_NUMBER, false); return orderInformationLineItem; } @@ -113,6 +116,15 @@ export class LineItem { return LineItemMapper.mapLineItemValues(this.functionName, this.lineItemTotalAmount, 'coupon', 'coupon', 'coupon', this.unitPrice, 1); } + private getTaxRate(isShipping: boolean): number | undefined { + return isShipping + ? this.cartObj?.shipping?.[0]?.shippingInfo?.taxRate?.includedInPrice + ? this.cartObj.shipping[0].shippingInfo.taxRate.amount + : undefined + : this.lineItem?.taxRate?.amount; + } + + /** * Sets values for a line item based on whether it is a shipping item. * @param {boolean} isShipping - Indicates if the line item is for shipping. @@ -122,7 +134,7 @@ export class LineItem { let discountPrice = 0; let unitPrice: number; let quantity: number; - let taxRate = null; + let taxRate = undefined; let item: any; let discountArray: any; if (isShipping) { @@ -130,15 +142,13 @@ export class LineItem { discountArray = item?.discountedPrice?.includedDiscounts; unitPrice = this.unitPrice; quantity = 1; - if (this.cartObj?.shipping && this.cartObj.shipping[0]?.shippingInfo?.taxRate?.includedInPrice) { - taxRate = this.cartObj.shipping[0].shippingInfo.taxRate.amount - } + taxRate = this.getTaxRate(isShipping) } else { item = this.item || this.lineItem; discountArray = item?.discountedPrice?.includedDiscounts; unitPrice = this.unitPrice; quantity = this.item ? this.item.quantity : this.lineItem.quantity; - taxRate = this.lineItem?.taxRate?.includedInPrice ? this.lineItem.taxRate.amount : undefined; + taxRate = this.getTaxRate(isShipping) } if (discountArray) { discountArray.forEach((discount: any) => { diff --git a/src/requestBuilder/PrepareFields.ts b/src/requestBuilder/PrepareFields.ts index 010f44b..a667db0 100644 --- a/src/requestBuilder/PrepareFields.ts +++ b/src/requestBuilder/PrepareFields.ts @@ -27,6 +27,7 @@ import { AddressMapper } from './AddressMapper'; import { OrderInformationMapper } from './OrderInformationMapper'; import { PaymentInformationModel } from './PaymentInformation'; import { ProcessingInformation } from './ProcessingInformationMapper'; +import cache from 'memory-cache'; /** * Generates the configuration object based on the provided parameters. @@ -79,6 +80,8 @@ const getConfigObject = async (functionName: string, midCredentials: MidCredenti configObject.merchantKeyId = midCredentialsObject.merchantKeyId; configObject.merchantsecretKey = midCredentialsObject.merchantSecretKey; if (paymentUtils.toBoolean(process.env.PAYMENT_GATEWAY_USE_MLE) && !Constants.MLE_UNSUPPORTED_FUNCTIONS.includes(functionName)) { + cache.del(Constants.CACHE_CERTIFICATE_FROM_P12_FILE); + cache.del(Constants.CACHE_CERTIFICATE_LAST_MODIFIED_TIMESTAMP); const jwtConfiguration = multiMid.getKeyCredentials(midCredentialsObject.merchantId); if (jwtConfiguration.keyPass && (jwtConfiguration.keyFileName || jwtConfiguration.keyFileUrl)) { configObject.useMLEGlobally = true; @@ -194,6 +197,10 @@ const getOrderInformation = (functionName: string, paymentObj: Payment | null, u return orderInformationMapper.getOrderInformation(); }; +const getCartTotalPrice = (cartObj: Cart): number => { + return cartObj.taxedPrice?.totalGross?.centAmount ?? cartObj.totalPrice?.centAmount ?? 0; +} + /** * Generates order information amount details based on the provided parameters. * @@ -223,12 +230,12 @@ const getOrderInformationAmountDetails = (functionName: string, captureAmount: n orderInformationAmountDetails.currency = paymentObj?.amountPlanned?.currencyCode; } else if (cartObj?.totalPrice && (FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE === functionName || FunctionConstant.FUNC_CREATE_ORDER_RESPONSE === functionName || FunctionConstant.FUNC_GET_SESSION_RESPONSE === functionName)) { orderInformationAmountDetails = {} as Ptsv2paymentsOrderInformationAmountDetails; - orderInformationAmountDetails.totalAmount = paymentUtils.convertCentToAmount(cartObj.totalPrice.centAmount, cartObj.totalPrice.fractionDigits); + orderInformationAmountDetails.totalAmount = paymentUtils.convertCentToAmount(getCartTotalPrice(cartObj), cartObj.totalPrice.fractionDigits); orderInformationAmountDetails.currency = cartObj?.totalPrice?.currencyCode; } else if (FunctionConstant.FUNC_GENERATE_CAPTURE_CONTEXT === functionName) { orderInformationAmountDetails = {} as Upv1capturecontextsOrderInformationAmountDetails; if ('Payments' === service && cartObj?.totalPrice) { - orderInformationAmountDetails.totalAmount = `${paymentUtils.convertCentToAmount(cartObj.totalPrice.centAmount, cartObj.totalPrice.fractionDigits)}`; + orderInformationAmountDetails.totalAmount = `${paymentUtils.convertCentToAmount(getCartTotalPrice(cartObj), cartObj.totalPrice.fractionDigits)}`; orderInformationAmountDetails.currency = cartObj?.totalPrice?.currencyCode; } else if ('MyAccounts' === service) { orderInformationAmountDetails.currency = currencyCode; diff --git a/src/requestBuilder/ProcessingInformationMapper.ts b/src/requestBuilder/ProcessingInformationMapper.ts index 86a5f57..dc5c7ca 100644 --- a/src/requestBuilder/ProcessingInformationMapper.ts +++ b/src/requestBuilder/ProcessingInformationMapper.ts @@ -76,7 +76,7 @@ export class ProcessingInformation { } this.configureReconciliationId(orderNo); this.configurePaymentSolution(resourceObj, customFields); - this.configureBankTransferOptions(resourceObj, customFields); + this.configureBankTransferOptions(resourceObj); return this.processingInformation; } @@ -89,7 +89,9 @@ export class ProcessingInformation { * @param customFields - Custom fields related to the payment. */ private configureAuthorizationProcessing(actionList: string[], customFields: any) { - if (customFields?.isv_enabledMoto) { + /* START GENAI */ + if (paymentUtils.toBoolean(process.env.PAYMENT_GATEWAY_ENABLE_MOTO)) { + /* END GENAI */ this.processingInformation.commerceIndicator = 'MOTO'; } if (customFields?.isv_saleEnabled && Constants.PAYPAL !== this.service) { @@ -194,12 +196,14 @@ export class ProcessingInformation { * @param resourceObj - The payment resource object containing payment method info. * @param customFields - Custom fields that may influence the bank transfer configuration. */ - private configureBankTransferOptions(resourceObj: Payment | null, customFields?: Partial) { + private configureBankTransferOptions(resourceObj: Payment | null) { if (Constants.ECHECK === resourceObj?.paymentMethodInfo?.method) { + /* START GENAI */ const banktransferOptions: Ptsv2creditsProcessingInformationBankTransferOptions = { - secCode: customFields?.isv_enabledMoto ? 'TEL' : 'WEB', + secCode: paymentUtils.toBoolean(process.env.PAYMENT_GATEWAY_ENABLE_MOTO) ? 'TEL' : 'WEB', fraudScreeningLevel: 1 }; + /* END GENAI */ this.processingInformation.bankTransferOptions = banktransferOptions; } } diff --git a/src/resources/isv_payment_data_type.json b/src/resources/isv_payment_data_type.json index 221102e..26252f8 100644 --- a/src/resources/isv_payment_data_type.json +++ b/src/resources/isv_payment_data_type.json @@ -370,17 +370,6 @@ }, "inputHint": "SingleLine" }, - { - "name": "isv_enabledMoto", - "label": { - "en": "Flag indicating MOTO transaction" - }, - "required": false, - "type": { - "name": "Boolean" - }, - "inputHint": "SingleLine" - }, { "name": "isv_walletType", "label": { diff --git a/src/service/payment/CreateWebhookSubscription.ts b/src/service/payment/CreateWebhookSubscription.ts index c1bbd01..7b46c1b 100644 --- a/src/service/payment/CreateWebhookSubscription.ts +++ b/src/service/payment/CreateWebhookSubscription.ts @@ -7,7 +7,7 @@ import prepareFields from '../../requestBuilder/PrepareFields'; import { MidCredentialsType } from '../../types/Types'; import { AuthenticationError, errorHandler } from '../../utils/ErrorHandler'; import paymentUtils from '../../utils/PaymentUtils'; -import isvApi from '../../utils/api/IsvApi'; +import isvApi from '../../utils/api/isvApi'; /** * Handles creating of webhook subscription. diff --git a/src/service/payment/DeleteWebhookSubscriptionService.ts b/src/service/payment/DeleteWebhookSubscriptionService.ts index 3d8ac06..7555413 100644 --- a/src/service/payment/DeleteWebhookSubscriptionService.ts +++ b/src/service/payment/DeleteWebhookSubscriptionService.ts @@ -7,7 +7,7 @@ import prepareFields from '../../requestBuilder/PrepareFields'; import { MidCredentialsType } from '../../types/Types'; import { AuthenticationError, errorHandler } from '../../utils/ErrorHandler'; import paymentUtils from '../../utils/PaymentUtils'; -import isvApi from '../../utils/api/IsvApi'; +import isvApi from '../../utils/api/isvApi'; /** * Deletes a webhook subscription. diff --git a/src/service/payment/GetWebhookSubscriptionDetails.ts b/src/service/payment/GetWebhookSubscriptionDetails.ts index f28ae8b..9579a8c 100644 --- a/src/service/payment/GetWebhookSubscriptionDetails.ts +++ b/src/service/payment/GetWebhookSubscriptionDetails.ts @@ -7,7 +7,7 @@ import prepareFields from '../../requestBuilder/PrepareFields'; import { MidCredentialsType } from '../../types/Types'; import { AuthenticationError, errorHandler } from '../../utils/ErrorHandler'; import paymentUtils from '../../utils/PaymentUtils'; -import isvApi from '../../utils/api/IsvApi'; +import isvApi from '../../utils/api/isvApi'; /** * Retrieves webhook subscription details for a mid. diff --git a/src/types/Types.ts b/src/types/Types.ts index 44ef7f1..488eceb 100644 --- a/src/types/Types.ts +++ b/src/types/Types.ts @@ -79,7 +79,6 @@ export type PaymentCustomFieldsType = { isv_applePayDisplayName: string; isv_applePaySessionData: string; isv_saleEnabled: boolean; - isv_enabledMoto: string; isv_walletType: string; isv_accountNumber: string; isv_accountType: string; @@ -176,7 +175,7 @@ export type CustomerTokensType = { cardExpiryMonth: string; cardExpiryYear: string; addressId: string; - timeStamp: string; + timestamp: string; address: Partial; }; //Mid credentials object diff --git a/src/unit-tests/const/CybersourceApiConst.ts b/src/unit-tests/const/CybersourceApiConst.ts index 06c697a..34c82b1 100644 --- a/src/unit-tests/const/CybersourceApiConst.ts +++ b/src/unit-tests/const/CybersourceApiConst.ts @@ -1,9 +1,11 @@ +/* START GENAI */ const configObject = { authenticationType: 'http_signature', - runEnvironment: 'apitest.cybersource.com', - merchantID: 'visa_isv_commercetools_pmt', - merchantKeyId: 'c886fd00-4d1b-4163-9a02-024948d0fe07', - merchantsecretKey: 'uWewxMNOAbkMcR6mivYXQDa7uyLUHN3d3TEAxIqI/2g=', + runEnvironment: process.env.PAYMENT_GATEWAY_TEST_ENVIRONMENT || 'apitest.cybersource.com', + merchantID: process.env.PAYMENT_GATEWAY_MERCHANT_ID || '', + merchantKeyId: process.env.PAYMENT_GATEWAY_MERCHANT_KEY_ID || '', + merchantsecretKey: process.env.PAYMENT_GATEWAY_MERCHANT_SECRET_KEY || '', +/* END GENAI */ logConfiguration: { enableLog: false, }, diff --git a/src/unit-tests/const/LineItemMapperConst.ts b/src/unit-tests/const/LineItemMapperConst.ts index 94f5721..7d503b8 100644 --- a/src/unit-tests/const/LineItemMapperConst.ts +++ b/src/unit-tests/const/LineItemMapperConst.ts @@ -1,672 +1,672 @@ -const unitPrice = 20; - -const isShipping = false; - -const isCustomLineItem = false; - -const isTotalPriceDiscount = false; - -const lineItemTotalAmount = 40.05; - -const discountedCart = { - type: 'Cart', - id: '740bfc91-4214-46c4-abac-e3f272f7fbb3', - version: 14, - versionModifiedAt: '2024-08-08T13:15:33.234Z', - lastMessageSequenceNumber: 1, - createdAt: '2024-08-08T13:15:25.649Z', - lastModifiedAt: '2024-08-08T13:15:33.234Z', - lastModifiedBy: { - clientId: 'BsI4_V0dn_H5HQB3js8xawFv', - isPlatformClient: false, - anonymousId: 'f48b84c5-138f-4cfa-9d81-a46875d55211', - }, - createdBy: { - clientId: 'BsI4_V0dn_H5HQB3js8xawFv', - isPlatformClient: false, - anonymousId: 'f48b84c5-138f-4cfa-9d81-a46875d55211', - }, - anonymousId: 'f48b84c5-138f-4cfa-9d81-a46875d55211', - locale: 'en', - lineItems: [ - { - id: '9f7adf8a-592d-4376-9b89-a10be1bd7c42', - productId: 'cea7f284-497d-4434-a33d-66e65f7223e0', - name: { - 'de-DE': 'Sony Earbuds(DE-DE)', - ja: 'Sony Earbuds(JA)', - fr: 'Sony Earbuds(FR)', - 'en-GB': 'Sony Earbuds(EN-GB)', - en: 'Sony Earbuds', - de: 'Sony Earbuds(DE)', - 'en-US': 'Sony Earbuds', - ar: 'Sony Earbuds(AR)', - es: 'Sony Earbuds(ES)', - hi: 'Sony Earbuds(HI)', - }, - productType: { - typeId: 'product-type', - id: '4c8dd9fe-026e-40f7-aa43-90f3280db45f', - version: 1, - }, - productSlug: { - 'de-DE': 'SKU-W5', - ja: 'SKU-W5', - fr: 'SKU-W5', - 'en-GB': 'SKU-W5', - en: 'SKU-W5', - 'en-US': 'SKU-W5', - ar: 'SKU-W5', - es: 'SKU-W5', - hi: 'SKU-W5', - }, - variant: { - id: 1, - sku: 'SKU-W5', - prices: [ - { - id: 'ac8249de-5676-4b68-bbb0-1bdea2bf60f5', - value: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 60080, - fractionDigits: 2, - }, - country: 'US', - }, - { - id: 'bc4e13ea-13ee-4ad1-9933-e697fa03b5e8', - value: { - type: 'centPrecision', - currencyCode: 'EUR', - centAmount: 40000, - fractionDigits: 2, - }, - country: 'DE', - }, - { - id: '0de9cf60-d24b-46e1-8098-244c4dd6a9f4', - value: { - type: 'centPrecision', - currencyCode: 'IQD', - centAmount: 700000, - fractionDigits: 3, - }, - }, - { - id: 'd43efc33-2b72-48ff-8431-b91d234d15e4', - value: { - type: 'centPrecision', - currencyCode: 'CLP', - centAmount: 550, - fractionDigits: 0, - }, - }, - { - id: '902d5a67-b353-4c61-96ee-cdc5e3ad3a65', - value: { - type: 'centPrecision', - currencyCode: 'JPY', - centAmount: 600, - fractionDigits: 0, - }, - }, - { - id: 'e10b8554-6a3d-4168-ae7b-c4f3e4e137aa', - value: { - type: 'centPrecision', - currencyCode: 'GBP', - centAmount: 283210, - fractionDigits: 2, - }, - }, - ], - images: [ - { - url: 'https://static2.nordic.pictures/33089719-thickbox_default/sony-wireless-earbuds-wf-c500d-pink.jpg', - dimensions: { - w: 300, - h: 375, - }, - }, - ], - attributes: [], - assets: [], - }, - price: { - id: 'ac8249de-5676-4b68-bbb0-1bdea2bf60f5', - value: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 60080, - fractionDigits: 2, - }, - country: 'US', - }, - quantity: 1, - discountedPrice: { - value: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 60080, - fractionDigits: 2, - }, - includedDiscounts: [ - { - discount: { - typeId: 'cart-discount', - id: '9280bdb9-5cbc-4fce-a2fb-b6fd3143d0df', - }, - discountedAmount: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 0, - fractionDigits: 2, - }, - }, - ], - }, - discountedPricePerQuantity: [ - { - quantity: 1, - discountedPrice: { - value: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 60080, - fractionDigits: 2, - }, - includedDiscounts: [ - { - discount: { - typeId: 'cart-discount', - id: '9280bdb9-5cbc-4fce-a2fb-b6fd3143d0df', - }, - discountedAmount: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 0, - fractionDigits: 2, - }, - }, - ], - }, - }, - ], - taxRate: { - name: 'test-tax-category', - amount: 0.2, - includedInPrice: true, - country: 'US', - id: 'HZIq01bI', - subRates: [], - }, - perMethodTaxRate: [], - addedAt: '2024-08-08T13:15:25.983Z', - lastModifiedAt: '2024-08-08T13:15:25.983Z', - state: [ - { - quantity: 1, - state: { - typeId: 'state', - id: 'd5097392-dd2d-45b4-a550-f7ea49700a3a', - }, - }, - ], - priceMode: 'Platform', - lineItemMode: 'Standard', - totalPrice: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 60080, - fractionDigits: 2, - }, - taxedPrice: { - totalNet: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 50067, - fractionDigits: 2, - }, - totalGross: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 60080, - fractionDigits: 2, - }, - taxPortions: [ - { - rate: 0.2, - amount: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 10013, - fractionDigits: 2, - }, - name: 'test-tax-category', - }, - ], - totalTax: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 10013, - fractionDigits: 2, - }, - }, - taxedPricePortions: [], - }, - { - id: 'a42766c8-2a3d-4ef3-b579-8ad691fb144d', - productId: 'f235846d-40b7-4005-9292-aa0f2cc1eb39', - name: { - 'de-DE': 'Airpods(DE-DE)', - ja: 'Airpods(JA)', - fr: 'Airpods(FR)', - 'en-GB': 'Airpods(EN-GB)', - en: 'Airpods(EN)', - de: 'Airpods(DE)', - 'en-US': 'Airpods(EN-US)', - ar: 'Airpods(AR)', - es: 'Airpods(ES)', - hi: 'Airpods(HI)', - }, - productType: { - typeId: 'product-type', - id: '4c8dd9fe-026e-40f7-aa43-90f3280db45f', - version: 1, - }, - productSlug: { - 'de-DE': 'SKU-W2', - ja: 'SKU-W2', - fr: 'SKU-W2', - 'en-GB': 'SKU-W2', - en: 'SKU-W2', - 'en-US': 'SKU-W2', - ar: 'SKU-W2', - es: 'SKU-W2', - hi: 'SKU-W2', - }, - variant: { - id: 1, - sku: 'SKU-W2', - prices: [ - { - id: 'a78cb404-16a6-4042-8c70-501b1faae21e', - value: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 5080, - fractionDigits: 2, - }, - country: 'US', - }, - { - id: 'd4d84feb-5404-4c7d-b39d-f06e0edf1dc4', - value: { - type: 'centPrecision', - currencyCode: 'EUR', - centAmount: 3000, - fractionDigits: 2, - }, - country: 'DE', - }, - { - id: '6dd63a7f-ef34-4cf6-b62a-7c904dad24ec', - value: { - type: 'centPrecision', - currencyCode: 'IQD', - centAmount: 40600, - fractionDigits: 3, - }, - }, - { - id: '6079531f-e1f3-4138-85d2-4daec3807943', - value: { - type: 'highPrecision', - currencyCode: 'CLP', - centAmount: 46, - preciseAmount: 4567, - fractionDigits: 2, - }, - }, - { - id: '804a147f-f10d-4453-a51f-22886a1a6d1d', - value: { - type: 'highPrecision', - currencyCode: 'JPY', - centAmount: 35, - preciseAmount: 3478, - fractionDigits: 2, - }, - }, - { - id: 'f9001cc3-6e94-4776-a6f1-748bc59c6ce8', - value: { - type: 'centPrecision', - currencyCode: 'GBP', - centAmount: 147510, - fractionDigits: 2, - }, - }, - ], - images: [ - { - url: 'https://m.media-amazon.com/images/I/71zny7BTRlL._AC_UF1000,1000_QL80_.jpg', - dimensions: { - w: 300, - h: 375, - }, - }, - ], - attributes: [], - assets: [], - }, - price: { - id: 'a78cb404-16a6-4042-8c70-501b1faae21e', - value: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 5080, - fractionDigits: 2, - }, - country: 'US', - }, - quantity: 1, - discountedPrice: { - value: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 2540, - fractionDigits: 2, - }, - includedDiscounts: [ - { - discount: { - typeId: 'cart-discount', - id: '9280bdb9-5cbc-4fce-a2fb-b6fd3143d0df', - }, - discountedAmount: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 2540, - fractionDigits: 2, - }, - }, - ], - }, - discountedPricePerQuantity: [ - { - quantity: 1, - discountedPrice: { - value: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 2540, - fractionDigits: 2, - }, - includedDiscounts: [ - { - discount: { - typeId: 'cart-discount', - id: '9280bdb9-5cbc-4fce-a2fb-b6fd3143d0df', - }, - discountedAmount: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 2540, - fractionDigits: 2, - }, - }, - ], - }, - }, - ], - taxRate: { - name: 'test-tax-category', - amount: 0.2, - includedInPrice: true, - country: 'US', - id: 'HZIq01bI', - subRates: [], - }, - perMethodTaxRate: [], - addedAt: '2024-08-08T13:15:30.028Z', - lastModifiedAt: '2024-08-08T13:15:30.028Z', - state: [ - { - quantity: 1, - state: { - typeId: 'state', - id: 'd5097392-dd2d-45b4-a550-f7ea49700a3a', - }, - }, - ], - priceMode: 'Platform', - lineItemMode: 'Standard', - totalPrice: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 2540, - fractionDigits: 2, - }, - taxedPrice: { - totalNet: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 2117, - fractionDigits: 2, - }, - totalGross: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 2540, - fractionDigits: 2, - }, - taxPortions: [ - { - rate: 0.2, - amount: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 423, - fractionDigits: 2, - }, - name: 'test-tax-category', - }, - ], - totalTax: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 423, - fractionDigits: 2, - }, - }, - taxedPricePortions: [], - }, - ], - cartState: 'Active', - totalPrice: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 63610, - fractionDigits: 2, - }, - taxedPrice: { - totalNet: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 53009, - fractionDigits: 2, - }, - totalGross: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 63610, - fractionDigits: 2, - }, - taxPortions: [ - { - rate: 0.2, - amount: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 10601, - fractionDigits: 2, - }, - name: 'test-tax-category', - }, - ], - totalTax: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 10601, - fractionDigits: 2, - }, - }, - country: 'US', - taxedShippingPrice: { - totalNet: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 825, - fractionDigits: 2, - }, - totalGross: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 990, - fractionDigits: 2, - }, - taxPortions: [ - { - rate: 0.2, - amount: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 165, - fractionDigits: 2, - }, - name: 'test-tax-category', - }, - ], - totalTax: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 165, - fractionDigits: 2, - }, - }, - shippingMode: 'Single', - shippingInfo: { - shippingMethodName: 'Standard Delivery', - price: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 990, - fractionDigits: 2, - }, - shippingRate: { - price: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 990, - fractionDigits: 2, - }, - tiers: [], - }, - taxRate: { - name: 'test-tax-category', - amount: 0.2, - includedInPrice: true, - country: 'US', - id: 'HZIq01bI', - subRates: [], - }, - taxCategory: { - typeId: 'tax-category', - id: 'c04efa03-8e49-4511-8572-315f40a7cbb2', - }, - deliveries: [], - shippingMethod: { - typeId: 'shipping-method', - id: '8ede0c25-0082-4147-8c25-106c38110a14', - }, - taxedPrice: { - totalNet: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 825, - fractionDigits: 2, - }, - totalGross: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 990, - fractionDigits: 2, - }, - taxPortions: [ - { - rate: 0.2, - amount: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 165, - fractionDigits: 2, - }, - name: 'test-tax-category', - }, - ], - totalTax: { - type: 'centPrecision', - currencyCode: 'USD', - centAmount: 165, - fractionDigits: 2, - }, - }, - shippingMethodState: 'MatchesCart', - }, - shipping: [], - customLineItems: [], - discountCodes: [], - directDiscounts: [], - inventoryMode: 'None', - taxMode: 'Platform', - taxRoundingMode: 'HalfEven', - taxCalculationMode: 'LineItemLevel', - deleteDaysAfterLastModification: 90, - refusedGifts: [], - origin: 'Customer', - shippingAddress: { - firstName: 'vignesh', - lastName: 'S', - streetName: '1295 Charleston Road', - postalCode: '94043', - city: 'Mountain View', - region: 'CA', - country: 'US', - phone: '9876543210', - email: 'vignesh@wipro.com', - }, - billingAddress: { - firstName: 'vignesh', - lastName: 'S', - streetName: '1295 Charleston Road', - postalCode: '94043', - city: 'Mountain View', - region: 'CA', - country: 'US', - phone: '9876543210', - email: 'vignesh@wipro.com', - }, - itemShippingAddresses: [], - totalLineItemQuantity: 2, -}; - -export default { - unitPrice, - isShipping, - isCustomLineItem, - isTotalPriceDiscount, - lineItemTotalAmount, - discountedCart, -}; +const unitPrice = 20; + +const isShipping = false; + +const isCustomLineItem = false; + +const isTotalPriceDiscount = false; + +const lineItemTotalAmount = 40.05; + +const discountedCart = { + type: 'Cart', + id: '740bfc91-4214-46c4-abac-e3f272f7fbb3', + version: 14, + versionModifiedAt: '2024-08-08T13:15:33.234Z', + lastMessageSequenceNumber: 1, + createdAt: '2024-08-08T13:15:25.649Z', + lastModifiedAt: '2024-08-08T13:15:33.234Z', + lastModifiedBy: { + clientId: 'BsI4_V0dn_H5HQB3js8xawFv', + isPlatformClient: false, + anonymousId: 'f48b84c5-138f-4cfa-9d81-a46875d55211', + }, + createdBy: { + clientId: 'BsI4_V0dn_H5HQB3js8xawFv', + isPlatformClient: false, + anonymousId: 'f48b84c5-138f-4cfa-9d81-a46875d55211', + }, + anonymousId: 'f48b84c5-138f-4cfa-9d81-a46875d55211', + locale: 'en', + lineItems: [ + { + id: '9f7adf8a-592d-4376-9b89-a10be1bd7c42', + productId: 'cea7f284-497d-4434-a33d-66e65f7223e0', + name: { + 'de-DE': 'Sony Earbuds(DE-DE)', + ja: 'Sony Earbuds(JA)', + fr: 'Sony Earbuds(FR)', + 'en-GB': 'Sony Earbuds(EN-GB)', + en: 'Sony Earbuds', + de: 'Sony Earbuds(DE)', + 'en-US': 'Sony Earbuds', + ar: 'Sony Earbuds(AR)', + es: 'Sony Earbuds(ES)', + hi: 'Sony Earbuds(HI)', + }, + productType: { + typeId: 'product-type', + id: '4c8dd9fe-026e-40f7-aa43-90f3280db45f', + version: 1, + }, + productSlug: { + 'de-DE': 'SKU-W5', + ja: 'SKU-W5', + fr: 'SKU-W5', + 'en-GB': 'SKU-W5', + en: 'SKU-W5', + 'en-US': 'SKU-W5', + ar: 'SKU-W5', + es: 'SKU-W5', + hi: 'SKU-W5', + }, + variant: { + id: 1, + sku: 'SKU-W5', + prices: [ + { + id: 'ac8249de-5676-4b68-bbb0-1bdea2bf60f5', + value: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 60080, + fractionDigits: 2, + }, + country: 'US', + }, + { + id: 'bc4e13ea-13ee-4ad1-9933-e697fa03b5e8', + value: { + type: 'centPrecision', + currencyCode: 'EUR', + centAmount: 40000, + fractionDigits: 2, + }, + country: 'DE', + }, + { + id: '0de9cf60-d24b-46e1-8098-244c4dd6a9f4', + value: { + type: 'centPrecision', + currencyCode: 'IQD', + centAmount: 700000, + fractionDigits: 3, + }, + }, + { + id: 'd43efc33-2b72-48ff-8431-b91d234d15e4', + value: { + type: 'centPrecision', + currencyCode: 'CLP', + centAmount: 550, + fractionDigits: 0, + }, + }, + { + id: '902d5a67-b353-4c61-96ee-cdc5e3ad3a65', + value: { + type: 'centPrecision', + currencyCode: 'JPY', + centAmount: 600, + fractionDigits: 0, + }, + }, + { + id: 'e10b8554-6a3d-4168-ae7b-c4f3e4e137aa', + value: { + type: 'centPrecision', + currencyCode: 'GBP', + centAmount: 283210, + fractionDigits: 2, + }, + }, + ], + images: [ + { + url: 'https://static2.nordic.pictures/33089719-thickbox_default/sony-wireless-earbuds-wf-c500d-pink.jpg', + dimensions: { + w: 300, + h: 375, + }, + }, + ], + attributes: [], + assets: [], + }, + price: { + id: 'ac8249de-5676-4b68-bbb0-1bdea2bf60f5', + value: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 60080, + fractionDigits: 2, + }, + country: 'US', + }, + quantity: 1, + discountedPrice: { + value: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 60080, + fractionDigits: 2, + }, + includedDiscounts: [ + { + discount: { + typeId: 'cart-discount', + id: '9280bdb9-5cbc-4fce-a2fb-b6fd3143d0df', + }, + discountedAmount: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 0, + fractionDigits: 2, + }, + }, + ], + }, + discountedPricePerQuantity: [ + { + quantity: 1, + discountedPrice: { + value: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 60080, + fractionDigits: 2, + }, + includedDiscounts: [ + { + discount: { + typeId: 'cart-discount', + id: '9280bdb9-5cbc-4fce-a2fb-b6fd3143d0df', + }, + discountedAmount: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 0, + fractionDigits: 2, + }, + }, + ], + }, + }, + ], + taxRate: { + name: 'test-tax-category', + amount: 0.2, + includedInPrice: true, + country: 'US', + id: 'HZIq01bI', + subRates: [], + }, + perMethodTaxRate: [], + addedAt: '2024-08-08T13:15:25.983Z', + lastModifiedAt: '2024-08-08T13:15:25.983Z', + state: [ + { + quantity: 1, + state: { + typeId: 'state', + id: 'd5097392-dd2d-45b4-a550-f7ea49700a3a', + }, + }, + ], + priceMode: 'Platform', + lineItemMode: 'Standard', + totalPrice: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 60080, + fractionDigits: 2, + }, + taxedPrice: { + totalNet: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 50067, + fractionDigits: 2, + }, + totalGross: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 60080, + fractionDigits: 2, + }, + taxPortions: [ + { + rate: 0.2, + amount: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 10013, + fractionDigits: 2, + }, + name: 'test-tax-category', + }, + ], + totalTax: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 10013, + fractionDigits: 2, + }, + }, + taxedPricePortions: [], + }, + { + id: 'a42766c8-2a3d-4ef3-b579-8ad691fb144d', + productId: 'f235846d-40b7-4005-9292-aa0f2cc1eb39', + name: { + 'de-DE': 'Airpods(DE-DE)', + ja: 'Airpods(JA)', + fr: 'Airpods(FR)', + 'en-GB': 'Airpods(EN-GB)', + en: 'Airpods(EN)', + de: 'Airpods(DE)', + 'en-US': 'Airpods(EN-US)', + ar: 'Airpods(AR)', + es: 'Airpods(ES)', + hi: 'Airpods(HI)', + }, + productType: { + typeId: 'product-type', + id: '4c8dd9fe-026e-40f7-aa43-90f3280db45f', + version: 1, + }, + productSlug: { + 'de-DE': 'SKU-W2', + ja: 'SKU-W2', + fr: 'SKU-W2', + 'en-GB': 'SKU-W2', + en: 'SKU-W2', + 'en-US': 'SKU-W2', + ar: 'SKU-W2', + es: 'SKU-W2', + hi: 'SKU-W2', + }, + variant: { + id: 1, + sku: 'SKU-W2', + prices: [ + { + id: 'a78cb404-16a6-4042-8c70-501b1faae21e', + value: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 5080, + fractionDigits: 2, + }, + country: 'US', + }, + { + id: 'd4d84feb-5404-4c7d-b39d-f06e0edf1dc4', + value: { + type: 'centPrecision', + currencyCode: 'EUR', + centAmount: 3000, + fractionDigits: 2, + }, + country: 'DE', + }, + { + id: '6dd63a7f-ef34-4cf6-b62a-7c904dad24ec', + value: { + type: 'centPrecision', + currencyCode: 'IQD', + centAmount: 40600, + fractionDigits: 3, + }, + }, + { + id: '6079531f-e1f3-4138-85d2-4daec3807943', + value: { + type: 'highPrecision', + currencyCode: 'CLP', + centAmount: 46, + preciseAmount: 4567, + fractionDigits: 2, + }, + }, + { + id: '804a147f-f10d-4453-a51f-22886a1a6d1d', + value: { + type: 'highPrecision', + currencyCode: 'JPY', + centAmount: 35, + preciseAmount: 3478, + fractionDigits: 2, + }, + }, + { + id: 'f9001cc3-6e94-4776-a6f1-748bc59c6ce8', + value: { + type: 'centPrecision', + currencyCode: 'GBP', + centAmount: 147510, + fractionDigits: 2, + }, + }, + ], + images: [ + { + url: 'https://m.media-amazon.com/images/I/71zny7BTRlL._AC_UF1000,1000_QL80_.jpg', + dimensions: { + w: 300, + h: 375, + }, + }, + ], + attributes: [], + assets: [], + }, + price: { + id: 'a78cb404-16a6-4042-8c70-501b1faae21e', + value: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 5080, + fractionDigits: 2, + }, + country: 'US', + }, + quantity: 1, + discountedPrice: { + value: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 2540, + fractionDigits: 2, + }, + includedDiscounts: [ + { + discount: { + typeId: 'cart-discount', + id: '9280bdb9-5cbc-4fce-a2fb-b6fd3143d0df', + }, + discountedAmount: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 2540, + fractionDigits: 2, + }, + }, + ], + }, + discountedPricePerQuantity: [ + { + quantity: 1, + discountedPrice: { + value: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 2540, + fractionDigits: 2, + }, + includedDiscounts: [ + { + discount: { + typeId: 'cart-discount', + id: '9280bdb9-5cbc-4fce-a2fb-b6fd3143d0df', + }, + discountedAmount: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 2540, + fractionDigits: 2, + }, + }, + ], + }, + }, + ], + taxRate: { + name: 'test-tax-category', + amount: 0.2, + includedInPrice: true, + country: 'US', + id: 'HZIq01bI', + subRates: [], + }, + perMethodTaxRate: [], + addedAt: '2024-08-08T13:15:30.028Z', + lastModifiedAt: '2024-08-08T13:15:30.028Z', + state: [ + { + quantity: 1, + state: { + typeId: 'state', + id: 'd5097392-dd2d-45b4-a550-f7ea49700a3a', + }, + }, + ], + priceMode: 'Platform', + lineItemMode: 'Standard', + totalPrice: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 2540, + fractionDigits: 2, + }, + taxedPrice: { + totalNet: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 2117, + fractionDigits: 2, + }, + totalGross: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 2540, + fractionDigits: 2, + }, + taxPortions: [ + { + rate: 0.2, + amount: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 423, + fractionDigits: 2, + }, + name: 'test-tax-category', + }, + ], + totalTax: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 423, + fractionDigits: 2, + }, + }, + taxedPricePortions: [], + }, + ], + cartState: 'Active', + totalPrice: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 63610, + fractionDigits: 2, + }, + taxedPrice: { + totalNet: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 53009, + fractionDigits: 2, + }, + totalGross: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 63610, + fractionDigits: 2, + }, + taxPortions: [ + { + rate: 0.2, + amount: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 10601, + fractionDigits: 2, + }, + name: 'test-tax-category', + }, + ], + totalTax: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 10601, + fractionDigits: 2, + }, + }, + country: 'US', + taxedShippingPrice: { + totalNet: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 825, + fractionDigits: 2, + }, + totalGross: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 990, + fractionDigits: 2, + }, + taxPortions: [ + { + rate: 0.2, + amount: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 165, + fractionDigits: 2, + }, + name: 'test-tax-category', + }, + ], + totalTax: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 165, + fractionDigits: 2, + }, + }, + shippingMode: 'Single', + shippingInfo: { + shippingMethodName: 'Standard Delivery', + price: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 990, + fractionDigits: 2, + }, + shippingRate: { + price: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 990, + fractionDigits: 2, + }, + tiers: [], + }, + taxRate: { + name: 'test-tax-category', + amount: 0.2, + includedInPrice: true, + country: 'US', + id: 'HZIq01bI', + subRates: [], + }, + taxCategory: { + typeId: 'tax-category', + id: 'c04efa03-8e49-4511-8572-315f40a7cbb2', + }, + deliveries: [], + shippingMethod: { + typeId: 'shipping-method', + id: '8ede0c25-0082-4147-8c25-106c38110a14', + }, + taxedPrice: { + totalNet: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 825, + fractionDigits: 2, + }, + totalGross: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 990, + fractionDigits: 2, + }, + taxPortions: [ + { + rate: 0.2, + amount: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 165, + fractionDigits: 2, + }, + name: 'test-tax-category', + }, + ], + totalTax: { + type: 'centPrecision', + currencyCode: 'USD', + centAmount: 165, + fractionDigits: 2, + }, + }, + shippingMethodState: 'MatchesCart', + }, + shipping: [], + customLineItems: [], + discountCodes: [], + directDiscounts: [], + inventoryMode: 'None', + taxMode: 'Platform', + taxRoundingMode: 'HalfEven', + taxCalculationMode: 'LineItemLevel', + deleteDaysAfterLastModification: 90, + refusedGifts: [], + origin: 'Customer', + shippingAddress: { + firstName: 'vignesh', + lastName: 'S', + streetName: '1295 Charleston Road', + postalCode: '94043', + city: 'Mountain View', + region: 'CA', + country: 'US', + phone: '9876543210', + email: 'vignesh@wipro.com', + }, + billingAddress: { + firstName: 'vignesh', + lastName: 'S', + streetName: '1295 Charleston Road', + postalCode: '94043', + city: 'Mountain View', + region: 'CA', + country: 'US', + phone: '9876543210', + email: 'vignesh@wipro.com', + }, + itemShippingAddresses: [], + totalLineItemQuantity: 2, +}; + +export default { + unitPrice, + isShipping, + isCustomLineItem, + isTotalPriceDiscount, + lineItemTotalAmount, + discountedCart, +}; diff --git a/src/unit-tests/const/PayerAuthHelperConst.ts b/src/unit-tests/const/PayerAuthHelperConst.ts index 945bcd6..16189c7 100644 --- a/src/unit-tests/const/PayerAuthHelperConst.ts +++ b/src/unit-tests/const/PayerAuthHelperConst.ts @@ -1,11 +1,11 @@ -import { TokenCreateFlagType } from "../../types/Types"; - - const tokenizeCardForPayerAuthenticationTokenCreateResponse : TokenCreateFlagType = -{ - "isSaveToken":false, - "isError":false -} - -export default { - tokenizeCardForPayerAuthenticationTokenCreateResponse +import { TokenCreateFlagType } from "../../types/Types"; + + const tokenizeCardForPayerAuthenticationTokenCreateResponse : TokenCreateFlagType = +{ + "isSaveToken":false, + "isError":false +} + +export default { + tokenizeCardForPayerAuthenticationTokenCreateResponse } \ No newline at end of file diff --git a/src/unit-tests/const/SyncHelperConst.ts b/src/unit-tests/const/SyncHelperConst.ts index 2582315..6f1444e 100644 --- a/src/unit-tests/const/SyncHelperConst.ts +++ b/src/unit-tests/const/SyncHelperConst.ts @@ -1,14 +1,14 @@ - const syncUpdateObject = { - id: '', - transactionId: '', - version: 0, - interactionId: '', - amountPlanned: { currencyCode: '', centAmount: 0 }, - type: '', - state: '', - securityCodePresent: false - } - - export default { - syncUpdateObject + const syncUpdateObject = { + id: '', + transactionId: '', + version: 0, + interactionId: '', + amountPlanned: { currencyCode: '', centAmount: 0 }, + type: '', + state: '', + securityCodePresent: false + } + + export default { + syncUpdateObject } \ No newline at end of file diff --git a/src/unit-tests/unit/RequestBuilder/LineItemMapper.spec.ts b/src/unit-tests/unit/RequestBuilder/LineItemMapper.spec.ts index 22588c8..29eb727 100644 --- a/src/unit-tests/unit/RequestBuilder/LineItemMapper.spec.ts +++ b/src/unit-tests/unit/RequestBuilder/LineItemMapper.spec.ts @@ -1,43 +1,43 @@ -import test from 'ava'; -import dotenv from 'dotenv'; - -import { FunctionConstant } from '../../../constants/functionConstant'; -import { LineItem } from '../../../requestBuilder/LineItemMapper'; -import CaptureContextServiceConst from '../../const/CaptureContextServiceConst'; -import PaymentAuthorizationServiceConstCC from '../../const/CreditCard/PaymentAuthorizationServiceConstCC'; -import LineItemMapperConst from '../../const/LineItemMapperConst'; - -dotenv.config(); - -const lineItemMapper = new LineItem( - PaymentAuthorizationServiceConstCC.shippingCart.lineItems[0], - LineItemMapperConst.unitPrice, - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - CaptureContextServiceConst.locale, - LineItemMapperConst.discountedCart.lineItems, - PaymentAuthorizationServiceConstCC.payments as any, - LineItemMapperConst.isShipping, - LineItemMapperConst.discountedCart as any, - LineItemMapperConst.isCustomLineItem, - LineItemMapperConst.isTotalPriceDiscount, - LineItemMapperConst.lineItemTotalAmount, -); - -test.serial('Map line item values', async (t) => { - try { - const result = lineItemMapper.getLineItemDetails(); - if (Object.keys(result).length) { - t.is(result.totalAmount, LineItemMapperConst.lineItemTotalAmount); - t.is(result.unitPrice, LineItemMapperConst.unitPrice); - t.is(result.discountAmount, 0); - } else { - t.fail(`Unexpected error: mapUpdateTokenBillTo' ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } +import test from 'ava'; +import dotenv from 'dotenv'; + +import { FunctionConstant } from '../../../constants/functionConstant'; +import { LineItem } from '../../../requestBuilder/LineItemMapper'; +import CaptureContextServiceConst from '../../const/CaptureContextServiceConst'; +import PaymentAuthorizationServiceConstCC from '../../const/CreditCard/PaymentAuthorizationServiceConstCC'; +import LineItemMapperConst from '../../const/LineItemMapperConst'; + +dotenv.config(); + +const lineItemMapper = new LineItem( + PaymentAuthorizationServiceConstCC.shippingCart.lineItems[0], + LineItemMapperConst.unitPrice, + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + CaptureContextServiceConst.locale, + LineItemMapperConst.discountedCart.lineItems, + PaymentAuthorizationServiceConstCC.payments as any, + LineItemMapperConst.isShipping, + LineItemMapperConst.discountedCart as any, + LineItemMapperConst.isCustomLineItem, + LineItemMapperConst.isTotalPriceDiscount, + LineItemMapperConst.lineItemTotalAmount, +); + +test.serial('Map line item values', async (t) => { + try { + const result = lineItemMapper.getLineItemDetails(); + if (Object.keys(result).length) { + t.is(result.totalAmount, LineItemMapperConst.lineItemTotalAmount); + t.is(result.unitPrice, LineItemMapperConst.unitPrice); + t.is(result.discountAmount, 0); + } else { + t.fail(`Unexpected error: mapUpdateTokenBillTo' ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } }); \ No newline at end of file diff --git a/src/unit-tests/unit/RequestBuilder/OrderInformationMapper.spec.ts b/src/unit-tests/unit/RequestBuilder/OrderInformationMapper.spec.ts index 0ef347e..2b542c7 100644 --- a/src/unit-tests/unit/RequestBuilder/OrderInformationMapper.spec.ts +++ b/src/unit-tests/unit/RequestBuilder/OrderInformationMapper.spec.ts @@ -1,193 +1,193 @@ -import test from 'ava'; -import dotenv from 'dotenv'; - -import { FunctionConstant } from '../../../constants/functionConstant'; -import { OrderInformationMapper } from '../../../requestBuilder/OrderInformationMapper'; -import AddTokenServiceConst from '../../const/AddTokenServiceConst'; -import PaymentAuthorizationServiceConstCC from '../../const/CreditCard/PaymentAuthorizationServiceConstCC'; -import LineItemMapperConst from '../../const/LineItemMapperConst'; -import PaymentHandlerConst from '../../const/PaymentHandlerConst'; - -dotenv.config(); - -const orderInformationForAuth = new OrderInformationMapper( - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - PaymentAuthorizationServiceConstCC.payment as any, - PaymentHandlerConst.authorizationHandlerUpdateTransactions, - LineItemMapperConst.discountedCart as any, - AddTokenServiceConst.addTokenResponseCustomerObj, - AddTokenServiceConst.addTokenAddress, - 'Payments', - 'USD', -); -const orderInformationForCharge = new OrderInformationMapper( - FunctionConstant.FUNC_GET_CAPTURE_RESPONSE, - PaymentAuthorizationServiceConstCC.payment as any, - PaymentHandlerConst.authorizationHandlerUpdateTransactions, - LineItemMapperConst.discountedCart as any, - AddTokenServiceConst.addTokenResponseCustomerObj, - AddTokenServiceConst.addTokenAddress, - 'Payments', - 'USD', -); -const orderInformationForRefund = new OrderInformationMapper( - FunctionConstant.FUNC_GET_REFUND_DATA, - PaymentAuthorizationServiceConstCC.payment as any, - PaymentHandlerConst.authorizationHandlerUpdateTransactions, - LineItemMapperConst.discountedCart as any, - AddTokenServiceConst.addTokenResponseCustomerObj, - AddTokenServiceConst.addTokenAddress, - 'Payments', - 'USD', -); -const orderInformationForAuthReversal = new OrderInformationMapper( - FunctionConstant.FUNC_GET_AUTH_REVERSAL_RESPONSE, - PaymentAuthorizationServiceConstCC.payment as any, - PaymentHandlerConst.authorizationHandlerUpdateTransactions, - LineItemMapperConst.discountedCart as any, - AddTokenServiceConst.addTokenResponseCustomerObj, - AddTokenServiceConst.addTokenAddress, - 'Payments', - 'USD', -); -const orderInformationForCaptureContext = new OrderInformationMapper( - FunctionConstant.FUNC_GENERATE_CAPTURE_CONTEXT, - PaymentAuthorizationServiceConstCC.payment as any, - PaymentHandlerConst.authorizationHandlerUpdateTransactions, - LineItemMapperConst.discountedCart as any, - AddTokenServiceConst.addTokenResponseCustomerObj, - AddTokenServiceConst.addTokenAddress, - 'Payments', - 'USD', -); -const orderInformationForAddToken = new OrderInformationMapper( - FunctionConstant.FUNC_GET_ADD_TOKEN_RESPONSE, - PaymentAuthorizationServiceConstCC.payment as any, - PaymentHandlerConst.authorizationHandlerUpdateTransactions, - LineItemMapperConst.discountedCart as any, - AddTokenServiceConst.addTokenResponseCustomerObj, - AddTokenServiceConst.addTokenAddress, - 'Payments', - 'USD', -); - -test.serial('Get order information for auth', (t) => { - try { - const result = orderInformationForAuth.getOrderInformation(); - if ('billTo' in result && 'shipTo' in result && 'lineItems' in result && 'amountDetails' in result) { - t.true(true, 'result contains all required fields'); - } else { - t.fail(`Unexpected error: order information for auth' ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get order information for charge', (t) => { - try { - const result: any = orderInformationForCharge.getOrderInformation(); - if (Object.keys(result).length) { - t.is(result.amountDetails.totalAmount, 69.7); - t.is(result.amountDetails.currency, 'USD'); - } else { - t.fail(`Unexpected error: information for charge' ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get order information for refund', (t) => { - try { - const result: any = orderInformationForRefund.getOrderInformation(); - if (Object.keys(result).length) { - t.is(result.amountDetails.totalAmount, 69.7); - t.is(result.amountDetails.currency, 'USD'); - } else { - t.fail(`Unexpected error: information for refund' ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get order information for auth reversal', (t) => { - try { - const result: any = orderInformationForAuthReversal.getOrderInformation(); - if (Object.keys(result).length) { - t.truthy(result.lineItems[0].productCode); - t.truthy(result.lineItems[0].productName); - t.truthy(result.lineItems[0].productSku); - t.truthy(result.lineItems[0].quantity); - t.truthy(result.lineItems[0].totalAmount); - t.truthy(result.lineItems[0].unitPrice); - } else { - t.fail(`Unexpected error: information for auth reversal' ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get order information for capture context', (t) => { - try { - const result: any = orderInformationForCaptureContext.getOrderInformation(); - if (Object.keys(result).length) { - t.is(result.amountDetails.totalAmount, '636.1'); - t.is(result.amountDetails.currency, 'USD'); - } else { - t.fail(`Unexpected error: information for capture context' ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get order information for add token', (t) => { - try { - const result: any = orderInformationForAddToken.getOrderInformation(); - if (Object.keys(result).length) { - t.truthy(result.billTo.firstName); - t.truthy(result.billTo.lastName); - t.truthy(result.billTo.address1); - t.truthy(result.billTo.address2); - t.truthy(result.billTo.locality); - t.truthy(result.billTo.administrativeArea); - t.truthy(result.billTo.postalCode); - t.truthy(result.billTo.country); - t.truthy(result.billTo.email); - t.truthy(result.billTo.phoneNumber); - t.is(result.amountDetails.totalAmount, 0); - t.is(result.amountDetails.currency, 'USD'); - } else { - t.fail(`Unexpected error: information for add token' ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } +import test from 'ava'; +import dotenv from 'dotenv'; + +import { FunctionConstant } from '../../../constants/functionConstant'; +import { OrderInformationMapper } from '../../../requestBuilder/OrderInformationMapper'; +import AddTokenServiceConst from '../../const/AddTokenServiceConst'; +import PaymentAuthorizationServiceConstCC from '../../const/CreditCard/PaymentAuthorizationServiceConstCC'; +import LineItemMapperConst from '../../const/LineItemMapperConst'; +import PaymentHandlerConst from '../../const/PaymentHandlerConst'; + +dotenv.config(); + +const orderInformationForAuth = new OrderInformationMapper( + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + PaymentAuthorizationServiceConstCC.payment as any, + PaymentHandlerConst.authorizationHandlerUpdateTransactions, + LineItemMapperConst.discountedCart as any, + AddTokenServiceConst.addTokenResponseCustomerObj, + AddTokenServiceConst.addTokenAddress, + 'Payments', + 'USD', +); +const orderInformationForCharge = new OrderInformationMapper( + FunctionConstant.FUNC_GET_CAPTURE_RESPONSE, + PaymentAuthorizationServiceConstCC.payment as any, + PaymentHandlerConst.authorizationHandlerUpdateTransactions, + LineItemMapperConst.discountedCart as any, + AddTokenServiceConst.addTokenResponseCustomerObj, + AddTokenServiceConst.addTokenAddress, + 'Payments', + 'USD', +); +const orderInformationForRefund = new OrderInformationMapper( + FunctionConstant.FUNC_GET_REFUND_DATA, + PaymentAuthorizationServiceConstCC.payment as any, + PaymentHandlerConst.authorizationHandlerUpdateTransactions, + LineItemMapperConst.discountedCart as any, + AddTokenServiceConst.addTokenResponseCustomerObj, + AddTokenServiceConst.addTokenAddress, + 'Payments', + 'USD', +); +const orderInformationForAuthReversal = new OrderInformationMapper( + FunctionConstant.FUNC_GET_AUTH_REVERSAL_RESPONSE, + PaymentAuthorizationServiceConstCC.payment as any, + PaymentHandlerConst.authorizationHandlerUpdateTransactions, + LineItemMapperConst.discountedCart as any, + AddTokenServiceConst.addTokenResponseCustomerObj, + AddTokenServiceConst.addTokenAddress, + 'Payments', + 'USD', +); +const orderInformationForCaptureContext = new OrderInformationMapper( + FunctionConstant.FUNC_GENERATE_CAPTURE_CONTEXT, + PaymentAuthorizationServiceConstCC.payment as any, + PaymentHandlerConst.authorizationHandlerUpdateTransactions, + LineItemMapperConst.discountedCart as any, + AddTokenServiceConst.addTokenResponseCustomerObj, + AddTokenServiceConst.addTokenAddress, + 'Payments', + 'USD', +); +const orderInformationForAddToken = new OrderInformationMapper( + FunctionConstant.FUNC_GET_ADD_TOKEN_RESPONSE, + PaymentAuthorizationServiceConstCC.payment as any, + PaymentHandlerConst.authorizationHandlerUpdateTransactions, + LineItemMapperConst.discountedCart as any, + AddTokenServiceConst.addTokenResponseCustomerObj, + AddTokenServiceConst.addTokenAddress, + 'Payments', + 'USD', +); + +test.serial('Get order information for auth', (t) => { + try { + const result = orderInformationForAuth.getOrderInformation(); + if ('billTo' in result && 'shipTo' in result && 'lineItems' in result && 'amountDetails' in result) { + t.true(true, 'result contains all required fields'); + } else { + t.fail(`Unexpected error: order information for auth' ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get order information for charge', (t) => { + try { + const result: any = orderInformationForCharge.getOrderInformation(); + if (Object.keys(result).length) { + t.is(result.amountDetails.totalAmount, 69.7); + t.is(result.amountDetails.currency, 'USD'); + } else { + t.fail(`Unexpected error: information for charge' ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get order information for refund', (t) => { + try { + const result: any = orderInformationForRefund.getOrderInformation(); + if (Object.keys(result).length) { + t.is(result.amountDetails.totalAmount, 69.7); + t.is(result.amountDetails.currency, 'USD'); + } else { + t.fail(`Unexpected error: information for refund' ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get order information for auth reversal', (t) => { + try { + const result: any = orderInformationForAuthReversal.getOrderInformation(); + if (Object.keys(result).length) { + t.truthy(result.lineItems[0].productCode); + t.truthy(result.lineItems[0].productName); + t.truthy(result.lineItems[0].productSku); + t.truthy(result.lineItems[0].quantity); + t.truthy(result.lineItems[0].totalAmount); + t.truthy(result.lineItems[0].unitPrice); + } else { + t.fail(`Unexpected error: information for auth reversal' ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get order information for capture context', (t) => { + try { + const result: any = orderInformationForCaptureContext.getOrderInformation(); + if (Object.keys(result).length) { + t.is(result.amountDetails.totalAmount, '636.1'); + t.is(result.amountDetails.currency, 'USD'); + } else { + t.fail(`Unexpected error: information for capture context' ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get order information for add token', (t) => { + try { + const result: any = orderInformationForAddToken.getOrderInformation(); + if (Object.keys(result).length) { + t.truthy(result.billTo.firstName); + t.truthy(result.billTo.lastName); + t.truthy(result.billTo.address1); + t.truthy(result.billTo.address2); + t.truthy(result.billTo.locality); + t.truthy(result.billTo.administrativeArea); + t.truthy(result.billTo.postalCode); + t.truthy(result.billTo.country); + t.truthy(result.billTo.email); + t.truthy(result.billTo.phoneNumber); + t.is(result.amountDetails.totalAmount, 0); + t.is(result.amountDetails.currency, 'USD'); + } else { + t.fail(`Unexpected error: information for add token' ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } }); \ No newline at end of file diff --git a/src/unit-tests/unit/RequestBuilder/PaymentInformation.spec.ts b/src/unit-tests/unit/RequestBuilder/PaymentInformation.spec.ts index ead13e8..4b33459 100644 --- a/src/unit-tests/unit/RequestBuilder/PaymentInformation.spec.ts +++ b/src/unit-tests/unit/RequestBuilder/PaymentInformation.spec.ts @@ -1,175 +1,175 @@ - -import test from 'ava'; -import dotenv from 'dotenv'; - -import { FunctionConstant } from '../../../constants/functionConstant'; -import { Constants } from '../../../constants/paymentConstants'; -import { PaymentInformationModel } from '../../../requestBuilder/PaymentInformation'; -import PaymentAuthorizationServiceConstAP from '../../const/ApplePay/PaymentAuthorizationServiceConstAP'; -import PaymentAuthorizationServiceConstCC from '../../const/CreditCard/PaymentAuthorizationServiceConstCC'; -import PaymentAuthorizationServiceConstECDebit from '../../const/ECheck/PaymentAuthorizationServiceConstECDebit'; -import PaymentAuthorizationServiceConstGP from '../../const/GooglePay/PaymentAuthorizationServiceConstGP'; -import PayerAuthenticationSetupServiceConst from '../../const/PayerAuthenticationSetupServiceConst'; - -dotenv.config(); - -const paymentInformationInstance = new PaymentInformationModel(); - -test.serial('Map payment information for credit card authorization', async (t) => { - try { - const result = paymentInformationInstance.mapPaymentInformation( - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - PaymentAuthorizationServiceConstCC.payment as any, - PaymentAuthorizationServiceConstCC.cardTokens, - PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, - ); - - if (Object.keys(result).length) { - t.is(result.customer.id, PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId); - t.is(result.card.typeSelectionIndicator, 1); - } else { - t.fail(`Unexpected error: information for credit card authorization' ${result}`); - } - } catch (error) { - t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); - } -}); - -test.serial('Map payment information for google pay authorization', async (t) => { - try { - const result = paymentInformationInstance.mapPaymentInformation( - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - PaymentAuthorizationServiceConstGP.payment as any, - PaymentAuthorizationServiceConstECDebit.cardTokens, - PaymentAuthorizationServiceConstECDebit.cardTokens.customerTokenId, - ); - - if (Object.keys(result).length) { - t.is(result.fluidData.value, PaymentAuthorizationServiceConstGP.payment.custom.fields.isv_token); - } else { - t.fail(`Unexpected error: information for google pay authorization' ${result}`); - } - } catch (error) { - t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); - } -}); - -test.serial('Map payment information for eCheck authorization', async (t) => { - try { - const result = paymentInformationInstance.mapPaymentInformation( - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - PaymentAuthorizationServiceConstECDebit.payment as any, - PaymentAuthorizationServiceConstECDebit.cardTokens, - PaymentAuthorizationServiceConstECDebit.cardTokens.customerTokenId, - ); - - if (Object.keys(result).length) { - t.is(result.bank.account.type, PaymentAuthorizationServiceConstECDebit.payment.custom.fields.isv_accountType); - t.is(result.bank.account.number, PaymentAuthorizationServiceConstECDebit.payment.custom.fields.isv_accountNumber); - t.is(result.bank.routingNumber, PaymentAuthorizationServiceConstECDebit.payment.custom.fields.isv_routingNumber); - } else { - t.fail(`Unexpected error: information for eCheck authorization' ${result}`); - } - } catch (error) { - t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); - } -}); - -test.serial('Map payment information for add token', async (t) => { - try { - const result = paymentInformationInstance.mapPaymentInformation( - FunctionConstant.FUNC_GET_ADD_TOKEN_RESPONSE, - PaymentAuthorizationServiceConstCC.payment as any, - PaymentAuthorizationServiceConstCC.cardTokens, - PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, - ); - - if (Object.keys(result).length) { - t.is(result.customer.id, PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId); - t.is(result.card.typeSelectionIndicator, 1); - } else { - t.fail(`Unexpected error: information for add token' ${result}`); - } - } catch (error) { - t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); - } -}); - -test.serial('Map payment information for payer auth set up', async (t) => { - try { - const result = paymentInformationInstance.mapPaymentInformation( - FunctionConstant.FUNC_GET_PAYER_AUTH_SETUP_DATA, - PayerAuthenticationSetupServiceConst.payments as any, - PaymentAuthorizationServiceConstCC.cardTokens, - PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, - ); - if (Object.keys(result).length) { - if (result?.customer) { - t.is(result.customer.id, PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId); - } else { - t.fail(); - } - } else { - t.fail(`Unexpected error: information for payer auth set up' ${result}`); - } - } catch (error) { - t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); - } -}); - -test.serial('Map payment information for credit card authorization with saved card', async (t) => { - try { - const result = paymentInformationInstance.mapPaymentInformation( - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - PaymentAuthorizationServiceConstCC.payments as any, - PaymentAuthorizationServiceConstCC.cardTokens, - PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, - ); - - if (Object.keys(result).length) { - t.is(result.customer.id, PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId); - t.is(result.paymentInstrument.id, PaymentAuthorizationServiceConstCC.cardTokens.paymentInstrumentId); - } else { - t.fail(`Unexpected error: information for credit card authorization with saved card' ${result}`); - } - } catch (error) { - t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); - } -}); - -test.serial('Map payment information for apple pay authorization', async (t) => { - try { - const result = paymentInformationInstance.mapPaymentInformation( - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - PaymentAuthorizationServiceConstAP.payment as any, - PaymentAuthorizationServiceConstCC.cardTokens, - PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, - ); - - if (Object.keys(result).length) { - t.is(result.fluidData.value, PaymentAuthorizationServiceConstAP.payment.custom.fields.isv_token); - t.is(result.fluidData.descriptor, Constants.PAYMENT_GATEWAY_APPLE_PAY_DESCRIPTOR); - t.is(result.fluidData.encoding, Constants.BASE_SIXTY_FOUR_ENCODING); - } else { - t.fail(`Unexpected error: information for apple pay authorization' ${result}`); - } - } catch (error) { - t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); - } -}); - -test.serial('Map payment information with empty function name', async (t) => { - try { - const result = paymentInformationInstance.mapPaymentInformation( - '', - PaymentAuthorizationServiceConstCC.payment as any, - PaymentAuthorizationServiceConstCC.cardTokens, - PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, - ); - if (!result) { - t.falsy(result); - } - } catch (error) { - t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); - } + +import test from 'ava'; +import dotenv from 'dotenv'; + +import { FunctionConstant } from '../../../constants/functionConstant'; +import { Constants } from '../../../constants/paymentConstants'; +import { PaymentInformationModel } from '../../../requestBuilder/PaymentInformation'; +import PaymentAuthorizationServiceConstAP from '../../const/ApplePay/PaymentAuthorizationServiceConstAP'; +import PaymentAuthorizationServiceConstCC from '../../const/CreditCard/PaymentAuthorizationServiceConstCC'; +import PaymentAuthorizationServiceConstECDebit from '../../const/ECheck/PaymentAuthorizationServiceConstECDebit'; +import PaymentAuthorizationServiceConstGP from '../../const/GooglePay/PaymentAuthorizationServiceConstGP'; +import PayerAuthenticationSetupServiceConst from '../../const/PayerAuthenticationSetupServiceConst'; + +dotenv.config(); + +const paymentInformationInstance = new PaymentInformationModel(); + +test.serial('Map payment information for credit card authorization', async (t) => { + try { + const result = paymentInformationInstance.mapPaymentInformation( + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + PaymentAuthorizationServiceConstCC.payment as any, + PaymentAuthorizationServiceConstCC.cardTokens, + PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, + ); + + if (Object.keys(result).length) { + t.is(result.customer.id, PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId); + t.is(result.card.typeSelectionIndicator, 1); + } else { + t.fail(`Unexpected error: information for credit card authorization' ${result}`); + } + } catch (error) { + t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); + } +}); + +test.serial('Map payment information for google pay authorization', async (t) => { + try { + const result = paymentInformationInstance.mapPaymentInformation( + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + PaymentAuthorizationServiceConstGP.payment as any, + PaymentAuthorizationServiceConstECDebit.cardTokens, + PaymentAuthorizationServiceConstECDebit.cardTokens.customerTokenId, + ); + + if (Object.keys(result).length) { + t.is(result.fluidData.value, PaymentAuthorizationServiceConstGP.payment.custom.fields.isv_token); + } else { + t.fail(`Unexpected error: information for google pay authorization' ${result}`); + } + } catch (error) { + t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); + } +}); + +test.serial('Map payment information for eCheck authorization', async (t) => { + try { + const result = paymentInformationInstance.mapPaymentInformation( + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + PaymentAuthorizationServiceConstECDebit.payment as any, + PaymentAuthorizationServiceConstECDebit.cardTokens, + PaymentAuthorizationServiceConstECDebit.cardTokens.customerTokenId, + ); + + if (Object.keys(result).length) { + t.is(result.bank.account.type, PaymentAuthorizationServiceConstECDebit.payment.custom.fields.isv_accountType); + t.is(result.bank.account.number, PaymentAuthorizationServiceConstECDebit.payment.custom.fields.isv_accountNumber); + t.is(result.bank.routingNumber, PaymentAuthorizationServiceConstECDebit.payment.custom.fields.isv_routingNumber); + } else { + t.fail(`Unexpected error: information for eCheck authorization' ${result}`); + } + } catch (error) { + t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); + } +}); + +test.serial('Map payment information for add token', async (t) => { + try { + const result = paymentInformationInstance.mapPaymentInformation( + FunctionConstant.FUNC_GET_ADD_TOKEN_RESPONSE, + PaymentAuthorizationServiceConstCC.payment as any, + PaymentAuthorizationServiceConstCC.cardTokens, + PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, + ); + + if (Object.keys(result).length) { + t.is(result.customer.id, PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId); + t.is(result.card.typeSelectionIndicator, 1); + } else { + t.fail(`Unexpected error: information for add token' ${result}`); + } + } catch (error) { + t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); + } +}); + +test.serial('Map payment information for payer auth set up', async (t) => { + try { + const result = paymentInformationInstance.mapPaymentInformation( + FunctionConstant.FUNC_GET_PAYER_AUTH_SETUP_DATA, + PayerAuthenticationSetupServiceConst.payments as any, + PaymentAuthorizationServiceConstCC.cardTokens, + PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, + ); + if (Object.keys(result).length) { + if (result?.customer) { + t.is(result.customer.id, PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId); + } else { + t.fail(); + } + } else { + t.fail(`Unexpected error: information for payer auth set up' ${result}`); + } + } catch (error) { + t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); + } +}); + +test.serial('Map payment information for credit card authorization with saved card', async (t) => { + try { + const result = paymentInformationInstance.mapPaymentInformation( + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + PaymentAuthorizationServiceConstCC.payments as any, + PaymentAuthorizationServiceConstCC.cardTokens, + PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, + ); + + if (Object.keys(result).length) { + t.is(result.customer.id, PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId); + t.is(result.paymentInstrument.id, PaymentAuthorizationServiceConstCC.cardTokens.paymentInstrumentId); + } else { + t.fail(`Unexpected error: information for credit card authorization with saved card' ${result}`); + } + } catch (error) { + t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); + } +}); + +test.serial('Map payment information for apple pay authorization', async (t) => { + try { + const result = paymentInformationInstance.mapPaymentInformation( + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + PaymentAuthorizationServiceConstAP.payment as any, + PaymentAuthorizationServiceConstCC.cardTokens, + PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, + ); + + if (Object.keys(result).length) { + t.is(result.fluidData.value, PaymentAuthorizationServiceConstAP.payment.custom.fields.isv_token); + t.is(result.fluidData.descriptor, Constants.PAYMENT_GATEWAY_APPLE_PAY_DESCRIPTOR); + t.is(result.fluidData.encoding, Constants.BASE_SIXTY_FOUR_ENCODING); + } else { + t.fail(`Unexpected error: information for apple pay authorization' ${result}`); + } + } catch (error) { + t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); + } +}); + +test.serial('Map payment information with empty function name', async (t) => { + try { + const result = paymentInformationInstance.mapPaymentInformation( + '', + PaymentAuthorizationServiceConstCC.payment as any, + PaymentAuthorizationServiceConstCC.cardTokens, + PaymentAuthorizationServiceConstCC.cardTokens.customerTokenId, + ); + if (!result) { + t.falsy(result); + } + } catch (error) { + t.fail(`Caught an error during execution: ${error instanceof Error ? error.message : String(error)}`); + } }); \ No newline at end of file diff --git a/src/unit-tests/unit/RequestBuilder/ProcessingInformationMapper.spec.ts b/src/unit-tests/unit/RequestBuilder/ProcessingInformationMapper.spec.ts index 868b484..2d1876b 100644 --- a/src/unit-tests/unit/RequestBuilder/ProcessingInformationMapper.spec.ts +++ b/src/unit-tests/unit/RequestBuilder/ProcessingInformationMapper.spec.ts @@ -1,196 +1,196 @@ -import test from 'ava'; -import dotenv from 'dotenv'; - -import { FunctionConstant } from '../../../constants/functionConstant'; -import { ProcessingInformation } from '../../../requestBuilder/ProcessingInformationMapper'; -import PaymentAuthorizationServiceConstAP from '../../const/ApplePay/PaymentAuthorizationServiceConstAP'; -import PaymentAuthorizationServiceVsConst from '../../const/ClickToPay/PaymentAuthorizationServiceVsConst'; -import PaymentAuthorizationReversalConstCC from '../../const/CreditCard/PaymentAuthorizationReversalConstCC'; -import PaymentAuthorizationServiceConstCC from '../../const/CreditCard/PaymentAuthorizationServiceConstCC'; -import PaymentAuthorizationServiceConstGP from '../../const/GooglePay/PaymentAuthorizationServiceConstGP'; - -dotenv.config(); - -const processingInformation = new ProcessingInformation( - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - PaymentAuthorizationServiceConstCC.payment as any, - PaymentAuthorizationServiceConstCC.orderNo, - PaymentAuthorizationServiceConstCC.service, - PaymentAuthorizationServiceConstCC.cardTokens, - false, -); -const processingInformationForClickToPay = new ProcessingInformation( - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - PaymentAuthorizationServiceVsConst.payment as any, - PaymentAuthorizationServiceConstGP.orderNo, - PaymentAuthorizationServiceConstGP.service, - PaymentAuthorizationServiceConstGP.cardTokens, - false, -); -const processingInformationForUCClickToPay = new ProcessingInformation( - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - PaymentAuthorizationServiceVsConst.payment as any, - PaymentAuthorizationServiceConstGP.orderNo, - PaymentAuthorizationServiceConstGP.service, - PaymentAuthorizationServiceConstGP.cardTokens, - false, -); -const processingInformationForGooglePay = new ProcessingInformation( - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - PaymentAuthorizationServiceConstGP.payment as any, - PaymentAuthorizationServiceConstGP.orderNo, - PaymentAuthorizationServiceConstGP.service, - PaymentAuthorizationServiceConstGP.cardTokens, - false, -); -const processingInformationForApplePay = new ProcessingInformation( - FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, - PaymentAuthorizationServiceConstAP.payment as any, - PaymentAuthorizationServiceConstGP.orderNo, - PaymentAuthorizationServiceConstGP.service, - PaymentAuthorizationServiceConstGP.cardTokens, - false, -); -const processingInformationForAuthReversal = new ProcessingInformation( - FunctionConstant.FUNC_GET_AUTH_REVERSAL_RESPONSE, - PaymentAuthorizationReversalConstCC.payment as any, - PaymentAuthorizationServiceConstGP.orderNo, - PaymentAuthorizationServiceConstGP.service, - PaymentAuthorizationServiceConstGP.cardTokens, - false, -); -const processingInformationForRefund = new ProcessingInformation( - FunctionConstant.FUNC_GET_REFUND_DATA, - PaymentAuthorizationReversalConstCC.payment as any, - PaymentAuthorizationServiceConstGP.orderNo, - PaymentAuthorizationServiceConstGP.service, - PaymentAuthorizationServiceConstGP.cardTokens, - false, -); - -test.serial('Get processing information for credit card', async (t) => { - try { - const result = processingInformation.getProcessingInformation(); - if (!result.length) { - t.deepEqual(result.actionList, []); - } else { - t.fail(`Unexpected error: information for credit card processing' ${JSON.stringify(result)}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get processing information for click to pay', async (t) => { - try { - const result = processingInformationForClickToPay.getProcessingInformation(); - if (!result.length) { - t.deepEqual(result.actionList, []); - t.is(result.paymentSolution, 'visaCheckout'); - t.is(result.visaCheckoutId, PaymentAuthorizationServiceVsConst.payment.custom.fields.isv_token); - } else { - t.fail(`Unexpected error: information for click to pay' ${JSON.stringify(result)}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get processing information for unified checkout click to pay', async (t) => { - try { - const result = processingInformationForUCClickToPay.getProcessingInformation(); - if (!result?.length) { - t.deepEqual(result.actionList, []); - t.is(result.paymentSolution, 'visaCheckout'); - } else { - t.fail(`Unexpected error: information for unified checkout click to pay' ${JSON.stringify(result)}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get processing information for google pay', async (t) => { - try { - const result = processingInformationForGooglePay.getProcessingInformation(); - - if (!result.length) { - t.deepEqual(result.actionList, []); - t.is(result.paymentSolution, '012'); - } else { - t.fail(`Unexpected error: information for google pay' ${JSON.stringify(result)}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get processing information for apple pay', async (t) => { - try { - const result = processingInformationForApplePay.getProcessingInformation(); - - if (!result.length) { - t.deepEqual(result.actionList, []); - t.is(result.paymentSolution, '001'); - } else { - t.fail(`Unexpected error: information for apple pay' ${JSON.stringify(result)}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get processing information for auth reversal', async (t) => { - try { - const result = processingInformationForAuthReversal.getProcessingInformation(); - - if (!result.length) { - t.deepEqual(result.actionList, []); - } else { - t.fail(`Unexpected error: information for auth reversal' ${JSON.stringify(result)}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get processing information for refund', async (t) => { - try { - const result = processingInformationForRefund.getProcessingInformation(); - if (!result.length) { - t.deepEqual(result.actionList, []); - } else { - t.fail(`Unexpected error: information for refund' ${JSON.stringify(result)}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } +import test from 'ava'; +import dotenv from 'dotenv'; + +import { FunctionConstant } from '../../../constants/functionConstant'; +import { ProcessingInformation } from '../../../requestBuilder/ProcessingInformationMapper'; +import PaymentAuthorizationServiceConstAP from '../../const/ApplePay/PaymentAuthorizationServiceConstAP'; +import PaymentAuthorizationServiceVsConst from '../../const/ClickToPay/PaymentAuthorizationServiceVsConst'; +import PaymentAuthorizationReversalConstCC from '../../const/CreditCard/PaymentAuthorizationReversalConstCC'; +import PaymentAuthorizationServiceConstCC from '../../const/CreditCard/PaymentAuthorizationServiceConstCC'; +import PaymentAuthorizationServiceConstGP from '../../const/GooglePay/PaymentAuthorizationServiceConstGP'; + +dotenv.config(); + +const processingInformation = new ProcessingInformation( + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + PaymentAuthorizationServiceConstCC.payment as any, + PaymentAuthorizationServiceConstCC.orderNo, + PaymentAuthorizationServiceConstCC.service, + PaymentAuthorizationServiceConstCC.cardTokens, + false, +); +const processingInformationForClickToPay = new ProcessingInformation( + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + PaymentAuthorizationServiceVsConst.payment as any, + PaymentAuthorizationServiceConstGP.orderNo, + PaymentAuthorizationServiceConstGP.service, + PaymentAuthorizationServiceConstGP.cardTokens, + false, +); +const processingInformationForUCClickToPay = new ProcessingInformation( + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + PaymentAuthorizationServiceVsConst.payment as any, + PaymentAuthorizationServiceConstGP.orderNo, + PaymentAuthorizationServiceConstGP.service, + PaymentAuthorizationServiceConstGP.cardTokens, + false, +); +const processingInformationForGooglePay = new ProcessingInformation( + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + PaymentAuthorizationServiceConstGP.payment as any, + PaymentAuthorizationServiceConstGP.orderNo, + PaymentAuthorizationServiceConstGP.service, + PaymentAuthorizationServiceConstGP.cardTokens, + false, +); +const processingInformationForApplePay = new ProcessingInformation( + FunctionConstant.FUNC_GET_AUTHORIZATION_RESPONSE, + PaymentAuthorizationServiceConstAP.payment as any, + PaymentAuthorizationServiceConstGP.orderNo, + PaymentAuthorizationServiceConstGP.service, + PaymentAuthorizationServiceConstGP.cardTokens, + false, +); +const processingInformationForAuthReversal = new ProcessingInformation( + FunctionConstant.FUNC_GET_AUTH_REVERSAL_RESPONSE, + PaymentAuthorizationReversalConstCC.payment as any, + PaymentAuthorizationServiceConstGP.orderNo, + PaymentAuthorizationServiceConstGP.service, + PaymentAuthorizationServiceConstGP.cardTokens, + false, +); +const processingInformationForRefund = new ProcessingInformation( + FunctionConstant.FUNC_GET_REFUND_DATA, + PaymentAuthorizationReversalConstCC.payment as any, + PaymentAuthorizationServiceConstGP.orderNo, + PaymentAuthorizationServiceConstGP.service, + PaymentAuthorizationServiceConstGP.cardTokens, + false, +); + +test.serial('Get processing information for credit card', async (t) => { + try { + const result = processingInformation.getProcessingInformation(); + if (!result.length) { + t.deepEqual(result.actionList, []); + } else { + t.fail(`Unexpected error: information for credit card processing' ${JSON.stringify(result)}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get processing information for click to pay', async (t) => { + try { + const result = processingInformationForClickToPay.getProcessingInformation(); + if (!result.length) { + t.deepEqual(result.actionList, []); + t.is(result.paymentSolution, 'visaCheckout'); + t.is(result.visaCheckoutId, PaymentAuthorizationServiceVsConst.payment.custom.fields.isv_token); + } else { + t.fail(`Unexpected error: information for click to pay' ${JSON.stringify(result)}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get processing information for unified checkout click to pay', async (t) => { + try { + const result = processingInformationForUCClickToPay.getProcessingInformation(); + if (!result?.length) { + t.deepEqual(result.actionList, []); + t.is(result.paymentSolution, 'visaCheckout'); + } else { + t.fail(`Unexpected error: information for unified checkout click to pay' ${JSON.stringify(result)}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get processing information for google pay', async (t) => { + try { + const result = processingInformationForGooglePay.getProcessingInformation(); + + if (!result.length) { + t.deepEqual(result.actionList, []); + t.is(result.paymentSolution, '012'); + } else { + t.fail(`Unexpected error: information for google pay' ${JSON.stringify(result)}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get processing information for apple pay', async (t) => { + try { + const result = processingInformationForApplePay.getProcessingInformation(); + + if (!result.length) { + t.deepEqual(result.actionList, []); + t.is(result.paymentSolution, '001'); + } else { + t.fail(`Unexpected error: information for apple pay' ${JSON.stringify(result)}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get processing information for auth reversal', async (t) => { + try { + const result = processingInformationForAuthReversal.getProcessingInformation(); + + if (!result.length) { + t.deepEqual(result.actionList, []); + } else { + t.fail(`Unexpected error: information for auth reversal' ${JSON.stringify(result)}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get processing information for refund', async (t) => { + try { + const result = processingInformationForRefund.getProcessingInformation(); + if (!result.length) { + t.deepEqual(result.actionList, []); + } else { + t.fail(`Unexpected error: information for refund' ${JSON.stringify(result)}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } }); \ No newline at end of file diff --git a/src/unit-tests/unit/TokenValidation.spec.ts b/src/unit-tests/unit/TokenValidation.spec.ts new file mode 100644 index 0000000..eecc8cb --- /dev/null +++ b/src/unit-tests/unit/TokenValidation.spec.ts @@ -0,0 +1,102 @@ +import test from 'ava'; +import dotenv from 'dotenv'; + +import apiController from '../../apiController'; + +dotenv.config(); + +// ============================================================ +// Negative tests for isValidTokenSchema +// ============================================================ + +test.serial('isValidTokenSchema rejects null input', (t) => { + t.false(apiController.isValidTokenSchema(null)); +}); + +test.serial('isValidTokenSchema rejects undefined input', (t) => { + t.false(apiController.isValidTokenSchema(undefined)); +}); + +test.serial('isValidTokenSchema rejects array input', (t) => { + t.false(apiController.isValidTokenSchema([{ paymentToken: 'abc', value: 'def' }])); +}); + +test.serial('isValidTokenSchema rejects string input', (t) => { + t.false(apiController.isValidTokenSchema('not an object')); +}); + +test.serial('isValidTokenSchema rejects number input', (t) => { + t.false(apiController.isValidTokenSchema(123)); +}); + +test.serial('isValidTokenSchema rejects object with missing paymentToken', (t) => { + t.false(apiController.isValidTokenSchema({ value: 'someValue', alias: 'myCard' })); +}); + +test.serial('isValidTokenSchema rejects object with missing value field', (t) => { + t.false(apiController.isValidTokenSchema({ paymentToken: 'token123' })); +}); + +test.serial('isValidTokenSchema rejects object with empty paymentToken', (t) => { + t.false(apiController.isValidTokenSchema({ paymentToken: '', value: 'someValue' })); +}); + +test.serial('isValidTokenSchema rejects object with whitespace-only paymentToken', (t) => { + t.false(apiController.isValidTokenSchema({ paymentToken: ' ', value: 'someValue' })); +}); + +test.serial('isValidTokenSchema rejects object with empty value field', (t) => { + t.false(apiController.isValidTokenSchema({ paymentToken: 'token123', value: '' })); +}); + +test.serial('isValidTokenSchema rejects object with extra/unexpected fields', (t) => { + t.false(apiController.isValidTokenSchema({ + paymentToken: 'token123', + value: 'someValue', + maliciousField: 'attack', + })); +}); + +test.serial('isValidTokenSchema rejects object with __proto__ field', (t) => { + const malicious = JSON.parse('{"paymentToken":"tok","value":"val","__proto__":{"admin":true}}'); + t.false(apiController.isValidTokenSchema(malicious)); +}); + +test.serial('isValidTokenSchema rejects object with constructor field', (t) => { + t.false(apiController.isValidTokenSchema({ + paymentToken: 'token123', + value: 'someValue', + constructor: 'malicious', + })); +}); + +test.serial('isValidTokenSchema rejects object with non-string paymentToken', (t) => { + t.false(apiController.isValidTokenSchema({ paymentToken: 12345, value: 'someValue' })); +}); + +test.serial('isValidTokenSchema rejects object with non-string value for allowed field', (t) => { + t.false(apiController.isValidTokenSchema({ + paymentToken: 'token123', + value: 'someValue', + cardExpiryMonth: 12, + })); +}); + +test.serial('isValidTokenSchema accepts valid token object', (t) => { + t.true(apiController.isValidTokenSchema({ + paymentToken: 'token123', + value: 'customerTokenId', + alias: 'My Visa Card', + cardType: 'visa', + cardNumber: '411111XXXXXX1111', + cardExpiryMonth: '12', + cardExpiryYear: '2028', + })); +}); + +test.serial('isValidTokenSchema accepts minimal valid token', (t) => { + t.true(apiController.isValidTokenSchema({ + paymentToken: 'abc', + value: 'def', + })); +}); diff --git a/src/unit-tests/unit/utils/PaymentActions.spec.ts b/src/unit-tests/unit/utils/PaymentActions.spec.ts index 120412b..560cc8d 100644 --- a/src/unit-tests/unit/utils/PaymentActions.spec.ts +++ b/src/unit-tests/unit/utils/PaymentActions.spec.ts @@ -1,296 +1,296 @@ -import test from 'ava'; -import dotenv from 'dotenv'; - -import paymentActions from '../../../utils/PaymentActions'; -import PaymentAuthorizationServiceConstCC from '../../const/CreditCard/PaymentAuthorizationServiceConstCC'; -import PaymentServiceConst from '../../const/HelpersConst'; -import PaymentHandlerConst from '../../const/PaymentHandlerConst'; -import PaymentUtilsConst from '../../const/PaymentUtilsConst'; - -dotenv.config(); - -test.serial('Add refund action', async (t) => { - try { - const result = paymentActions.addRefundAction(PaymentServiceConst.addRefundActionAmount, PaymentServiceConst.addRefundActionOrderResponse, PaymentServiceConst.state); - - if (result?.action && result?.transaction) { - t.is(result.action, 'addTransaction'); - t.is(result.transaction.state, 'Success'); - } else { - t.fail(`Unexpected error: information for refund is invalid: ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Add refund action when state is empty', async (t) => { - try { - const result = paymentActions.addRefundAction(PaymentServiceConst.addRefundActionAmount, PaymentServiceConst.addRefundActionOrderResponse, ''); - - if (result?.action && result?.transaction) { - t.is(result.action, 'addTransaction'); - t.is(result.transaction.state, ''); - } else { - t.fail(`Unexpected error: information for refund is invalid: ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get the create response function when transaction is failed', async (t: any) => { - try { - let result: any = paymentActions.createResponse(PaymentServiceConst.createResponseSetTransaction, PaymentServiceConst.createTransactionSetFailedCustomField, PaymentServiceConst.createTransactionPaymentFailure, PaymentServiceConst.createTransactionSetCustomType); - if (Array.isArray(result?.actions) && result.actions.length !== 0) { - t.is(result.actions[0].action, 'changeTransactionInteractionId'); - t.is(result.actions[0].interactionId, PaymentServiceConst.createResponseSetTransaction.interactionId); - t.is(result.actions[1].action, 'changeTransactionState'); - t.is(result.actions[1].state, PaymentServiceConst.createTransactionSetFailedCustomField.state); - } else { - t.fail(`Unexpected get the create response: ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - t.log(`Stack trace: ${error.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get the create response function ', async (t: any) => { - try { - let result: any = paymentActions.createResponse(PaymentServiceConst.createResponseSetTransaction, PaymentServiceConst.createTransactionSetCustomField, null, null); - if (Array.isArray(result?.actions) && result.actions.length !== 0) { - t.is(result.actions[0].action, 'changeTransactionInteractionId'); - t.is(result.actions[0].interactionId, PaymentServiceConst.createResponseSetTransaction.interactionId); - t.is(result.actions[1].action, 'changeTransactionState'); - t.is(result.actions[1].state, PaymentServiceConst.createTransactionSetCustomField.state); - } else { - t.fail(`Unexpected error create response ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - t.log(`Stack trace: ${error.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Check visa card detail action ', async (t: any) => { - try { - let result = paymentActions.cardDetailsActions(PaymentServiceConst.visaCardDetailsActionVisaCheckoutData); - if (Array.isArray(result) && result.length !== 0) { - t.is(result[0].action, 'setCustomField'); - t.is(result[0].name, 'isv_maskedPan'); - t.is(result[1].action, 'setCustomField'); - t.is(result[1].name, 'isv_cardExpiryMonth'); - t.is(result[2].action, 'setCustomField'); - t.is(result[2].name, 'isv_cardExpiryYear'); - t.is(result[3].action, 'setCustomField'); - t.is(result[3].name, 'isv_cardType'); - } else { - t.fail(`Unexpected error create response ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - t.log(`Stack trace: ${error.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Check visa card detail action with empty data', async (t: any) => { - try { - let result = paymentActions.cardDetailsActions(PaymentServiceConst.visaCardDetailsActionVisaCheckoutEmptyData); - if (Array.isArray(result) && result.length === 0) { - t.deepEqual(result, []); - } else { - t.fail(`Unexpected error create response ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - t.log(`Stack trace: ${error.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get update token actions ', async (t: any) => { - try { - let result = paymentActions.getUpdateTokenActions(PaymentServiceConst.getUpdateTokenActionsActions, [], true, PaymentServiceConst.deleteTokenCustomerObj, null); - if (result?.actions[0].action) { - if (PaymentServiceConst.deleteTokenCustomerObj?.custom?.type?.id) { - t.is(result.actions[0].action, 'setCustomField'); - } else if (result?.actions[0]?.type?.key) { - t.is(result.actions[0].action, 'setCustomType'); - t.is(result.actions[0].type.key, 'isv_payments_customer_tokens'); - } else { - t.fail(`Unexpected error create response ${result}`); - } - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - t.log(`Stack trace: ${error.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get update token actions when tokens has invalid values', async (t: any) => { - try { - let result = paymentActions.getUpdateTokenActions(PaymentServiceConst.getUpdateInvalidTokenActionsActions, [], true, PaymentServiceConst.deleteTokenCustomerObj, null); - if (result?.actions[0].action) { - if (PaymentServiceConst.deleteTokenCustomerObj?.custom?.type?.id) { - t.is(result.actions[0].action, 'setCustomField'); - } else if (result?.actions[0]?.type?.key) { - t.is(result.actions[0].action, 'setCustomType'); - t.is(result.actions[0].type.key, 'isv_payments_customer_tokens'); - } else { - t.fail(`Unexpected error create response ${result}`); - } - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - t.log(`Stack trace: ${error.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Handle auth application', async (t) => { - try { - let result = await paymentActions.handleAuthApplication(PaymentAuthorizationServiceConstCC.payment as any, PaymentServiceConst.handleAuthApplication, PaymentServiceConst.authResponse, PaymentServiceConst.retrieveSyncResponseTransactionElement); - if (Array.isArray(result?.actions) && result.actions.length !== 0) { - t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); - t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); - t.is(result.actions[2].name, 'isv_payerEnrollStatus'); - t.is(result.actions[3].name, 'isv_payerAuthenticationTransactionId'); - t.is(result.actions[4].name, 'isv_tokenCaptureContextSignature'); - t.is(result.actions[5].name, 'isv_payerAuthenticationRequired'); - t.is(result.actions[6].action, 'addTransaction'); - } else { - t.fail(`Unexpected error Handle auth ${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - t.log(`Stack trace: ${error.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get payer auth actions when response is empty', async (t: any) => { - try { - let result = paymentActions.payerAuthActions(PaymentServiceConst.payerAuthActionsEmptyResponse); - if (Array.isArray(result) && result.length !== 0) { - t.is(result[0].action, 'setCustomField'); - t.is(result[0].name, 'isv_payerAuthenticationRequired'); - t.is(result[1].name, 'isv_payerAuthenticationTransactionId'); - t.is(result[2].name, 'isv_payerAuthenticationAcsUrl'); - t.is(result[3].name, 'isv_payerAuthenticationPaReq'); - t.is(result[4].name, 'isv_stepUpUrl'); - t.is(result[5].name, 'isv_responseJwt'); - } else { - t.fail(`Unexpected error payer auth action${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - t.log(`Stack trace: ${error.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get payer auth actions ', async (t: any) => { - try { - let result = paymentActions.payerAuthActions(PaymentServiceConst.payerAuthActionsResponse); - if (Array.isArray(result) && result.length != 0 && result[result.length - 1]?.fields?.authenticationRequired) { - t.is(result[result.length - 1].action, 'addInterfaceInteraction'); - t.is(result[result.length - 1]?.fields?.authenticationRequired, true); - t.is(result[0].name, 'isv_payerAuthenticationRequired'); - t.is(result[0].value, true); - t.is(result[1].name, 'isv_payerAuthenticationTransactionId'); - t.is(result[2].name, 'isv_payerAuthenticationAcsUrl'); - t.is(result[3].name, 'isv_payerAuthenticationPaReq'); - t.is(result[4].name, 'isv_stepUpUrl'); - t.is(result[5].name, 'isv_responseJwt'); - } else { - t.fail(`Unexpected error payer auth action${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - t.log(`Stack trace: ${error.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get payer auth validate response', async (t) => { - try { - let result = await paymentActions.payerAuthValidateActions(PaymentServiceConst.authResponse, PaymentServiceConst.payerEnrollActionsResponse); - if (result.actions.length != 0) { - t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); - t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); - t.is(result.actions[2].name, 'isv_payerEnrollStatus'); - t.is(result.actions[3].name, 'isv_payerAuthenticationTransactionId'); - t.is(result.actions[4].name, 'isv_tokenCaptureContextSignature'); - t.is(result.actions[5].name, 'isv_payerAuthenticationRequired'); - t.is(result.actions[6].action, 'addTransaction'); - t.is(result.actions[7].action, 'addInterfaceInteraction'); - } else { - t.fail(`Unexpected error payer auth action${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - t.log(`Stack trace: ${error.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Create enroll response actions ', (t) => { - try { - const result = paymentActions.createEnrollResponseActions(PaymentUtilsConst.setTransactionIdPaymentResponse, PaymentHandlerConst.getPayerAuthValidateResponseUpdatePaymentObj as any); - if (result) { - t.pass(); - } else { - t.fail(`Unexpected error payer auth action${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - t.log(`Stack trace: ${error.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } +import test from 'ava'; +import dotenv from 'dotenv'; + +import paymentActions from '../../../utils/PaymentActions'; +import PaymentAuthorizationServiceConstCC from '../../const/CreditCard/PaymentAuthorizationServiceConstCC'; +import PaymentServiceConst from '../../const/HelpersConst'; +import PaymentHandlerConst from '../../const/PaymentHandlerConst'; +import PaymentUtilsConst from '../../const/PaymentUtilsConst'; + +dotenv.config(); + +test.serial('Add refund action', async (t) => { + try { + const result = paymentActions.addRefundAction(PaymentServiceConst.addRefundActionAmount, PaymentServiceConst.addRefundActionOrderResponse, PaymentServiceConst.state); + + if (result?.action && result?.transaction) { + t.is(result.action, 'addTransaction'); + t.is(result.transaction.state, 'Success'); + } else { + t.fail(`Unexpected error: information for refund is invalid: ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Add refund action when state is empty', async (t) => { + try { + const result = paymentActions.addRefundAction(PaymentServiceConst.addRefundActionAmount, PaymentServiceConst.addRefundActionOrderResponse, ''); + + if (result?.action && result?.transaction) { + t.is(result.action, 'addTransaction'); + t.is(result.transaction.state, ''); + } else { + t.fail(`Unexpected error: information for refund is invalid: ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get the create response function when transaction is failed', async (t: any) => { + try { + let result: any = paymentActions.createResponse(PaymentServiceConst.createResponseSetTransaction, PaymentServiceConst.createTransactionSetFailedCustomField, PaymentServiceConst.createTransactionPaymentFailure, PaymentServiceConst.createTransactionSetCustomType); + if (Array.isArray(result?.actions) && result.actions.length !== 0) { + t.is(result.actions[0].action, 'changeTransactionInteractionId'); + t.is(result.actions[0].interactionId, PaymentServiceConst.createResponseSetTransaction.interactionId); + t.is(result.actions[1].action, 'changeTransactionState'); + t.is(result.actions[1].state, PaymentServiceConst.createTransactionSetFailedCustomField.state); + } else { + t.fail(`Unexpected get the create response: ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + t.log(`Stack trace: ${error.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get the create response function ', async (t: any) => { + try { + let result: any = paymentActions.createResponse(PaymentServiceConst.createResponseSetTransaction, PaymentServiceConst.createTransactionSetCustomField, null, null); + if (Array.isArray(result?.actions) && result.actions.length !== 0) { + t.is(result.actions[0].action, 'changeTransactionInteractionId'); + t.is(result.actions[0].interactionId, PaymentServiceConst.createResponseSetTransaction.interactionId); + t.is(result.actions[1].action, 'changeTransactionState'); + t.is(result.actions[1].state, PaymentServiceConst.createTransactionSetCustomField.state); + } else { + t.fail(`Unexpected error create response ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + t.log(`Stack trace: ${error.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Check visa card detail action ', async (t: any) => { + try { + let result = paymentActions.cardDetailsActions(PaymentServiceConst.visaCardDetailsActionVisaCheckoutData); + if (Array.isArray(result) && result.length !== 0) { + t.is(result[0].action, 'setCustomField'); + t.is(result[0].name, 'isv_maskedPan'); + t.is(result[1].action, 'setCustomField'); + t.is(result[1].name, 'isv_cardExpiryMonth'); + t.is(result[2].action, 'setCustomField'); + t.is(result[2].name, 'isv_cardExpiryYear'); + t.is(result[3].action, 'setCustomField'); + t.is(result[3].name, 'isv_cardType'); + } else { + t.fail(`Unexpected error create response ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + t.log(`Stack trace: ${error.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Check visa card detail action with empty data', async (t: any) => { + try { + let result = paymentActions.cardDetailsActions(PaymentServiceConst.visaCardDetailsActionVisaCheckoutEmptyData); + if (Array.isArray(result) && result.length === 0) { + t.deepEqual(result, []); + } else { + t.fail(`Unexpected error create response ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + t.log(`Stack trace: ${error.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get update token actions ', async (t: any) => { + try { + let result = paymentActions.getUpdateTokenActions(PaymentServiceConst.getUpdateTokenActionsActions, [], true, PaymentServiceConst.deleteTokenCustomerObj, null); + if (result?.actions[0].action) { + if (PaymentServiceConst.deleteTokenCustomerObj?.custom?.type?.id) { + t.is(result.actions[0].action, 'setCustomField'); + } else if (result?.actions[0]?.type?.key) { + t.is(result.actions[0].action, 'setCustomType'); + t.is(result.actions[0].type.key, 'isv_payments_customer_tokens'); + } else { + t.fail(`Unexpected error create response ${result}`); + } + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + t.log(`Stack trace: ${error.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get update token actions when tokens has invalid values', async (t: any) => { + try { + let result = paymentActions.getUpdateTokenActions(PaymentServiceConst.getUpdateInvalidTokenActionsActions, [], true, PaymentServiceConst.deleteTokenCustomerObj, null); + if (result?.actions[0].action) { + if (PaymentServiceConst.deleteTokenCustomerObj?.custom?.type?.id) { + t.is(result.actions[0].action, 'setCustomField'); + } else if (result?.actions[0]?.type?.key) { + t.is(result.actions[0].action, 'setCustomType'); + t.is(result.actions[0].type.key, 'isv_payments_customer_tokens'); + } else { + t.fail(`Unexpected error create response ${result}`); + } + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + t.log(`Stack trace: ${error.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Handle auth application', async (t) => { + try { + let result = await paymentActions.handleAuthApplication(PaymentAuthorizationServiceConstCC.payment as any, PaymentServiceConst.handleAuthApplication, PaymentServiceConst.authResponse, PaymentServiceConst.retrieveSyncResponseTransactionElement); + if (Array.isArray(result?.actions) && result.actions.length !== 0) { + t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); + t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); + t.is(result.actions[2].name, 'isv_payerEnrollStatus'); + t.is(result.actions[3].name, 'isv_payerAuthenticationTransactionId'); + t.is(result.actions[4].name, 'isv_tokenCaptureContextSignature'); + t.is(result.actions[5].name, 'isv_payerAuthenticationRequired'); + t.is(result.actions[6].action, 'addTransaction'); + } else { + t.fail(`Unexpected error Handle auth ${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + t.log(`Stack trace: ${error.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get payer auth actions when response is empty', async (t: any) => { + try { + let result = paymentActions.payerAuthActions(PaymentServiceConst.payerAuthActionsEmptyResponse); + if (Array.isArray(result) && result.length !== 0) { + t.is(result[0].action, 'setCustomField'); + t.is(result[0].name, 'isv_payerAuthenticationRequired'); + t.is(result[1].name, 'isv_payerAuthenticationTransactionId'); + t.is(result[2].name, 'isv_payerAuthenticationAcsUrl'); + t.is(result[3].name, 'isv_payerAuthenticationPaReq'); + t.is(result[4].name, 'isv_stepUpUrl'); + t.is(result[5].name, 'isv_responseJwt'); + } else { + t.fail(`Unexpected error payer auth action${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + t.log(`Stack trace: ${error.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get payer auth actions ', async (t: any) => { + try { + let result = paymentActions.payerAuthActions(PaymentServiceConst.payerAuthActionsResponse); + if (Array.isArray(result) && result.length != 0 && result[result.length - 1]?.fields?.authenticationRequired) { + t.is(result[result.length - 1].action, 'addInterfaceInteraction'); + t.is(result[result.length - 1]?.fields?.authenticationRequired, true); + t.is(result[0].name, 'isv_payerAuthenticationRequired'); + t.is(result[0].value, true); + t.is(result[1].name, 'isv_payerAuthenticationTransactionId'); + t.is(result[2].name, 'isv_payerAuthenticationAcsUrl'); + t.is(result[3].name, 'isv_payerAuthenticationPaReq'); + t.is(result[4].name, 'isv_stepUpUrl'); + t.is(result[5].name, 'isv_responseJwt'); + } else { + t.fail(`Unexpected error payer auth action${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + t.log(`Stack trace: ${error.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get payer auth validate response', async (t) => { + try { + let result = await paymentActions.payerAuthValidateActions(PaymentServiceConst.authResponse, PaymentServiceConst.payerEnrollActionsResponse); + if (result.actions.length != 0) { + t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); + t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); + t.is(result.actions[2].name, 'isv_payerEnrollStatus'); + t.is(result.actions[3].name, 'isv_payerAuthenticationTransactionId'); + t.is(result.actions[4].name, 'isv_tokenCaptureContextSignature'); + t.is(result.actions[5].name, 'isv_payerAuthenticationRequired'); + t.is(result.actions[6].action, 'addTransaction'); + t.is(result.actions[7].action, 'addInterfaceInteraction'); + } else { + t.fail(`Unexpected error payer auth action${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + t.log(`Stack trace: ${error.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Create enroll response actions ', (t) => { + try { + const result = paymentActions.createEnrollResponseActions(PaymentUtilsConst.setTransactionIdPaymentResponse, PaymentHandlerConst.getPayerAuthValidateResponseUpdatePaymentObj as any); + if (result) { + t.pass(); + } else { + t.fail(`Unexpected error payer auth action${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + t.log(`Stack trace: ${error.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } }); \ No newline at end of file diff --git a/src/unit-tests/unit/utils/api/CommercetoolsApi.spec.ts b/src/unit-tests/unit/utils/api/CommercetoolsApi.spec.ts new file mode 100644 index 0000000..f77ac75 --- /dev/null +++ b/src/unit-tests/unit/utils/api/CommercetoolsApi.spec.ts @@ -0,0 +1,836 @@ +import test from 'ava'; +import dotenv from 'dotenv'; + +dotenv.config(); +import { Constants } from '../../../../constants/paymentConstants' +import paymentCustomJson from '../../../../resources/isv_payment_data_type.json'; +import paymentUpdateJson from '../../../../resources/payment_update_extension.json'; +import commercetoolsApi from '../../../../utils/api/CommercetoolsApi'; +import unit from '../../../JSON/unit.json'; +import CommercetoolsApiConst from '../../../const/CommercetoolsApiConst'; +import PaymentAuthorizationServiceConstCC from '../../../const/CreditCard/PaymentAuthorizationServiceConstCC'; +import PaymentServiceConst from '../../../const/HelpersConst'; + +test.serial('Retrieving cart using customerid ', async (t) => { + let result = await commercetoolsApi.queryCartById(CommercetoolsApiConst.customerId, Constants.CUSTOMER_ID); + if (result) { + if (result?.count > 0) { + t.is(result.count, 1); + t.is(result.results[0].type, 'Cart'); + if (result.results[0].cartState == 'Active') { + t.is(result.results[0].cartState, 'Active'); + } else if (result.results[0].cartState == 'Merged') { + t.is(result.results[0].cartState, 'Merged'); + } else if (result.results[0].cartState == 'Ordered') { + t.is(result.results[0].cartState, 'Ordered'); + } + } else { + t.is(result.count, 0); + t.is(result.total, 0); + } + } else { + t.pass(); + } +}); + +test.serial('Retrieving cart using customerid as null', async (t) => { + let result = await commercetoolsApi.queryCartById('', Constants.CUSTOMER_ID); + t.is(result, null); +}); + +test.serial('Retrieving cart with invalid customer id', async (t) => { + try { + let result = await commercetoolsApi.queryCartById('^T^Y*U^', Constants.CUSTOMER_ID); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieving cart using payment id ', async (t) => { + try { + let result = await commercetoolsApi.queryCartById(CommercetoolsApiConst.paymentId, Constants.PAYMENT_ID); + if (result) { + if (result?.count == 1) { + t.is(result.count, 1); + t.is(result.results[0].type, 'Cart'); + if (result.results[0].cartState == 'Active') { + t.is(result.results[0].cartState, 'Active'); + } else if (result.results[0].cartState == 'Merged') { + t.is(result.results[0].cartState, 'Merged'); + } else if (result.results[0].cartState == 'Ordered') { + t.is(result.results[0].cartState, 'Ordered'); + } + } else { + t.not(result.count, 1); + t.deepEqual(result.results, []); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieving cart using paymentid as null', async (t) => { + try { + let result = await commercetoolsApi.queryCartById('', Constants.PAYMENT_ID); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieving payment using paymentid ', async (t) => { + try { + let result = await commercetoolsApi.retrievePayment(CommercetoolsApiConst.paymentId); + if (result) { + let i = 0; + if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + } + t.is(i, 1); + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieving payment using paymentid as null', async (t) => { + try { + let result = await commercetoolsApi.retrievePayment(''); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Get all orders ', async (t) => { + try { + let result = await commercetoolsApi.getOrders(); + let i = 0; + if (result && 'limit' in result && 'offset' in result && 'count' in result && 'total' in result) { + i++; + } + t.is(i, 1); + } catch (error) { + t.pass(); + } +}); + +test.serial('get customer using customer id', async (t) => { + try { + let result = await commercetoolsApi.getCustomer(CommercetoolsApiConst.customerId); + if (result) { + let i = 0; + if ('email' in result && 'firstName' in result && 'lastName' in result) { + i++; + } + t.is(i, 1); + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('get customer using customer id as null', async (t) => { + try { + let result = await commercetoolsApi.getCustomer(''); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieving cart by anonymous id ', async (t) => { + try { + let result = await commercetoolsApi.queryCartById(CommercetoolsApiConst.anonymousId, Constants.ANONYMOUS_ID); + if (result) { + if (result?.count > 0) { + t.is(result.count, 1); + t.is(result.results[0].type, 'Cart'); + if (result.results[0].cartState == 'Active') { + t.is(result.results[0].cartState, 'Active'); + } else if (result.results[0].cartState == 'Merged') { + t.is(result.results[0].cartState, 'Merged'); + } else if (result.results[0].cartState == 'Ordered') { + t.is(result.results[0].cartState, 'Ordered'); + } + } else { + t.is(result.count, 0); + t.is(result.total, 0); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieving cart by anonymous id as null', async (t) => { + try { + let result = await commercetoolsApi.queryCartById('', Constants.ANONYMOUS_ID); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieving order by cart id ', async (t) => { + try { + let result = await commercetoolsApi.queryOrderById(CommercetoolsApiConst.cartId, Constants.CART_ID); + if (result) { + if (result?.count > 0) { + t.is(result.count, 1); + t.is(result.results[0].type, 'Order'); + if (result.results[0].orderState == 'Open') { + t.is(result.results[0].orderState, 'Open'); + } else if (result.results[0].orderState == 'Confirmed') { + t.is(result.results[0].orderState, 'Confirmed'); + } else if (result.results[0].orderState == 'Complete') { + t.is(result.results[0].orderState, 'Complete'); + } else if (result.results[0].orderState == 'Cancelled') { + t.is(result.results[0].orderState, 'Cancelled'); + } + } else { + t.is(result.count, 0); + t.is(result.total, 0); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieving order by cart id as null', async (t) => { + try { + let result = await commercetoolsApi.queryOrderById('', Constants.CART_ID); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieving order with invalid cart id', async (t) => { + try { + let result = await commercetoolsApi.queryOrderById('^T^Y*U^', Constants.CART_ID); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieving order by payment id ', async (t) => { + try { + let result = await commercetoolsApi.queryOrderById(CommercetoolsApiConst.paymentId, Constants.PAYMENT_ID); + if (result) { + if (result?.count > 0) { + t.is(result.count, 1); + t.is(result.results[0].type, 'Order'); + if (result.results[0].orderState == 'Open') { + t.is(result.results[0].orderState, 'Open'); + } else if (result.results[0].orderState == 'Confirmed') { + t.is(result.results[0].orderState, 'Confirmed'); + } else if (result.results[0].orderState == 'Complete') { + t.is(result.results[0].orderState, 'Complete'); + } else if (result.results[0].orderState == 'Cancelled') { + t.is(result.results[0].orderState, 'Cancelled'); + } + } else { + t.is(result.count, 0); + t.is(result.total, 0); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieving order by payment id as null', async (t) => { + try { + let result = await commercetoolsApi.queryOrderById('', Constants.PAYMENT_ID); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Get custom type ', async (t) => { + try { + let result = await commercetoolsApi.getCustomType(CommercetoolsApiConst.key); + if (result.statusCode == 200) { + t.is(result.statusCode, 200); + } else { + t.not(result.statusCode, 200); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Get custom type when type is null', async (t) => { + try { + let result = await commercetoolsApi.getCustomType(''); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Add customer address ', async (t) => { + try { + let result = await commercetoolsApi.addCustomerAddress(CommercetoolsApiConst.customerId, CommercetoolsApiConst.address); + let i = 0; + if (result && result?.addresses && 0 < result?.addresses?.length) { + i++; + t.is(i, 1); + } else { + t.is(i, 0); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Adding customer address when customer id is null', async (t) => { + try { + let result = await commercetoolsApi.addCustomerAddress('', CommercetoolsApiConst.address); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Add customer address with invalid customer id', async (t) => { + try { + let result = await commercetoolsApi.addCustomerAddress('123', CommercetoolsApiConst.address); + let i = 0; + if (result?.addresses && 0 < result?.addresses.length) { + i++; + } + t.is(i, 0); + } catch (error) { + t.pass(); + } +}); + +test.serial('Add customer address when address field is null', async (t) => { + try { + let result = await commercetoolsApi.addCustomerAddress(CommercetoolsApiConst.customerId, CommercetoolsApiConst.emptyAddressField); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Add transaction for run sync ', async (t) => { + try { + let paymentObjRunSync = await commercetoolsApi.retrievePayment(unit.paymentId); + if (paymentObjRunSync) { + CommercetoolsApiConst.addTransactionForCharge.version = paymentObjRunSync?.version; + let result = await commercetoolsApi.addTransaction(CommercetoolsApiConst.addTransactionForCharge, unit.paymentId); + let i = 0; + if (result && 'amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + t.is(i, 1); + } else { + t.is(i, 0); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Add transaction for run sync with invalid payment id', async (t) => { + try { + let result = await commercetoolsApi.addTransaction(CommercetoolsApiConst.addTransactionForCharge, '^T^Y*U^'); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('Add transaction for run sync when payment id is null', async (t) => { + try { + let paymentObjRunSyncIdNull = await commercetoolsApi.retrievePayment(unit.paymentId); + if (paymentObjRunSyncIdNull) { + CommercetoolsApiConst.addTransactionForCharge.version = paymentObjRunSyncIdNull?.version; + let result = await commercetoolsApi.addTransaction(CommercetoolsApiConst.addTransactionForCharge, ''); + t.is(result, null); + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('update cart by payment id ', async (t) => { + try { + let cartData = await commercetoolsApi.getCartById(unit.cartId); + let result = await commercetoolsApi.updateCartByPaymentId(unit.cartId, unit.paymentId, cartData?.version, PaymentServiceConst.visaCardDetailsActionVisaCheckoutData); + if (result) { + t.is(result.type, 'Cart'); + if (result.cartState == 'Active') { + t.is(result.cartState, 'Active'); + } else if (result.cartState == 'Merged') { + t.is(result.cartState, 'Merged'); + } else if (result.cartState == 'Ordered') { + t.is(result.cartState, 'Ordered'); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('update cart by payment id when shipping email is available ', async (t) => { + try { + let cartData = await commercetoolsApi.getCartById(unit.cartId); + PaymentServiceConst.visaCardDetailsActionVisaCheckoutData.shipToFieldGroup.email = 'test@gmail.com' + let result = await commercetoolsApi.updateCartByPaymentId(unit.cartId, unit.paymentId, cartData?.version, PaymentServiceConst.visaCardDetailsActionVisaCheckoutData); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('update cart by payment id with invalid cart id', async (t) => { + try { + let cartData = await commercetoolsApi.getCartById(unit.cartId); + let result = await commercetoolsApi.updateCartByPaymentId('^T^Y*U^', unit.paymentId, cartData?.version, PaymentServiceConst.visaCardDetailsActionVisaCheckoutData); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + + +test.serial('update cart by payment id when cart id is null', async (t) => { + try { + let cartData = await commercetoolsApi.getCartById(unit.cartId); + let result = await commercetoolsApi.updateCartByPaymentId('', unit.paymentId, cartData?.version, PaymentServiceConst.visaCardDetailsActionVisaCheckoutData); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('update cart by payment id when payment id is null', async (t) => { + try { + let cartData = await commercetoolsApi.getCartById(unit.cartId); + let result = await commercetoolsApi.updateCartByPaymentId(unit.cartId, '', cartData?.version, PaymentServiceConst.visaCardDetailsActionVisaCheckoutData); + if (result) { + t.is(result.type, 'Cart'); + if (result.cartState == 'Active') { + t.is(result.cartState, 'Active'); + } else if (result.cartState == 'Merged') { + t.is(result.cartState, 'Merged'); + } else if (result.cartState == 'Ordered') { + t.is(result.cartState, 'Ordered'); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('set Customer Tokens', async (t) => { + try { + let result = await commercetoolsApi.setCustomerTokens(PaymentServiceConst.processTokensCustomerCardTokensObject.customerTokenId, PaymentServiceConst.processTokensCustomerCardTokensObject.paymentInstrumentId, '7010000000121591111', PaymentAuthorizationServiceConstCC.payment as any, ''); + if (result) { + if (result?.body) { + result = result.body; + } + let i = 0; + if ('email' in result && 'firstName' in result && 'lastName' in result && 'custom' in result) { + i++; + } + if (1 === i) + t.is(i, 1) + else + t.is(i, 0); + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('set Customer Tokens when payment instrument id is null', async (t) => { + try { + let result = await commercetoolsApi.setCustomerTokens(PaymentServiceConst.processTokensCustomerCardTokensObject.customerTokenId, '', '7010000000121591111', PaymentAuthorizationServiceConstCC.payment as any, ''); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('set custom type', async (t) => { + try { + let result = await commercetoolsApi.setCustomType(unit.customerId, CommercetoolsApiConst.setCustomTypeFieldsData, [], PaymentServiceConst.processTokensCustomerCardTokensObject.customerTokenId); + if (result) { + let i = 0; + if ('email' in result && 'firstName' in result && 'lastName' in result && 'custom' in result) { + i++; + } + t.is(i, 1); + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('set custom type when customer id is null', async (t) => { + try { + let result = await commercetoolsApi.setCustomType('', CommercetoolsApiConst.setCustomTypeFieldsData, [], PaymentServiceConst.processTokensCustomerCardTokensObject.customerTokenId); + t.is(result, null); + } catch (error) { + t.pass(); + } +}); + +test.serial('sync visa card details ', async (t) => { + try { + let paymentObjSyncVisaCard = await commercetoolsApi.retrievePayment(unit.paymentId); + if (paymentObjSyncVisaCard) { + let visaUpdateObject: any = { + actions: CommercetoolsApiConst.syncVisaCardEtailsActions, + id: paymentObjSyncVisaCard?.id, + version: paymentObjSyncVisaCard?.version, + }; + let result = await commercetoolsApi.syncVisaCardDetails(visaUpdateObject); + let i = 0; + if (result && 'amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + t.is(i, 1); + } else { + t.is(i, 0); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('sync visa card details with incorrect data', async (t) => { + try { + let paymentObjSyncInvalidCard = await commercetoolsApi.retrievePayment(unit.paymentId); + if (paymentObjSyncInvalidCard) { + let visaUpdateObject: any = { + actions: CommercetoolsApiConst.syncVisaCardEtailsActions, + id: '', + version: '', + }; + let result = await commercetoolsApi.syncVisaCardDetails(visaUpdateObject); + t.is(result, null); + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('sync add transaction ', async (t) => { + try { + let paymentObjSync = await commercetoolsApi.retrievePayment(unit.paymentId); + if (paymentObjSync) { + PaymentServiceConst.runSyncAddTransactionSyncUpdateObject.version = paymentObjSync?.version; + let result = await commercetoolsApi.syncAddTransaction(PaymentServiceConst.runSyncAddTransactionSyncUpdateObject); + let i = 0; + if (result && 'amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + t.is(i, 1); + } else { + t.is(i, 0); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('sync add transaction with incorrect data', async (t) => { + try { + let paymentObjSyncIncorrect = await commercetoolsApi.retrievePayment(unit.paymentId); + if (paymentObjSyncIncorrect) { + PaymentServiceConst.runSyncAddTransactionSyncUpdateObject.version = paymentObjSyncIncorrect?.version; + let result = await commercetoolsApi.syncAddTransaction(PaymentServiceConst.runSyncAddTransactionSyncUpdateEmptyObject); + t.is(result, null); + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('add custom types ', async (t) => { + try { + let result = await commercetoolsApi.addCustomTypes(paymentCustomJson as any); + if (result) { + if (201 == result.statusCode) { + t.is(result.statusCode, 201); + } else { + t.not(result.statusCode, 201); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('add custom types with empty object', async (t) => { + try { + let result = await commercetoolsApi.addCustomTypes('' as any); + t.falsy(result); + } catch (error) { + t.pass(); + } +}); + +test.serial('add extensions', async (t) => { + try { + let result = await commercetoolsApi.addExtensions(paymentUpdateJson as any); + if (result) { + if (201 !== parseInt(result.statusCode)) { + t.is(result.statusCode, 201); + } else { + t.not(result.statusCode, 201); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('add extensions with empty object', async (t) => { + try { + let result = await commercetoolsApi.addExtensions('' as any); + t.falsy(result); + } catch (error) { + t.pass(); + } +}); + +test.serial('update available amount ', async (t) => { + try { + let updatePaymentObj = await commercetoolsApi.retrievePayment(unit.paymentId); + if (updatePaymentObj) { + let result = await commercetoolsApi.updateAvailableAmount(updatePaymentObj?.id, updatePaymentObj?.version, '123', 4); + let i = 0; + if (result && 'amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + t.is(i, 1); + } else { + t.is(i, 0); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('update available amount when payment id is null', async (t) => { + try { + let updatePaymentObjIdNull = await commercetoolsApi.retrievePayment(unit.paymentId); + if (updatePaymentObjIdNull) { + let result = await commercetoolsApi.updateAvailableAmount('', updatePaymentObjIdNull?.version, '123', 4); + t.falsy(result); + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('get cart by id', async (t) => { + try { + let result = await commercetoolsApi.getCartById(unit.cartId); + if (result) { + t.is(result.type, 'Cart'); + if (result.cartState == 'Active') { + t.is(result.cartState, 'Active'); + } else if (result.cartState == 'Merged') { + t.is(result.cartState, 'Merged'); + } else if (result.cartState == 'Ordered') { + t.is(result.cartState, 'Ordered'); + } + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('get cart by id when cart id is null', async (t) => { + try { + let result = await commercetoolsApi.getCartById(''); + t.falsy(result); + } catch (error) { + t.pass(); + } +}); + +test.serial('Create commercetools custom object', async (t) => { + try { + let result = await commercetoolsApi.createCTCustomObject(CommercetoolsApiConst.createCTCustomObjectData); + if (result.statusCode == 200) { + t.is(result.statusCode, 200); + } else { + t.not(result.statusCode, 200); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieve custom objects', async (t) => { + try { + let result = await commercetoolsApi.retrieveCustomObjectByContainer(CommercetoolsApiConst.customObjectContainer); + let i = 0; + if (result && 'limit' in result && 'offset' in result && 'count' in result && 'total' in result) { + i++; + t.is(i, 1); + } else { + t.is(i, 0); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieve custom objects when container is empty', async (t) => { + try { + let result = await commercetoolsApi.retrieveCustomObjectByContainer(''); + let i = 0; + if (result && 'limit' in result && 'offset' in result && 'count' in result && 'total' in result) { + i++; + t.is(i, 1); + } else { + t.is(i, 0); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieve customer by custom field', async (t) => { + try { + let result = await commercetoolsApi.retrieveCustomerByCustomField(CommercetoolsApiConst.customFieldName, CommercetoolsApiConst.customFieldValue); + let i = 0; + if (result && result?.results[0] && 'email' in result.results[0] && 'firstName' in result.results[0] && 'lastName' in result.results[0] && 'custom' in result.results[0]) { + i++; + t.is(i, 1); + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieve customer by custom field when field name is empty', async (t) => { + try { + let result = await commercetoolsApi.retrieveCustomerByCustomField('', CommercetoolsApiConst.customFieldValue); + t.falsy(result); + } catch (error) { + t.pass(); + } +}); + +test.serial('Retrieve customer by custom field when field value is empty', async (t) => { + try { + let result = await commercetoolsApi.retrieveCustomerByCustomField(CommercetoolsApiConst.customFieldName, ''); + t.falsy(result); + } catch (error) { + t.pass(); + } +}); + +test.serial('Change transaction interaction id', async (t) => { + try { + const payment = await commercetoolsApi.retrievePayment(unit.paymentId); + CommercetoolsApiConst.changeTransactionInteractionIdTransactionObject.version = payment?.version; + const result = await commercetoolsApi.changeTransactionInteractionId(CommercetoolsApiConst.changeTransactionInteractionIdTransactionObject); + if (result) { + let i = 0; + if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + } + t.is(i, 1); + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}) + +test.serial('Get discount code', async (t) => { + try { + const result = await commercetoolsApi.getDiscountCodes(unit.discountId); + if (result) { + let i = 0; + if ('code' in result && 'cartDiscounts' in result && 'isActive' in result) { + i++; + } + t.is(i, 1); + } else { + t.pass(); + } + } catch (error) { + t.pass(); + } +}) + +test.serial('Get discount code with invalid discount id', async (t) => { + try { + const result = await commercetoolsApi.getDiscountCodes("*&^^$%%^&^"); + t.is(result, null); + } catch (error) { + t.pass(); + } +}) + +test.serial('Get discount code with empty discount id', async (t) => { + try { + const result = await commercetoolsApi.getDiscountCodes(""); + t.is(result, null); + } catch (error) { + t.pass(); + } +}) diff --git a/src/unit-tests/unit/utils/api/IsvApi.spec.ts b/src/unit-tests/unit/utils/api/IsvApi.spec.ts new file mode 100644 index 0000000..9f0829f --- /dev/null +++ b/src/unit-tests/unit/utils/api/IsvApi.spec.ts @@ -0,0 +1,36 @@ +import test from 'ava'; +import restApi from 'cybersource-rest-client'; +import dotenv from 'dotenv'; +dotenv.config(); + +import cybersourceApi from '../../../../utils/api/isvApi'; +import CybersourceApiConst from '../../../const/CybersourceApiConst'; + +test.serial('Test get subscription details api function', async (t) => { + let apiClient = new restApi.ApiClient(); + let result: any = { + status: 0, + webhookId: '', + webhookUrl: '', + }; + + let callbackPromise = await new Promise((resolve, reject) => { + cybersourceApi.getSubscriptionDetails(apiClient, CybersourceApiConst.configObject, CybersourceApiConst.requestObject, (_error: any, data: any, response: any) => { + if (data) { + result.status = response.status; + result.webhookId = data.webhookId; + result.webhookUrl = data.webhookUrl; + resolve(result); + } else { + reject(result); + } + }); + }); + + result = callbackPromise; + if (200 === result.status) { + t.is(result.status, 200); + } else { + t.not(result.status, 200); + } +}); diff --git a/src/unit-tests/unit/utils/config/CustomExtension.spec.ts b/src/unit-tests/unit/utils/config/CustomExtension.spec.ts new file mode 100644 index 0000000..667adc6 --- /dev/null +++ b/src/unit-tests/unit/utils/config/CustomExtension.spec.ts @@ -0,0 +1,38 @@ +import test from 'ava'; +import dotenv from 'dotenv'; + +dotenv.config(); +import customerUpdateJson from '../../../../resources/customer_update_extension.json'; +import paymentCreateJson from '../../../../resources/payment_create_extension.json'; +import paymentUpdateJson from '../../../../resources/payment_update_extension.json'; +import customExtensions from '../../../../utils/config/CustomExtensions'; + +test.serial('sync extensions for payment update', async (t) => { + let result = await customExtensions.syncExtensions(paymentUpdateJson); + t.is(typeof result, 'boolean'); +}); + +test.serial('sync extensions for payment create', async (t) => { + let result = await customExtensions.syncExtensions(paymentCreateJson); + t.is(typeof result, 'boolean'); +}); + +test.serial('sync extensions for customer update', async (t) => { + let result = await customExtensions.syncExtensions(customerUpdateJson); + t.is(typeof result, 'boolean'); +}); + +test.serial('sync extensions with object is null', async (t) => { + let result = await customExtensions.syncExtensions(null); + t.is(typeof result, 'boolean'); +}); + +test.serial('sync extensions with object is empty', async (t) => { + let result = await customExtensions.syncExtensions(''); + t.is(typeof result, 'boolean'); +}); + +test.serial('sync extensions with incorrect object', async (t) => { + let result = await customExtensions.syncExtensions(123); + t.is(typeof result, 'boolean'); +}); diff --git a/src/unit-tests/unit/utils/config/CustomTypes.spec.ts b/src/unit-tests/unit/utils/config/CustomTypes.spec.ts new file mode 100644 index 0000000..f7f3fc3 --- /dev/null +++ b/src/unit-tests/unit/utils/config/CustomTypes.spec.ts @@ -0,0 +1,26 @@ +import test from 'ava'; +import dotenv from 'dotenv'; + +dotenv.config(); +import paymentCustomJson from '../../../../resources/isv_payment_data_type.json'; +import customTypes from '../../../../utils/config/CustomTypes'; + +test.serial('sync custom type', async (t) => { + let result = await customTypes.syncCustomType(paymentCustomJson); + t.is(typeof result, 'boolean'); +}); + +test.serial('sync custom type when object is null', async (t) => { + let result = await customTypes.syncCustomType(null); + t.is(typeof result, 'boolean'); +}); + +test.serial('sync custom type when object is empty', async (t) => { + let result = await customTypes.syncCustomType(''); + t.is(typeof result, 'boolean'); +}); + +test.serial('sync custom type when object is incorrect', async (t) => { + let result = await customTypes.syncCustomType(123); + t.is(typeof result, 'boolean'); +}); diff --git a/src/unit-tests/unit/utils/config/MultiMid.spec.ts b/src/unit-tests/unit/utils/config/MultiMid.spec.ts new file mode 100644 index 0000000..121c281 --- /dev/null +++ b/src/unit-tests/unit/utils/config/MultiMid.spec.ts @@ -0,0 +1,49 @@ +import test from 'ava'; +import dotenv from 'dotenv'; + +dotenv.config(); +import multiMid from '../../../../utils/config/MultiMid'; +import CaptureContextServiceConst from '../../../const/CaptureContextServiceConst'; + +test.serial('get mid credentials ', async (t) => { + let result = await multiMid.getMidCredentials(CaptureContextServiceConst.merchantId); + let i = 0; + if ('merchantId' in result && 'merchantKeyId' in result && 'merchantSecretKey' in result) { + i++; + } + if (i === 1) { + t.is(i, 1); + } else { + t.is(i, 0); + } +}); + +test.serial('get mid credentials without mid', async (t) => { + let result = await multiMid.getMidCredentials(''); + let i = 0; + if ('merchantId' in result && 'merchantKeyId' in result && 'merchantSecretKey' in result) { + i++; + } + if (i === 1) { + t.is(i, 1); + } else { + t.is(i, 0); + } +}); + +test.serial('get all mid details ', async t => { + let result = await multiMid.getAllMidDetails(); + let i = 0; + if (result.length) { + if ('merchantId' in result[0] && 'merchantKeyId' in result[0] && 'merchantSecretKey' in result[0]) { + i++; + } + if (i === 1) { + t.is(i, 1); + } else { + t.is(i, 0); + } + } else { + t.pass(); + } +}); diff --git a/src/unit-tests/unit/utils/helpers/PayerAuthHelper.spec.ts b/src/unit-tests/unit/utils/helpers/PayerAuthHelper.spec.ts index a8894a8..c39e61f 100644 --- a/src/unit-tests/unit/utils/helpers/PayerAuthHelper.spec.ts +++ b/src/unit-tests/unit/utils/helpers/PayerAuthHelper.spec.ts @@ -1,185 +1,185 @@ -import test from 'ava'; -import dotenv from 'dotenv'; - -dotenv.config(); -import payerAuthHelper from '../../../../utils/helpers/PayerAuthHelper'; -import PaymentAuthorizationReversalConstGP from '../../../const/GooglePay/PaymentAuthorizationReversalConstGP'; -import PaymentAuthorizationServiceConstGP from '../../../const/GooglePay/PaymentAuthorizationServiceConstGP'; -import PaymentServiceConst from '../../../const/HelpersConst'; -import PayerAuthHelperConst from '../../../const/PayerAuthHelperConst'; -import PaymentHandlerConst from '../../../const/PaymentHandlerConst'; - -test.serial('Test tokenized card for payer authentication', async (t) => { - try { - if (PaymentServiceConst.payerEnrollActionsUpdatePaymentObj?.custom) { - PaymentServiceConst.payerEnrollActionsUpdatePaymentObj.custom.fields['isv_tokenAlias'] = '4111 card'; - } - const result = await payerAuthHelper.getEnrollResponseForPayerAuthentication( - PaymentServiceConst.payerEnrollActionsUpdatePaymentObj, - PayerAuthHelperConst.tokenizeCardForPayerAuthenticationTokenCreateResponse, - PaymentServiceConst.payerEnrollActionsUpdatePaymentObj?.custom?.fields || {}, - 'de8c98ef-dd88-4c3e-bb79-209e50d27f1e', - PaymentAuthorizationReversalConstGP.cart as any, - PaymentAuthorizationServiceConstGP.cardTokens, - '' - ); - if (0 < result.actions.length ) { - t.is(result.actions[0].action, 'setCustomField'); - t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); - t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); - t.is(result.actions[2].name, 'isv_payerEnrollStatus'); - } else { - t.fail(`Unexpected result : ${result}`); - } - } catch (exception) { - if (exception instanceof Error) { - t.fail(`Caught an error during execution: ${exception.message}`); - t.log(`Stack trace: ${exception.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(exception)}`); - } - } -}); - -test.serial('Get Payer auth validate response', async (t: any) => { - try { - let result = await payerAuthHelper.getPayerAuthValidateResponse(PaymentHandlerConst.getPayerAuthValidateResponseUpdatePaymentObj as any); - if ( 0 < result?.actions?.length) { - t.is(result.actions[0].action, 'setCustomField'); - t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); - t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); - t.is(result.actions[2].name, 'isv_payerEnrollStatus'); - } else { - t.fail(`Unexpected result : ${result}`); - } - } catch (exception) { - if (exception instanceof Error) { - t.fail(`Caught an error during execution: ${exception.message}`); - t.log(`Stack trace: ${exception.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(exception)}`); - } - } -}); - -test.serial('Get payer auth set up response ', async (t: any) => { - try { - let result: any = await payerAuthHelper.getPayerAuthSetUpResponse(PaymentHandlerConst.authorizationHandler3DSUpdatePaymentObject as any); - if (result) { - if (0 === result?.actions[0]?.length) { - t.deepEqual(result.actions, []); - t.deepEqual(result.errors, []); - } else if ('setCustomField' === result?.actions[0]?.action) { - t.is(result.actions[0].action, 'setCustomField'); - t.is(result.actions[0].name, 'isv_requestJwt'); - t.is(result.actions[1].action, 'setCustomField'); - t.is(result.actions[1].name, 'isv_cardinalReferenceId'); - t.is(result.actions[2].action, 'setCustomField'); - t.is(result.actions[2].name, 'isv_deviceDataCollectionUrl'); - } else { - t.fail(`Unexpected result : ${result}`); - } - } else { - t.fail(`Unexpected result : ${result}`); - } - } catch (exception) { - if (exception instanceof Error) { - t.fail(`Caught an error during execution: ${exception.message}`); - t.log(`Stack trace: ${exception.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(exception)}`); - } - } -}); - -test.serial('Get payer auth enroll response', async (t: any) => { - try { - let result = await payerAuthHelper.getPayerAuthEnrollResponse(PaymentHandlerConst.getPayerAuthEnrollResponseUpdatePaymentObj as any); - if (result.actions.length <= 0) { - t.deepEqual(result.actions, []); - t.is(result.errors[0].code, 'InvalidInput'); - t.is(result.errors[0].message, 'Cannot process the payment due to invalid input'); - } else { - t.is(result.actions[0].action, 'setCustomField'); - t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); - t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); - t.is(result.actions[2].name, 'isv_payerEnrollStatus'); - } - } catch (exception) { - if (exception instanceof Error) { - t.fail(`Caught an error during execution: ${exception.message}`); - t.log(`Stack trace: ${exception.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(exception)}`); - } - } -}); - -test.serial('Process payer authentication for payer auth set up', async (t) => { - try { - const result = await payerAuthHelper.processPayerAuthentication(PaymentHandlerConst.authorizationHandler3DSUpdatePaymentObject as any); - if (result) { - if ('setCustomField' === result?.actions[0]?.action) { - t.is(result.actions[0].action, 'setCustomField'); - t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); - t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); - t.is(result.actions[2].name, 'isv_payerEnrollStatus'); - } else if (result.actions.length <= 0) { - t.deepEqual(result.actions, []); - t.is(result.errors[0].code, 'InvalidInput'); - t.is(result.errors[0].message, 'Cannot process the payment due to invalid input'); - } else { - t.fail(`Unexpected result : ${result}`); - } - } else { - t.fail(`Unexpected result : ${result}`); - } - } catch (exception) { - if (exception instanceof Error) { - t.fail(`Caught an error during execution: ${exception.message}`); - t.log(`Stack trace: ${exception.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(exception)}`); - } - } -}); - -test.serial('Process payer authentication for payer auth enroll', async (t) => { - try { - const result = await payerAuthHelper.processPayerAuthentication(PaymentHandlerConst.getPayerAuthEnrollResponseUpdatePaymentObj as any); - if (result.actions.length <= 0) { - t.deepEqual(result.actions, []); - t.is(result.errors[0].code, 'InvalidInput'); - t.is(result.errors[0].message, 'Cannot process the payment due to invalid input'); - } else { - t.is(result.actions[0].action, 'setCustomField'); - t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); - t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); - t.is(result.actions[2].name, 'isv_payerEnrollStatus'); - } - } catch (error) { - t.pass(); - } -}); - -test.serial('Process payer authentication for payer auth validate', async (t) => { - try { - const result = await payerAuthHelper.processPayerAuthentication(PaymentHandlerConst.getPayerAuthValidateResponseUpdatePaymentObj as any); - if (result.actions.length > 0) { - t.is(result.actions[0].action, 'setCustomField'); - t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); - t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); - t.is(result.actions[2].name, 'isv_payerEnrollStatus'); - } else { - t.deepEqual(result.actions, []); - t.deepEqual(result.errors, []); - } - } catch (exception) { - if (exception instanceof Error) { - t.fail(`Caught an error during execution: ${exception.message}`); - t.log(`Stack trace: ${exception.stack}`); - } else { - t.fail(`Caught an unknown error: ${String(exception)}`); - } - } +import test from 'ava'; +import dotenv from 'dotenv'; + +dotenv.config(); +import payerAuthHelper from '../../../../utils/helpers/PayerAuthHelper'; +import PaymentAuthorizationReversalConstGP from '../../../const/GooglePay/PaymentAuthorizationReversalConstGP'; +import PaymentAuthorizationServiceConstGP from '../../../const/GooglePay/PaymentAuthorizationServiceConstGP'; +import PaymentServiceConst from '../../../const/HelpersConst'; +import PayerAuthHelperConst from '../../../const/PayerAuthHelperConst'; +import PaymentHandlerConst from '../../../const/PaymentHandlerConst'; + +test.serial('Test tokenized card for payer authentication', async (t) => { + try { + if (PaymentServiceConst.payerEnrollActionsUpdatePaymentObj?.custom) { + PaymentServiceConst.payerEnrollActionsUpdatePaymentObj.custom.fields['isv_tokenAlias'] = '4111 card'; + } + const result = await payerAuthHelper.getEnrollResponseForPayerAuthentication( + PaymentServiceConst.payerEnrollActionsUpdatePaymentObj, + PayerAuthHelperConst.tokenizeCardForPayerAuthenticationTokenCreateResponse, + PaymentServiceConst.payerEnrollActionsUpdatePaymentObj?.custom?.fields || {}, + 'de8c98ef-dd88-4c3e-bb79-209e50d27f1e', + PaymentAuthorizationReversalConstGP.cart as any, + PaymentAuthorizationServiceConstGP.cardTokens, + '' + ); + if (0 < result.actions.length ) { + t.is(result.actions[0].action, 'setCustomField'); + t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); + t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); + t.is(result.actions[2].name, 'isv_payerEnrollStatus'); + } else { + t.fail(`Unexpected result : ${result}`); + } + } catch (exception) { + if (exception instanceof Error) { + t.fail(`Caught an error during execution: ${exception.message}`); + t.log(`Stack trace: ${exception.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(exception)}`); + } + } +}); + +test.serial('Get Payer auth validate response', async (t: any) => { + try { + let result = await payerAuthHelper.getPayerAuthValidateResponse(PaymentHandlerConst.getPayerAuthValidateResponseUpdatePaymentObj as any); + if ( 0 < result?.actions?.length) { + t.is(result.actions[0].action, 'setCustomField'); + t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); + t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); + t.is(result.actions[2].name, 'isv_payerEnrollStatus'); + } else { + t.fail(`Unexpected result : ${result}`); + } + } catch (exception) { + if (exception instanceof Error) { + t.fail(`Caught an error during execution: ${exception.message}`); + t.log(`Stack trace: ${exception.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(exception)}`); + } + } +}); + +test.serial('Get payer auth set up response ', async (t: any) => { + try { + let result: any = await payerAuthHelper.getPayerAuthSetUpResponse(PaymentHandlerConst.authorizationHandler3DSUpdatePaymentObject as any); + if (result) { + if (0 === result?.actions[0]?.length) { + t.deepEqual(result.actions, []); + t.deepEqual(result.errors, []); + } else if ('setCustomField' === result?.actions[0]?.action) { + t.is(result.actions[0].action, 'setCustomField'); + t.is(result.actions[0].name, 'isv_requestJwt'); + t.is(result.actions[1].action, 'setCustomField'); + t.is(result.actions[1].name, 'isv_cardinalReferenceId'); + t.is(result.actions[2].action, 'setCustomField'); + t.is(result.actions[2].name, 'isv_deviceDataCollectionUrl'); + } else { + t.fail(`Unexpected result : ${result}`); + } + } else { + t.fail(`Unexpected result : ${result}`); + } + } catch (exception) { + if (exception instanceof Error) { + t.fail(`Caught an error during execution: ${exception.message}`); + t.log(`Stack trace: ${exception.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(exception)}`); + } + } +}); + +test.serial('Get payer auth enroll response', async (t: any) => { + try { + let result = await payerAuthHelper.getPayerAuthEnrollResponse(PaymentHandlerConst.getPayerAuthEnrollResponseUpdatePaymentObj as any); + if (result.actions.length <= 0) { + t.deepEqual(result.actions, []); + t.is(result.errors[0].code, 'InvalidInput'); + t.is(result.errors[0].message, 'Cannot process the payment due to invalid input'); + } else { + t.is(result.actions[0].action, 'setCustomField'); + t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); + t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); + t.is(result.actions[2].name, 'isv_payerEnrollStatus'); + } + } catch (exception) { + if (exception instanceof Error) { + t.fail(`Caught an error during execution: ${exception.message}`); + t.log(`Stack trace: ${exception.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(exception)}`); + } + } +}); + +test.serial('Process payer authentication for payer auth set up', async (t) => { + try { + const result = await payerAuthHelper.processPayerAuthentication(PaymentHandlerConst.authorizationHandler3DSUpdatePaymentObject as any); + if (result) { + if ('setCustomField' === result?.actions[0]?.action) { + t.is(result.actions[0].action, 'setCustomField'); + t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); + t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); + t.is(result.actions[2].name, 'isv_payerEnrollStatus'); + } else if (result.actions.length <= 0) { + t.deepEqual(result.actions, []); + t.is(result.errors[0].code, 'InvalidInput'); + t.is(result.errors[0].message, 'Cannot process the payment due to invalid input'); + } else { + t.fail(`Unexpected result : ${result}`); + } + } else { + t.fail(`Unexpected result : ${result}`); + } + } catch (exception) { + if (exception instanceof Error) { + t.fail(`Caught an error during execution: ${exception.message}`); + t.log(`Stack trace: ${exception.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(exception)}`); + } + } +}); + +test.serial('Process payer authentication for payer auth enroll', async (t) => { + try { + const result = await payerAuthHelper.processPayerAuthentication(PaymentHandlerConst.getPayerAuthEnrollResponseUpdatePaymentObj as any); + if (result.actions.length <= 0) { + t.deepEqual(result.actions, []); + t.is(result.errors[0].code, 'InvalidInput'); + t.is(result.errors[0].message, 'Cannot process the payment due to invalid input'); + } else { + t.is(result.actions[0].action, 'setCustomField'); + t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); + t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); + t.is(result.actions[2].name, 'isv_payerEnrollStatus'); + } + } catch (error) { + t.pass(); + } +}); + +test.serial('Process payer authentication for payer auth validate', async (t) => { + try { + const result = await payerAuthHelper.processPayerAuthentication(PaymentHandlerConst.getPayerAuthValidateResponseUpdatePaymentObj as any); + if (result.actions.length > 0) { + t.is(result.actions[0].action, 'setCustomField'); + t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); + t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); + t.is(result.actions[2].name, 'isv_payerEnrollStatus'); + } else { + t.deepEqual(result.actions, []); + t.deepEqual(result.errors, []); + } + } catch (exception) { + if (exception instanceof Error) { + t.fail(`Caught an error during execution: ${exception.message}`); + t.log(`Stack trace: ${exception.stack}`); + } else { + t.fail(`Caught an unknown error: ${String(exception)}`); + } + } }); \ No newline at end of file diff --git a/src/unit-tests/unit/utils/helpers/SyncHelper.spec.ts b/src/unit-tests/unit/utils/helpers/SyncHelper.spec.ts index ed3a38d..ca5b7d7 100644 --- a/src/unit-tests/unit/utils/helpers/SyncHelper.spec.ts +++ b/src/unit-tests/unit/utils/helpers/SyncHelper.spec.ts @@ -1,480 +1,480 @@ -import test from 'ava'; -import dotenv from 'dotenv'; - -dotenv.config(); -import { Constants } from '../../../../constants/paymentConstants'; -import CommercetoolsApi from '../../../../utils/api/CommercetoolsApi'; -import syncHelper from '../../../../utils/helpers/SyncHelper'; -import unit from '../../../JSON/unit.json'; -import CommercetoolsApiConst from '../../../const/CommercetoolsApiConst'; -import PaymentServiceConst from '../../../const/HelpersConst'; -import SyncHelperConst from '../../../const/SyncHelperConst'; - -test.serial('Retrieve sync response', async (t: any) => { - try { - let result = await syncHelper.retrieveSyncResponse(PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, PaymentServiceConst.retrieveSyncResponseTransactionElement); - let i = 0; - if (result && 'amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Process application response when auth is present', async (t:any) => { - try { - const result = await syncHelper.processApplicationResponse(PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse, PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, SyncHelperConst.syncUpdateObject, PaymentServiceConst.retrieveSyncResponseTransactionElement); - if (result) { - let i = 0; - if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Process application response when capture is present', async (t:any) => { - try { - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authPresent = false; - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.capturePresent = true; - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.captureReasonCodePresent = true; - const result = await syncHelper.processApplicationResponse(PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse, PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, SyncHelperConst.syncUpdateObject, PaymentServiceConst.retrieveSyncResponseTransactionElement); - if (result) { - let i = 0; - if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Process application response when auth reversal is present', async (t:any) => { - try { - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authPresent = false; - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.capturePresent = false; - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authReversalPresent = true; - const result = await syncHelper.processApplicationResponse(PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse, PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, SyncHelperConst.syncUpdateObject, PaymentServiceConst.retrieveSyncResponseTransactionElement); - if (result) { - let i = 0; - if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Process application response when refund is present', async (t:any) => { - try { - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authPresent = false; - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.capturePresent = false; - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authReversalPresent = false; - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.refundPresent = true; - const result = await syncHelper.processApplicationResponse(PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse, PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, SyncHelperConst.syncUpdateObject, PaymentServiceConst.retrieveSyncResponseTransactionElement); - if (result) { - let i = 0; - if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Run sync add transaction ', async (t:any) => { - try { - const result = await syncHelper.runSyncAddTransaction(CommercetoolsApiConst.syncAddTransactionObject, '100', true, true); - if (result) { - let i = 0; - if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Run sync add transaction when there is error', async (t:any) => { - try { - const result = await syncHelper.runSyncAddTransaction(CommercetoolsApiConst.syncAddTransactionObject, Constants.PAYMENT_GATEWAY_ERROR_REASON_CODE, true, true); - if (result) { - let i = 0; - if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Run sync add transaction when there is failure', async (t:any) => { - try { - const result = await syncHelper.runSyncAddTransaction(CommercetoolsApiConst.syncAddTransactionObject, Constants.PAYMENT_GATEWAY_FAILURE_REASON_CODE, true, true); - if (result) { - let i = 0; - if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Run sync add transaction when there is failure and auth reason code is not present', async (t:any) => { - try { - const result = await syncHelper.runSyncAddTransaction(CommercetoolsApiConst.syncAddTransactionObject, Constants.PAYMENT_GATEWAY_FAILURE_REASON_CODE, true, false); - if (result) { - let i = 0; - if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('add transaction for run sync when auth is not present', async (t: any) => { - try { - let result = await syncHelper.runSyncAddTransaction(PaymentServiceConst.runSyncAddTransactionSyncUpdateObject, '100', false, false); - if (result) { - t.is(result, true); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('add transaction for run sync when reason code is empty', async (t: any) => { - try { - let result = await syncHelper.runSyncAddTransaction(PaymentServiceConst.runSyncAddTransactionSyncUpdateObject, '', false, false); - if (null === result) { - t.is(result, null); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Run sync add transaction with refund', async (t:any) => { - try { - CommercetoolsApiConst.syncAddTransactionObject.type = Constants.CT_TRANSACTION_TYPE_REFUND; - const result = await syncHelper.runSyncAddTransaction(CommercetoolsApiConst.syncAddTransactionObject, '100', true, true); - if (result) { - let i = 0; - if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Process update capture amount for run sync ', async (t:any) => { - try { - let paymentObject: any = await CommercetoolsApi.retrievePayment(unit.paymentId); - let result = await syncHelper.processRunSyncUpdateCaptureAmount(PaymentServiceConst.captureResponse as any, 'f8269041-5c82-45f3-b45a-5c6586187cb1', paymentObject?.version, 300, 100); - let i = 0; - if (result && 'amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Process update capture amount for run sync when payment id is empty', async (t:any) => { - try { - let paymentObject: any = await CommercetoolsApi.retrievePayment(unit.paymentId); - let result = await syncHelper.processRunSyncUpdateCaptureAmount(PaymentServiceConst.captureResponse as any, '', paymentObject?.version, 300, 100); - t.falsy(result); - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('check if auth reversal triggered', async (t:any) => { - try { - let result = await syncHelper.isAuthReversalTriggered(PaymentServiceConst.getAuthorizedAmountCapturePaymentObj as any, 'submitTimeUtc:[NOW/DAY-1DAY TO NOW/HOUR+1HOUR}'); - if ('boolean' === typeof result) { - t.is(typeof result, 'boolean'); - } else { - t.fail(`Unexpected Result:${result} with type: ${typeof result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Retrieve sync amount details when capture is present', async (t: any) => { - try { - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authReasonCodePresent = false; - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.capturePresent = true; - PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.captureReasonCodePresent = true; - let result = await syncHelper.retrieveSyncAmountDetails(PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, PaymentServiceConst.retrieveSyncResponseTransactionElement, PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse); - if (result.centAmount && result.currencyCode) { - t.is(result.centAmount, 4500); - t.is(result.currencyCode, 'USD'); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('update capture amount for run sync', async (t: any) => { - try { - let result = await syncHelper.runSyncUpdateCaptureAmount(PaymentServiceConst.runSyncUpdateCaptureAmountUpdatePaymentObj as any, 1000); - if (result) { - let i = 0; - if (result && 'amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { - i++; - t.is(i, 1); - } else { - t.is(i, 0); - } - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('update capture amount for run sync when amount is 0', async (t: any) => { - try { - let result = await syncHelper.runSyncUpdateCaptureAmount(PaymentServiceConst.runSyncUpdateCaptureAmountUpdatePaymentObj as any, 0); - if (!result) { - t.falsy(result); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('check if auth reversal triggered with empty query string', async (t:any) => { - try { - let result = await syncHelper.isAuthReversalTriggered(PaymentServiceConst.getAuthorizedAmountCapturePaymentObj as any, ''); - if ('boolean' === typeof result) { - t.is(typeof result, 'boolean'); - } else { - t.fail(`Unexpected Result:${result} with type: ${typeof result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get the transaction summaries', async (t: any) => { - try { - let result: any = await syncHelper.getTransactionSummaries(PaymentServiceConst.getTransactionSummariesUpdatePaymentObj as any, 3); - if (result) { - let i = 0; - if ('summaries' in result && 'historyPresent' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get the transaction summaries with retry count is 0', async (t: any) => { - try { - let result: any = await syncHelper.getTransactionSummaries(PaymentServiceConst.getTransactionSummariesUpdatePaymentObj as any, 0); - if (result) { - let i = 0; - if ('summaries' in result && 'historyPresent' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('check if auth reversal is triggered ', async (t: any) => { - try { - let result = await syncHelper.checkAuthReversalTriggered( - PaymentServiceConst.getTransactionSummariesUpdatePaymentObj as any, - PaymentServiceConst.getCreditCardResponseCartObj as any, - PaymentServiceConst.checkAuthReversalTriggeredPaymentResponse, - PaymentServiceConst.checkAuthReversalTriggeredUpdateActions, - ); - if ('changeTransactionInteractionId' === result.actions[0].action && 'Success' === result.actions[1].state) { - t.is(result.actions[0].action, 'changeTransactionInteractionId'); - t.is(result.actions[1].action, 'changeTransactionState'); - t.is(result.actions[1].state, 'Success'); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get applications present', async (t:any) => { - try { - let result = await syncHelper.getApplicationsPresent(PaymentServiceConst.getPresentApplications); - let i = 0; - if ('authPresent' in result && 'authReasonCodePresent' in result && 'capturePresent' in result && 'captureReasonCodePresent' in result && 'authReversalPresent' in result && 'refundPresent' in result) { - i++; - } - if (i === 1) { - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } +import test from 'ava'; +import dotenv from 'dotenv'; + +dotenv.config(); +import { Constants } from '../../../../constants/paymentConstants'; +import CommercetoolsApi from '../../../../utils/api/CommercetoolsApi'; +import syncHelper from '../../../../utils/helpers/SyncHelper'; +import unit from '../../../JSON/unit.json'; +import CommercetoolsApiConst from '../../../const/CommercetoolsApiConst'; +import PaymentServiceConst from '../../../const/HelpersConst'; +import SyncHelperConst from '../../../const/SyncHelperConst'; + +test.serial('Retrieve sync response', async (t: any) => { + try { + let result = await syncHelper.retrieveSyncResponse(PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, PaymentServiceConst.retrieveSyncResponseTransactionElement); + let i = 0; + if (result && 'amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Process application response when auth is present', async (t:any) => { + try { + const result = await syncHelper.processApplicationResponse(PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse, PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, SyncHelperConst.syncUpdateObject, PaymentServiceConst.retrieveSyncResponseTransactionElement); + if (result) { + let i = 0; + if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Process application response when capture is present', async (t:any) => { + try { + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authPresent = false; + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.capturePresent = true; + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.captureReasonCodePresent = true; + const result = await syncHelper.processApplicationResponse(PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse, PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, SyncHelperConst.syncUpdateObject, PaymentServiceConst.retrieveSyncResponseTransactionElement); + if (result) { + let i = 0; + if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Process application response when auth reversal is present', async (t:any) => { + try { + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authPresent = false; + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.capturePresent = false; + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authReversalPresent = true; + const result = await syncHelper.processApplicationResponse(PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse, PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, SyncHelperConst.syncUpdateObject, PaymentServiceConst.retrieveSyncResponseTransactionElement); + if (result) { + let i = 0; + if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Process application response when refund is present', async (t:any) => { + try { + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authPresent = false; + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.capturePresent = false; + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authReversalPresent = false; + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.refundPresent = true; + const result = await syncHelper.processApplicationResponse(PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse, PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, SyncHelperConst.syncUpdateObject, PaymentServiceConst.retrieveSyncResponseTransactionElement); + if (result) { + let i = 0; + if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Run sync add transaction ', async (t:any) => { + try { + const result = await syncHelper.runSyncAddTransaction(CommercetoolsApiConst.syncAddTransactionObject, '100', true, true); + if (result) { + let i = 0; + if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Run sync add transaction when there is error', async (t:any) => { + try { + const result = await syncHelper.runSyncAddTransaction(CommercetoolsApiConst.syncAddTransactionObject, Constants.PAYMENT_GATEWAY_ERROR_REASON_CODE, true, true); + if (result) { + let i = 0; + if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Run sync add transaction when there is failure', async (t:any) => { + try { + const result = await syncHelper.runSyncAddTransaction(CommercetoolsApiConst.syncAddTransactionObject, Constants.PAYMENT_GATEWAY_FAILURE_REASON_CODE, true, true); + if (result) { + let i = 0; + if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Run sync add transaction when there is failure and auth reason code is not present', async (t:any) => { + try { + const result = await syncHelper.runSyncAddTransaction(CommercetoolsApiConst.syncAddTransactionObject, Constants.PAYMENT_GATEWAY_FAILURE_REASON_CODE, true, false); + if (result) { + let i = 0; + if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('add transaction for run sync when auth is not present', async (t: any) => { + try { + let result = await syncHelper.runSyncAddTransaction(PaymentServiceConst.runSyncAddTransactionSyncUpdateObject, '100', false, false); + if (result) { + t.is(result, true); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('add transaction for run sync when reason code is empty', async (t: any) => { + try { + let result = await syncHelper.runSyncAddTransaction(PaymentServiceConst.runSyncAddTransactionSyncUpdateObject, '', false, false); + if (null === result) { + t.is(result, null); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Run sync add transaction with refund', async (t:any) => { + try { + CommercetoolsApiConst.syncAddTransactionObject.type = Constants.CT_TRANSACTION_TYPE_REFUND; + const result = await syncHelper.runSyncAddTransaction(CommercetoolsApiConst.syncAddTransactionObject, '100', true, true); + if (result) { + let i = 0; + if ('amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Process update capture amount for run sync ', async (t:any) => { + try { + let paymentObject: any = await CommercetoolsApi.retrievePayment(unit.paymentId); + let result = await syncHelper.processRunSyncUpdateCaptureAmount(PaymentServiceConst.captureResponse as any, 'f8269041-5c82-45f3-b45a-5c6586187cb1', paymentObject?.version, 300, 100); + let i = 0; + if (result && 'amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Process update capture amount for run sync when payment id is empty', async (t:any) => { + try { + let paymentObject: any = await CommercetoolsApi.retrievePayment(unit.paymentId); + let result = await syncHelper.processRunSyncUpdateCaptureAmount(PaymentServiceConst.captureResponse as any, '', paymentObject?.version, 300, 100); + t.falsy(result); + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('check if auth reversal triggered', async (t:any) => { + try { + let result = await syncHelper.isAuthReversalTriggered(PaymentServiceConst.getAuthorizedAmountCapturePaymentObj as any, 'submitTimeUtc:[NOW/DAY-1DAY TO NOW/HOUR+1HOUR}'); + if ('boolean' === typeof result) { + t.is(typeof result, 'boolean'); + } else { + t.fail(`Unexpected Result:${result} with type: ${typeof result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Retrieve sync amount details when capture is present', async (t: any) => { + try { + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.authReasonCodePresent = false; + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.capturePresent = true; + PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse.captureReasonCodePresent = true; + let result = await syncHelper.retrieveSyncAmountDetails(PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, PaymentServiceConst.retrieveSyncResponseTransactionElement, PaymentServiceConst.retrieveSyncAmountDetailsApplicationResponse); + if (result.centAmount && result.currencyCode) { + t.is(result.centAmount, 4500); + t.is(result.currencyCode, 'USD'); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('update capture amount for run sync', async (t: any) => { + try { + let result = await syncHelper.runSyncUpdateCaptureAmount(PaymentServiceConst.runSyncUpdateCaptureAmountUpdatePaymentObj as any, 1000); + if (result) { + let i = 0; + if (result && 'amountPlanned' in result && 'paymentMethodInfo' in result && 'paymentStatus' in result) { + i++; + t.is(i, 1); + } else { + t.is(i, 0); + } + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('update capture amount for run sync when amount is 0', async (t: any) => { + try { + let result = await syncHelper.runSyncUpdateCaptureAmount(PaymentServiceConst.runSyncUpdateCaptureAmountUpdatePaymentObj as any, 0); + if (!result) { + t.falsy(result); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('check if auth reversal triggered with empty query string', async (t:any) => { + try { + let result = await syncHelper.isAuthReversalTriggered(PaymentServiceConst.getAuthorizedAmountCapturePaymentObj as any, ''); + if ('boolean' === typeof result) { + t.is(typeof result, 'boolean'); + } else { + t.fail(`Unexpected Result:${result} with type: ${typeof result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get the transaction summaries', async (t: any) => { + try { + let result: any = await syncHelper.getTransactionSummaries(PaymentServiceConst.getTransactionSummariesUpdatePaymentObj as any, 3); + if (result) { + let i = 0; + if ('summaries' in result && 'historyPresent' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get the transaction summaries with retry count is 0', async (t: any) => { + try { + let result: any = await syncHelper.getTransactionSummaries(PaymentServiceConst.getTransactionSummariesUpdatePaymentObj as any, 0); + if (result) { + let i = 0; + if ('summaries' in result && 'historyPresent' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('check if auth reversal is triggered ', async (t: any) => { + try { + let result = await syncHelper.checkAuthReversalTriggered( + PaymentServiceConst.getTransactionSummariesUpdatePaymentObj as any, + PaymentServiceConst.getCreditCardResponseCartObj as any, + PaymentServiceConst.checkAuthReversalTriggeredPaymentResponse, + PaymentServiceConst.checkAuthReversalTriggeredUpdateActions, + ); + if ('changeTransactionInteractionId' === result.actions[0].action && 'Success' === result.actions[1].state) { + t.is(result.actions[0].action, 'changeTransactionInteractionId'); + t.is(result.actions[1].action, 'changeTransactionState'); + t.is(result.actions[1].state, 'Success'); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get applications present', async (t:any) => { + try { + let result = await syncHelper.getApplicationsPresent(PaymentServiceConst.getPresentApplications); + let i = 0; + if ('authPresent' in result && 'authReasonCodePresent' in result && 'capturePresent' in result && 'captureReasonCodePresent' in result && 'authReversalPresent' in result && 'refundPresent' in result) { + i++; + } + if (i === 1) { + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } }); \ No newline at end of file diff --git a/src/unit-tests/unit/utils/helpers/TokenHelper.spec.ts b/src/unit-tests/unit/utils/helpers/TokenHelper.spec.ts index 9bf1980..becd5b9 100644 --- a/src/unit-tests/unit/utils/helpers/TokenHelper.spec.ts +++ b/src/unit-tests/unit/utils/helpers/TokenHelper.spec.ts @@ -1,606 +1,606 @@ -import test from 'ava'; -import dotenv from 'dotenv'; - -import { FunctionConstant } from '../../../../constants/functionConstant'; -import { Constants } from '../../../../constants/paymentConstants'; -import tokenHelper from '../../../../utils/helpers/TokenHelper'; -import unit from '../../../JSON/unit.json' -import AddTokenServiceConst from '../../../const/AddTokenServiceConst'; -import PaymentAuthorizationServiceConstCC from '../../../const/CreditCard/PaymentAuthorizationServiceConstCC'; -import PaymentCaptureServiceConstCC from '../../../const/CreditCard/PaymentCaptureServiceConstCC'; -import PaymentServiceConst from '../../../const/HelpersConst'; -import PaymentHandlerConst from '../../../const/PaymentHandlerConst'; -import PaymentUtilsConst from '../../../const/PaymentUtilsConst'; - -dotenv.config(); - -test.serial('Get bill to fields', async (t: any) => { - const result = await tokenHelper.getBillToFields(AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields, AddTokenServiceConst.addTokenResponseAddress, AddTokenServiceConst.addTokenResponseCustomerObj); - try { - if (result) { - let i = 0; - if ('id' in result && 'firstName' in result && 'lastName' in result && 'streetName' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get bill to fields when custom fields are empty', async (t: any) => { - let customFields: any = null; - try { - const result = await tokenHelper.getBillToFields(customFields, AddTokenServiceConst.addTokenResponseAddress, AddTokenServiceConst.addTokenResponseCustomerObj); - if (null === result) { - t.is(result, null); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get bill to fields when custom fields has string value', async (t: any) => { - let customFields: any = '12345'; - try { - const result = await tokenHelper.getBillToFields(customFields, AddTokenServiceConst.addTokenResponseAddress, AddTokenServiceConst.addTokenResponseCustomerObj); - if (null === result) { - t.is(result, null); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get bill to fields when custom fields has boolean value', async (t: any) => { - let customFields: any = true; - try { - const result = await tokenHelper.getBillToFields(customFields, AddTokenServiceConst.addTokenResponseAddress, AddTokenServiceConst.addTokenResponseCustomerObj); - if (null === result) { - t.is(result, null); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Get bill to fields for unified checkout', async (t: any) => { - try { - AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields.isv_addressId = 'UCAddress'; - const result = await tokenHelper.getBillToFields(AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields, AddTokenServiceConst.addTokenResponseAddress, AddTokenServiceConst.addTokenResponseCustomerObj); - if (result) { - let i = 0; - if ('id' in result && 'firstName' in result && 'lastName' in result && 'streetName' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get saved card count for rate limiter', async (t: any) => { - try { - let startTime = new Date(); - startTime.setHours(startTime.getHours() - Number(process.env.PAYMENT_GATEWAY_SAVED_CARD_LIMIT_FRAME)); - let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, new Date(startTime).toISOString(), new Date(Date.now()).toISOString()); - let i = 0; - if ('number' == typeof result) { - i++; - } - if (1 === i) { - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get saved card count for rate limiter with empty start time', async (t: any) => { - try { - let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, '', new Date(Date.now()).toISOString()); - if (0 === result) { - t.is(result, 0); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get saved card count for rate limiter with invalid start time', async (t: any) => { - try { - let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, '$^&**^%', new Date(Date.now()).toISOString()); - if (0 === result) { - t.is(result, 0); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get saved card count for rate limiter when end time is empty', async (t: any) => { - try { - let startTime = new Date(); - startTime.setHours(startTime.getHours() - Number(process.env.PAYMENT_GATEWAY_SAVED_CARD_LIMIT_FRAME)); - let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, new Date(startTime).toISOString(), ''); - if (0 === result) { - t.is(result, 0); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get saved card count for rate limiter when end time is invalid', async (t: any) => { - try { - let startTime = new Date(); - startTime.setHours(startTime.getHours() - Number(process.env.PAYMENT_GATEWAY_SAVED_CARD_LIMIT_FRAME)); - let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, new Date(startTime).toISOString(), '#&W^%'); - if (0 === result) { - t.is(result, 0); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get saved card count for rate limiter when start time and end time are invalid', async (t: any) => { - try { - let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, '#$%%^&*', '#&W^%'); - if (0 === result) { - t.is(result, 0); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Processing response for invalid card ', async (t) => { - try { - const result = await tokenHelper.processInvalidCardResponse(AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields, AddTokenServiceConst.addTokenResponseCustomerObj, unit.customerId); - if ('isv_tokens' === result.actions[0].name) { - t.is(result.actions[0].name, 'isv_tokens'); - t.is(result.actions[1].name, 'isv_tokenUpdated'); - t.is(result.actions[2].name, 'isv_failedTokens'); - t.is(result.actions[3].name, 'isv_tokenAlias'); - t.is(result.actions[4].name, 'isv_cardType'); - t.is(result.actions[5].name, 'isv_cardExpiryYear'); - t.is(result.actions[6].name, 'isv_cardExpiryMonth'); - t.is(result.actions[7].name, 'isv_addressId'); - t.is(result.actions[8].name, 'isv_currencyCode'); - t.is(result.actions[9].name, 'isv_deviceFingerprintId'); - t.is(result.actions[10].name, 'isv_token'); - t.is(result.actions[11].name, 'isv_maskedPan'); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Processing response for invalid card when custom field is not present', async (t) => { - let customFields: any = ''; - try { - const response = await tokenHelper.processInvalidCardResponse(customFields, AddTokenServiceConst.addTokenResponseCustomerObj, unit.customerId); - if (response?.errors) { - t.pass(); - } else { - t.fail(`Unexpected Result:${response}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Processing response for invalid card when custom field is a string', async (t) => { - let customFields: any = '^&*I(*'; - try { - const response = await tokenHelper.processInvalidCardResponse(customFields, AddTokenServiceConst.addTokenResponseCustomerObj, unit.customerId); - if (response?.errors) { - t.pass(); - } else { - t.fail(`Unexpected Result:${response}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Processing response for invalid card when customer id is empty', async (t) => { - try { - const result = await tokenHelper.processInvalidCardResponse(AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields, AddTokenServiceConst.addTokenResponseCustomerObj, ''); - if ('isv_tokens' === result.actions[0].name) { - t.is(result.actions[0].name, 'isv_tokens'); - t.is(result.actions[1].name, 'isv_tokenUpdated'); - t.is(result.actions[2].name, 'isv_failedTokens'); - t.is(result.actions[3].name, 'isv_tokenAlias'); - t.is(result.actions[4].name, 'isv_cardType'); - t.is(result.actions[5].name, 'isv_cardExpiryYear'); - t.is(result.actions[6].name, 'isv_cardExpiryMonth'); - t.is(result.actions[7].name, 'isv_addressId'); - t.is(result.actions[8].name, 'isv_currencyCode'); - t.is(result.actions[9].name, 'isv_deviceFingerprintId'); - t.is(result.actions[10].name, 'isv_token'); - t.is(result.actions[11].name, 'isv_maskedPan'); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Processing valid card response ', async (t) => { - try { - const result = await tokenHelper.processValidCardResponse(AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields, PaymentServiceConst.processTokensCustomerCardTokensObject, PaymentUtilsConst.validAddTokenResponse, AddTokenServiceConst.addTokenResponseCustomerObj, PaymentUtilsConst.createTokenDataAddress); - if ('isv_tokens' === result.actions[0].name) { - t.is(result.actions[0].name, 'isv_tokens'); - t.is(result.actions[1].name, 'isv_tokenUpdated'); - t.is(result.actions[2].name, 'isv_customerId'); - t.is(result.actions[3].name, 'isv_failedTokens'); - t.is(result.actions[4].name, 'isv_tokenAlias'); - t.is(result.actions[5].name, 'isv_cardType'); - t.is(result.actions[6].name, 'isv_cardExpiryYear'); - t.is(result.actions[7].name, 'isv_cardExpiryMonth'); - t.is(result.actions[8].name, 'isv_addressId'); - t.is(result.actions[9].name, 'isv_currencyCode'); - t.is(result.actions[10].name, 'isv_deviceFingerprintId'); - t.is(result.actions[11].name, 'isv_token'); - t.is(result.actions[12].name, 'isv_maskedPan'); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Processing valid card response when custom field is not present', async (t) => { - const customFields: any = null; - try { - const result = await tokenHelper.processValidCardResponse(customFields, PaymentServiceConst.processTokensCustomerCardTokensObject, PaymentUtilsConst.validAddTokenResponse, AddTokenServiceConst.addTokenResponseCustomerObj, PaymentUtilsConst.createTokenDataAddress); - if ('isv_tokens' === result.actions[0].name) { - t.is(result.actions[0].name, 'isv_tokens'); - t.is(result.actions[1].name, 'isv_tokenUpdated'); - t.is(result.actions[2].name, 'isv_customerId'); - t.is(result.actions[3].name, 'isv_failedTokens'); - t.is(result.actions[4].name, 'isv_tokenAlias'); - t.is(result.actions[5].name, 'isv_cardType'); - t.is(result.actions[6].name, 'isv_cardExpiryYear'); - t.is(result.actions[7].name, 'isv_cardExpiryMonth'); - t.is(result.actions[8].name, 'isv_addressId'); - t.is(result.actions[9].name, 'isv_currencyCode'); - t.is(result.actions[10].name, 'isv_deviceFingerprintId'); - t.is(result.actions[11].name, 'isv_token'); - t.is(result.actions[12].name, 'isv_maskedPan'); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Processing valid card response when custom field is a string', async (t) => { - const customFields: any = '784^&*'; - try { - const result = await tokenHelper.processValidCardResponse(customFields, PaymentServiceConst.processTokensCustomerCardTokensObject, PaymentUtilsConst.validAddTokenResponse, AddTokenServiceConst.addTokenResponseCustomerObj, PaymentUtilsConst.createTokenDataAddress); - if ('isv_tokens' === result.actions[0].name) { - t.is(result.actions[0].name, 'isv_tokens'); - t.is(result.actions[1].name, 'isv_tokenUpdated'); - t.is(result.actions[2].name, 'isv_customerId'); - t.is(result.actions[3].name, 'isv_failedTokens'); - t.is(result.actions[4].name, 'isv_tokenAlias'); - t.is(result.actions[5].name, 'isv_cardType'); - t.is(result.actions[6].name, 'isv_cardExpiryYear'); - t.is(result.actions[7].name, 'isv_cardExpiryMonth'); - t.is(result.actions[8].name, 'isv_addressId'); - t.is(result.actions[9].name, 'isv_currencyCode'); - t.is(result.actions[10].name, 'isv_deviceFingerprintId'); - t.is(result.actions[11].name, 'isv_token'); - t.is(result.actions[12].name, 'isv_maskedPan'); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get card tokens', async (t: any) => { - try { - let result = await tokenHelper.getCardTokens(PaymentHandlerConst.updateCardHandlerCustomerObj, 'abc'); - let i = 0; - if ('customerTokenId' in result && 'paymentInstrumentId' in result) { - i++; - } - if (1 === i) { - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('get card tokens when saved token is empty', async (t: any) => { - try { - let result = await tokenHelper.getCardTokens(PaymentHandlerConst.updateCardHandlerCustomerObj, ''); - let i = 0; - if ('customerTokenId' in result && 'paymentInstrumentId' in result) { - i++; - } - if (1 === i) { - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('set Customer Token Data', async (t) => { - try { - let result = await tokenHelper.setCustomerTokenData( - PaymentServiceConst.customerCardTokens, - PaymentServiceConst.getAuthResponsePaymentResponse, - PaymentServiceConst.authResponse, - false, - PaymentHandlerConst.authorizationHandler3DSUpdatePaymentObject as any, - PaymentCaptureServiceConstCC.cart as any - ); - if ('setCustomField' === result.actions[0].action) { - t.is(result.actions[0].action, 'setCustomField'); - t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); - t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); - t.is(result.actions[2].name, 'isv_payerEnrollStatus'); - t.is(result.actions[3].name, 'isv_payerAuthenticationTransactionId'); - t.is(result.actions[4].name, 'isv_tokenCaptureContextSignature'); - t.is(result.actions[5].name, 'isv_payerAuthenticationRequired'); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Evaluate token creation', async (t) => { - try { - const result = await tokenHelper.evaluateTokenCreation(AddTokenServiceConst.addTokenResponseCustomerObj, PaymentAuthorizationServiceConstCC.payments as any, FunctionConstant.FUNC_HANDLE_CARD_ADDITION); - if ('boolean' === typeof result.isSaveToken && 'boolean' === typeof result.isError) { - t.is(typeof result.isSaveToken, 'boolean'); - t.is(typeof result.isError, 'boolean'); - } else { - t.fail(`Unexpected Result :${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('add customer address for uc', async (t: any) => { - try { - let result = await tokenHelper.addTokenAddressForUC(PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, PaymentServiceConst.getCreditCardResponseCartObj as any); - if (result) { - let i = 0; - if ('email' in result && 'firstName' in result && 'lastName' in result && 'custom' in result) { - i++; - } - if (1 === i) { - t.is(i, 1); - } - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Set failed token data to customer', async (t) => { - try { - let result: any = await tokenHelper.setCustomerFailedTokenData(PaymentAuthorizationServiceConstCC.payment as any, PaymentServiceConst.customFields, ''); - if (Constants.HTTP_OK_STATUS_CODE === result?.statusCode) { - if (result?.body) result = result.body; - let i = 0; - if (result && 'email' in result && 'firstName' in result && 'lastName' in result) { - i++; - t.is(i, 1); - } - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('process tokens', async (t) => { - try { - let result = await tokenHelper.processTokens( - PaymentServiceConst.processTokensCustomerCardTokensObject.customerTokenId, - PaymentServiceConst.processTokensCustomerCardTokensObject.paymentInstrumentId, - PaymentServiceConst.processTokensInstrumentIdentifier, - PaymentAuthorizationServiceConstCC.payment as any, - '', - ); - if (result) { - let i = 0; - if ('email' in result && 'firstName' in result && 'lastName' in result && 'custom' in result) { - i++; - } - if (1 === i) t.is(i, 1); - else t.is(i, 0); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('process tokens when token and instrument id is empty', async (t) => { - try { - let result = await tokenHelper.processTokens('', '', PaymentServiceConst.processTokensInstrumentIdentifier, PaymentAuthorizationServiceConstCC.payment as any, ''); - if (null === result) { - t.is(result, null); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('process tokens with empty instrument identifier', async (t) => { - try { - let result = await tokenHelper.processTokens(PaymentServiceConst.processTokensCustomerCardTokensObject.customerTokenId, PaymentServiceConst.processTokensCustomerCardTokensObject.paymentInstrumentId, '', PaymentAuthorizationServiceConstCC.payment as any, ''); - if (result) { - let i = 0; - if ('email' in result && 'firstName' in result && 'lastName' in result && 'custom' in result) { - i++; - } - t.is(i, 1); - } else { - t.fail(`Unexpected Result:${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } +import test from 'ava'; +import dotenv from 'dotenv'; + +import { FunctionConstant } from '../../../../constants/functionConstant'; +import { Constants } from '../../../../constants/paymentConstants'; +import tokenHelper from '../../../../utils/helpers/TokenHelper'; +import unit from '../../../JSON/unit.json' +import AddTokenServiceConst from '../../../const/AddTokenServiceConst'; +import PaymentAuthorizationServiceConstCC from '../../../const/CreditCard/PaymentAuthorizationServiceConstCC'; +import PaymentCaptureServiceConstCC from '../../../const/CreditCard/PaymentCaptureServiceConstCC'; +import PaymentServiceConst from '../../../const/HelpersConst'; +import PaymentHandlerConst from '../../../const/PaymentHandlerConst'; +import PaymentUtilsConst from '../../../const/PaymentUtilsConst'; + +dotenv.config(); + +test.serial('Get bill to fields', async (t: any) => { + const result = await tokenHelper.getBillToFields(AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields, AddTokenServiceConst.addTokenResponseAddress, AddTokenServiceConst.addTokenResponseCustomerObj); + try { + if (result) { + let i = 0; + if ('id' in result && 'firstName' in result && 'lastName' in result && 'streetName' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get bill to fields when custom fields are empty', async (t: any) => { + let customFields: any = null; + try { + const result = await tokenHelper.getBillToFields(customFields, AddTokenServiceConst.addTokenResponseAddress, AddTokenServiceConst.addTokenResponseCustomerObj); + if (null === result) { + t.is(result, null); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get bill to fields when custom fields has string value', async (t: any) => { + let customFields: any = '12345'; + try { + const result = await tokenHelper.getBillToFields(customFields, AddTokenServiceConst.addTokenResponseAddress, AddTokenServiceConst.addTokenResponseCustomerObj); + if (null === result) { + t.is(result, null); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get bill to fields when custom fields has boolean value', async (t: any) => { + let customFields: any = true; + try { + const result = await tokenHelper.getBillToFields(customFields, AddTokenServiceConst.addTokenResponseAddress, AddTokenServiceConst.addTokenResponseCustomerObj); + if (null === result) { + t.is(result, null); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Get bill to fields for unified checkout', async (t: any) => { + try { + AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields.isv_addressId = 'UCAddress'; + const result = await tokenHelper.getBillToFields(AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields, AddTokenServiceConst.addTokenResponseAddress, AddTokenServiceConst.addTokenResponseCustomerObj); + if (result) { + let i = 0; + if ('id' in result && 'firstName' in result && 'lastName' in result && 'streetName' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get saved card count for rate limiter', async (t: any) => { + try { + let startTime = new Date(); + startTime.setHours(startTime.getHours() - Number(process.env.PAYMENT_GATEWAY_SAVED_CARD_LIMIT_FRAME)); + let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, new Date(startTime).toISOString(), new Date(Date.now()).toISOString()); + let i = 0; + if ('number' == typeof result) { + i++; + } + if (1 === i) { + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get saved card count for rate limiter with empty start time', async (t: any) => { + try { + let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, '', new Date(Date.now()).toISOString()); + if (0 === result) { + t.is(result, 0); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get saved card count for rate limiter with invalid start time', async (t: any) => { + try { + let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, '$^&**^%', new Date(Date.now()).toISOString()); + if (0 === result) { + t.is(result, 0); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get saved card count for rate limiter when end time is empty', async (t: any) => { + try { + let startTime = new Date(); + startTime.setHours(startTime.getHours() - Number(process.env.PAYMENT_GATEWAY_SAVED_CARD_LIMIT_FRAME)); + let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, new Date(startTime).toISOString(), ''); + if (0 === result) { + t.is(result, 0); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get saved card count for rate limiter when end time is invalid', async (t: any) => { + try { + let startTime = new Date(); + startTime.setHours(startTime.getHours() - Number(process.env.PAYMENT_GATEWAY_SAVED_CARD_LIMIT_FRAME)); + let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, new Date(startTime).toISOString(), '#&W^%'); + if (0 === result) { + t.is(result, 0); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get saved card count for rate limiter when start time and end time are invalid', async (t: any) => { + try { + let result = await tokenHelper.getRateLimiterTokenCount(PaymentHandlerConst.updateCardHandlerCustomerObj, '#$%%^&*', '#&W^%'); + if (0 === result) { + t.is(result, 0); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Processing response for invalid card ', async (t) => { + try { + const result = await tokenHelper.processInvalidCardResponse(AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields, AddTokenServiceConst.addTokenResponseCustomerObj, unit.customerId); + if ('isv_tokens' === result.actions[0].name) { + t.is(result.actions[0].name, 'isv_tokens'); + t.is(result.actions[1].name, 'isv_tokenUpdated'); + t.is(result.actions[2].name, 'isv_failedTokens'); + t.is(result.actions[3].name, 'isv_tokenAlias'); + t.is(result.actions[4].name, 'isv_cardType'); + t.is(result.actions[5].name, 'isv_cardExpiryYear'); + t.is(result.actions[6].name, 'isv_cardExpiryMonth'); + t.is(result.actions[7].name, 'isv_addressId'); + t.is(result.actions[8].name, 'isv_currencyCode'); + t.is(result.actions[9].name, 'isv_deviceFingerprintId'); + t.is(result.actions[10].name, 'isv_token'); + t.is(result.actions[11].name, 'isv_maskedPan'); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Processing response for invalid card when custom field is not present', async (t) => { + let customFields: any = ''; + try { + const response = await tokenHelper.processInvalidCardResponse(customFields, AddTokenServiceConst.addTokenResponseCustomerObj, unit.customerId); + if (response?.errors) { + t.pass(); + } else { + t.fail(`Unexpected Result:${response}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Processing response for invalid card when custom field is a string', async (t) => { + let customFields: any = '^&*I(*'; + try { + const response = await tokenHelper.processInvalidCardResponse(customFields, AddTokenServiceConst.addTokenResponseCustomerObj, unit.customerId); + if (response?.errors) { + t.pass(); + } else { + t.fail(`Unexpected Result:${response}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Processing response for invalid card when customer id is empty', async (t) => { + try { + const result = await tokenHelper.processInvalidCardResponse(AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields, AddTokenServiceConst.addTokenResponseCustomerObj, ''); + if ('isv_tokens' === result.actions[0].name) { + t.is(result.actions[0].name, 'isv_tokens'); + t.is(result.actions[1].name, 'isv_tokenUpdated'); + t.is(result.actions[2].name, 'isv_failedTokens'); + t.is(result.actions[3].name, 'isv_tokenAlias'); + t.is(result.actions[4].name, 'isv_cardType'); + t.is(result.actions[5].name, 'isv_cardExpiryYear'); + t.is(result.actions[6].name, 'isv_cardExpiryMonth'); + t.is(result.actions[7].name, 'isv_addressId'); + t.is(result.actions[8].name, 'isv_currencyCode'); + t.is(result.actions[9].name, 'isv_deviceFingerprintId'); + t.is(result.actions[10].name, 'isv_token'); + t.is(result.actions[11].name, 'isv_maskedPan'); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Processing valid card response ', async (t) => { + try { + const result = await tokenHelper.processValidCardResponse(AddTokenServiceConst.addTokenResponseCustomerObj.custom.fields, PaymentServiceConst.processTokensCustomerCardTokensObject, PaymentUtilsConst.validAddTokenResponse, AddTokenServiceConst.addTokenResponseCustomerObj, PaymentUtilsConst.createTokenDataAddress); + if ('isv_tokens' === result.actions[0].name) { + t.is(result.actions[0].name, 'isv_tokens'); + t.is(result.actions[1].name, 'isv_tokenUpdated'); + t.is(result.actions[2].name, 'isv_customerId'); + t.is(result.actions[3].name, 'isv_failedTokens'); + t.is(result.actions[4].name, 'isv_tokenAlias'); + t.is(result.actions[5].name, 'isv_cardType'); + t.is(result.actions[6].name, 'isv_cardExpiryYear'); + t.is(result.actions[7].name, 'isv_cardExpiryMonth'); + t.is(result.actions[8].name, 'isv_addressId'); + t.is(result.actions[9].name, 'isv_currencyCode'); + t.is(result.actions[10].name, 'isv_deviceFingerprintId'); + t.is(result.actions[11].name, 'isv_token'); + t.is(result.actions[12].name, 'isv_maskedPan'); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Processing valid card response when custom field is not present', async (t) => { + const customFields: any = null; + try { + const result = await tokenHelper.processValidCardResponse(customFields, PaymentServiceConst.processTokensCustomerCardTokensObject, PaymentUtilsConst.validAddTokenResponse, AddTokenServiceConst.addTokenResponseCustomerObj, PaymentUtilsConst.createTokenDataAddress); + if ('isv_tokens' === result.actions[0].name) { + t.is(result.actions[0].name, 'isv_tokens'); + t.is(result.actions[1].name, 'isv_tokenUpdated'); + t.is(result.actions[2].name, 'isv_customerId'); + t.is(result.actions[3].name, 'isv_failedTokens'); + t.is(result.actions[4].name, 'isv_tokenAlias'); + t.is(result.actions[5].name, 'isv_cardType'); + t.is(result.actions[6].name, 'isv_cardExpiryYear'); + t.is(result.actions[7].name, 'isv_cardExpiryMonth'); + t.is(result.actions[8].name, 'isv_addressId'); + t.is(result.actions[9].name, 'isv_currencyCode'); + t.is(result.actions[10].name, 'isv_deviceFingerprintId'); + t.is(result.actions[11].name, 'isv_token'); + t.is(result.actions[12].name, 'isv_maskedPan'); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Processing valid card response when custom field is a string', async (t) => { + const customFields: any = '784^&*'; + try { + const result = await tokenHelper.processValidCardResponse(customFields, PaymentServiceConst.processTokensCustomerCardTokensObject, PaymentUtilsConst.validAddTokenResponse, AddTokenServiceConst.addTokenResponseCustomerObj, PaymentUtilsConst.createTokenDataAddress); + if ('isv_tokens' === result.actions[0].name) { + t.is(result.actions[0].name, 'isv_tokens'); + t.is(result.actions[1].name, 'isv_tokenUpdated'); + t.is(result.actions[2].name, 'isv_customerId'); + t.is(result.actions[3].name, 'isv_failedTokens'); + t.is(result.actions[4].name, 'isv_tokenAlias'); + t.is(result.actions[5].name, 'isv_cardType'); + t.is(result.actions[6].name, 'isv_cardExpiryYear'); + t.is(result.actions[7].name, 'isv_cardExpiryMonth'); + t.is(result.actions[8].name, 'isv_addressId'); + t.is(result.actions[9].name, 'isv_currencyCode'); + t.is(result.actions[10].name, 'isv_deviceFingerprintId'); + t.is(result.actions[11].name, 'isv_token'); + t.is(result.actions[12].name, 'isv_maskedPan'); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get card tokens', async (t: any) => { + try { + let result = await tokenHelper.getCardTokens(PaymentHandlerConst.updateCardHandlerCustomerObj, 'abc'); + let i = 0; + if ('customerTokenId' in result && 'paymentInstrumentId' in result) { + i++; + } + if (1 === i) { + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('get card tokens when saved token is empty', async (t: any) => { + try { + let result = await tokenHelper.getCardTokens(PaymentHandlerConst.updateCardHandlerCustomerObj, ''); + let i = 0; + if ('customerTokenId' in result && 'paymentInstrumentId' in result) { + i++; + } + if (1 === i) { + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('set Customer Token Data', async (t) => { + try { + let result = await tokenHelper.setCustomerTokenData( + PaymentServiceConst.customerCardTokens, + PaymentServiceConst.getAuthResponsePaymentResponse, + PaymentServiceConst.authResponse, + false, + PaymentHandlerConst.authorizationHandler3DSUpdatePaymentObject as any, + PaymentCaptureServiceConstCC.cart as any + ); + if ('setCustomField' === result.actions[0].action) { + t.is(result.actions[0].action, 'setCustomField'); + t.is(result.actions[0].name, 'isv_payerEnrollTransactionId'); + t.is(result.actions[1].name, 'isv_payerEnrollHttpCode'); + t.is(result.actions[2].name, 'isv_payerEnrollStatus'); + t.is(result.actions[3].name, 'isv_payerAuthenticationTransactionId'); + t.is(result.actions[4].name, 'isv_tokenCaptureContextSignature'); + t.is(result.actions[5].name, 'isv_payerAuthenticationRequired'); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Evaluate token creation', async (t) => { + try { + const result = await tokenHelper.evaluateTokenCreation(AddTokenServiceConst.addTokenResponseCustomerObj, PaymentAuthorizationServiceConstCC.payments as any, FunctionConstant.FUNC_HANDLE_CARD_ADDITION); + if ('boolean' === typeof result.isSaveToken && 'boolean' === typeof result.isError) { + t.is(typeof result.isSaveToken, 'boolean'); + t.is(typeof result.isError, 'boolean'); + } else { + t.fail(`Unexpected Result :${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('add customer address for uc', async (t: any) => { + try { + let result = await tokenHelper.addTokenAddressForUC(PaymentServiceConst.getCreditCardResponseUpdatePaymentObj, PaymentServiceConst.getCreditCardResponseCartObj as any); + if (result) { + let i = 0; + if ('email' in result && 'firstName' in result && 'lastName' in result && 'custom' in result) { + i++; + } + if (1 === i) { + t.is(i, 1); + } + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Set failed token data to customer', async (t) => { + try { + let result: any = await tokenHelper.setCustomerFailedTokenData(PaymentAuthorizationServiceConstCC.payment as any, PaymentServiceConst.customFields, ''); + if (Constants.HTTP_OK_STATUS_CODE === result?.statusCode) { + if (result?.body) result = result.body; + let i = 0; + if (result && 'email' in result && 'firstName' in result && 'lastName' in result) { + i++; + t.is(i, 1); + } + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('process tokens', async (t) => { + try { + let result = await tokenHelper.processTokens( + PaymentServiceConst.processTokensCustomerCardTokensObject.customerTokenId, + PaymentServiceConst.processTokensCustomerCardTokensObject.paymentInstrumentId, + PaymentServiceConst.processTokensInstrumentIdentifier, + PaymentAuthorizationServiceConstCC.payment as any, + '', + ); + if (result) { + let i = 0; + if ('email' in result && 'firstName' in result && 'lastName' in result && 'custom' in result) { + i++; + } + if (1 === i) t.is(i, 1); + else t.is(i, 0); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('process tokens when token and instrument id is empty', async (t) => { + try { + let result = await tokenHelper.processTokens('', '', PaymentServiceConst.processTokensInstrumentIdentifier, PaymentAuthorizationServiceConstCC.payment as any, ''); + if (null === result) { + t.is(result, null); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('process tokens with empty instrument identifier', async (t) => { + try { + let result = await tokenHelper.processTokens(PaymentServiceConst.processTokensCustomerCardTokensObject.customerTokenId, PaymentServiceConst.processTokensCustomerCardTokensObject.paymentInstrumentId, '', PaymentAuthorizationServiceConstCC.payment as any, ''); + if (result) { + let i = 0; + if ('email' in result && 'firstName' in result && 'lastName' in result && 'custom' in result) { + i++; + } + t.is(i, 1); + } else { + t.fail(`Unexpected Result:${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } }); \ No newline at end of file diff --git a/src/unit-tests/unit/utils/helpers/WebhookHelper.spec.ts b/src/unit-tests/unit/utils/helpers/WebhookHelper.spec.ts index d3a681f..69246cd 100644 --- a/src/unit-tests/unit/utils/helpers/WebhookHelper.spec.ts +++ b/src/unit-tests/unit/utils/helpers/WebhookHelper.spec.ts @@ -1,156 +1,156 @@ -import test from 'ava'; -import dotenv from 'dotenv'; - -dotenv.config(); -import { Constants } from '../../../../constants/paymentConstants'; -import multiMid from '../../../../utils/config/MultiMid'; -import webhookHelper from '../../../../utils/helpers/WebhookHelper'; -import DeleteWebhookSubscriptionConst from '../../../const/DeleteWebhookSubscriptionConst'; -import PaymentServiceConst from '../../../const/HelpersConst'; - -test.serial('Handle webhook subscription', async (t) => { - try { - let midCredentials = await multiMid.getMidCredentials(process.env.PAYMENT_GATEWAY_MERCHANT_ID as string); - const result = await webhookHelper.handleWebhookSubscription(midCredentials); - if (Constants.HTTP_OK_STATUS_CODE === result.httpCode || Constants.HTTP_SUCCESS_STATUS_CODE === result.httpCode) { - t.pass(); - } else { - t.fail(`Unexpected response: HTTP ${result.httpCode}, Status:${JSON.stringify(result)}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Handle webhook subscription with empty mid credential', async (t) => { - try { - const result = await webhookHelper.handleWebhookSubscription(DeleteWebhookSubscriptionConst.emptyMidCredentials); - if (Constants.HTTP_CODE_ZERO === result.httpCode) { - t.pass(); - } else { - t.fail(`Unexpected response: HTTP ${result.httpCode}, Status:${JSON.stringify(result)}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Handle webhook subscription with invalid mid credential', async (t) => { - try { - const result = await webhookHelper.handleWebhookSubscription(DeleteWebhookSubscriptionConst.invalidMidCredentials); - if (Constants.HTTP_UNAUTHORIZED_STATUS_CODE === result.httpCode) { - t.pass(); - } else { - t.fail(`Unexpected response: HTTP ${result.httpCode}, Status:${JSON.stringify(result)}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Test getSubscriptionDetails api function', async (t) => { - try { - let result = await webhookHelper.verifySubscription(PaymentServiceConst.searchSubscriptionResponse, process.env.PAYMENT_GATEWAY_MERCHANT_ID); - if ('boolean' === typeof result.isSubscribed && 'boolean' === typeof result.presentInCustomObject) { - t.is(typeof result.isSubscribed, 'boolean'); - t.is(typeof result.presentInCustomObject, 'boolean'); - t.is(result.webhookId, PaymentServiceConst.searchSubscriptionResponse.webhookId); - } else { - t.fail(`Unexpected Result :${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Test getSubscriptionDetails api function when merchant id is null', async (t) => { - try { - let result = await webhookHelper.verifySubscription(PaymentServiceConst.searchSubscriptionResponse, ''); - if ('boolean' === typeof result.isSubscribed && 'boolean' === typeof result.presentInCustomObject) { - t.is(typeof result.isSubscribed, 'boolean'); - t.is(typeof result.presentInCustomObject, 'boolean'); - t.is(result.webhookId, PaymentServiceConst.searchSubscriptionResponse.webhookId); - } else { - t.fail(`Unexpected Result :${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Test getSubscriptionDetails api function with empty webhook id', async (t) => { - try { - let result = await webhookHelper.verifySubscription(PaymentServiceConst.invalidSearchSubscriptionResponse, process.env.PAYMENT_GATEWAY_MERCHANT_ID); - if (false === result.isSubscribed && false === result.presentInCustomObject) { - t.is(result.isSubscribed, false); - t.is(result.presentInCustomObject, false); - t.is(result.webhookId, ''); - } else { - t.fail(`Unexpected Result :${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Test getSubscriptionDetails api function with empty webhook id and merchant id', async (t) => { - try { - let result = await webhookHelper.verifySubscription(PaymentServiceConst.invalidSearchSubscriptionResponse, ''); - if (false === result.isSubscribed && false === result.presentInCustomObject) { - t.is(result.isSubscribed, false); - t.is(result.presentInCustomObject, false); - t.is(result.webhookId, ''); - } else { - t.fail(`Unexpected Result :${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } -}); - -test.serial('Test getSubscriptionDetails api function with invalid subscription response', async (t) => { - try { - let result = await webhookHelper.verifySubscription(PaymentServiceConst.invalidSubscriptionResponse, process.env.PAYMENT_GATEWAY_MERCHANT_ID); - if ('boolean' === typeof result.isSubscribed && 'boolean' === typeof result.presentInCustomObject) { - t.is(typeof result.isSubscribed, 'boolean'); - t.is(typeof result.presentInCustomObject, 'boolean'); - t.is(result.webhookId, ''); - } else { - t.fail(`Unexpected Result :${result}`); - } - } catch (error) { - if (error instanceof Error) { - t.fail(`Caught an error during execution: ${error.message}`); - } else { - t.fail(`Caught an unknown error: ${String(error)}`); - } - } +import test from 'ava'; +import dotenv from 'dotenv'; + +dotenv.config(); +import { Constants } from '../../../../constants/paymentConstants'; +import multiMid from '../../../../utils/config/MultiMid'; +import webhookHelper from '../../../../utils/helpers/WebhookHelper'; +import DeleteWebhookSubscriptionConst from '../../../const/DeleteWebhookSubscriptionConst'; +import PaymentServiceConst from '../../../const/HelpersConst'; + +test.serial('Handle webhook subscription', async (t) => { + try { + let midCredentials = await multiMid.getMidCredentials(process.env.PAYMENT_GATEWAY_MERCHANT_ID as string); + const result = await webhookHelper.handleWebhookSubscription(midCredentials); + if (Constants.HTTP_OK_STATUS_CODE === result.httpCode || Constants.HTTP_SUCCESS_STATUS_CODE === result.httpCode) { + t.pass(); + } else { + t.fail(`Unexpected response: HTTP ${result.httpCode}, Status:${JSON.stringify(result)}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Handle webhook subscription with empty mid credential', async (t) => { + try { + const result = await webhookHelper.handleWebhookSubscription(DeleteWebhookSubscriptionConst.emptyMidCredentials); + if (Constants.HTTP_CODE_ZERO === result.httpCode) { + t.pass(); + } else { + t.fail(`Unexpected response: HTTP ${result.httpCode}, Status:${JSON.stringify(result)}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Handle webhook subscription with invalid mid credential', async (t) => { + try { + const result = await webhookHelper.handleWebhookSubscription(DeleteWebhookSubscriptionConst.invalidMidCredentials); + if (Constants.HTTP_UNAUTHORIZED_STATUS_CODE === result.httpCode) { + t.pass(); + } else { + t.fail(`Unexpected response: HTTP ${result.httpCode}, Status:${JSON.stringify(result)}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Test getSubscriptionDetails api function', async (t) => { + try { + let result = await webhookHelper.verifySubscription(PaymentServiceConst.searchSubscriptionResponse, process.env.PAYMENT_GATEWAY_MERCHANT_ID); + if ('boolean' === typeof result.isSubscribed && 'boolean' === typeof result.presentInCustomObject) { + t.is(typeof result.isSubscribed, 'boolean'); + t.is(typeof result.presentInCustomObject, 'boolean'); + t.is(result.webhookId, PaymentServiceConst.searchSubscriptionResponse.webhookId); + } else { + t.fail(`Unexpected Result :${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Test getSubscriptionDetails api function when merchant id is null', async (t) => { + try { + let result = await webhookHelper.verifySubscription(PaymentServiceConst.searchSubscriptionResponse, ''); + if ('boolean' === typeof result.isSubscribed && 'boolean' === typeof result.presentInCustomObject) { + t.is(typeof result.isSubscribed, 'boolean'); + t.is(typeof result.presentInCustomObject, 'boolean'); + t.is(result.webhookId, PaymentServiceConst.searchSubscriptionResponse.webhookId); + } else { + t.fail(`Unexpected Result :${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Test getSubscriptionDetails api function with empty webhook id', async (t) => { + try { + let result = await webhookHelper.verifySubscription(PaymentServiceConst.invalidSearchSubscriptionResponse, process.env.PAYMENT_GATEWAY_MERCHANT_ID); + if (false === result.isSubscribed && false === result.presentInCustomObject) { + t.is(result.isSubscribed, false); + t.is(result.presentInCustomObject, false); + t.is(result.webhookId, ''); + } else { + t.fail(`Unexpected Result :${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Test getSubscriptionDetails api function with empty webhook id and merchant id', async (t) => { + try { + let result = await webhookHelper.verifySubscription(PaymentServiceConst.invalidSearchSubscriptionResponse, ''); + if (false === result.isSubscribed && false === result.presentInCustomObject) { + t.is(result.isSubscribed, false); + t.is(result.presentInCustomObject, false); + t.is(result.webhookId, ''); + } else { + t.fail(`Unexpected Result :${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } +}); + +test.serial('Test getSubscriptionDetails api function with invalid subscription response', async (t) => { + try { + let result = await webhookHelper.verifySubscription(PaymentServiceConst.invalidSubscriptionResponse, process.env.PAYMENT_GATEWAY_MERCHANT_ID); + if ('boolean' === typeof result.isSubscribed && 'boolean' === typeof result.presentInCustomObject) { + t.is(typeof result.isSubscribed, 'boolean'); + t.is(typeof result.presentInCustomObject, 'boolean'); + t.is(result.webhookId, ''); + } else { + t.fail(`Unexpected Result :${result}`); + } + } catch (error) { + if (error instanceof Error) { + t.fail(`Caught an error during execution: ${error.message}`); + } else { + t.fail(`Caught an unknown error: ${String(error)}`); + } + } }); \ No newline at end of file diff --git a/src/utils/PaymentActions.ts b/src/utils/PaymentActions.ts index ee6e64b..5380b76 100644 --- a/src/utils/PaymentActions.ts +++ b/src/utils/PaymentActions.ts @@ -201,8 +201,10 @@ const createEnrollResponseActions = (response: any, updatePaymentObj: Payment): let { transactionId: isv_payerEnrollTransactionId, httpCode: isv_payerEnrollHttpCode, status: isv_payerEnrollStatus, data } = response || {}; action.actions = paymentUtils.setCustomFieldMapper({ isv_payerEnrollTransactionId, isv_payerEnrollHttpCode, isv_payerEnrollStatus }); if (Constants.HTTP_SUCCESS_STATUS_CODE === isv_payerEnrollHttpCode && Constants.API_STATUS_AUTHORIZED === isv_payerEnrollStatus && data) { + if(!customFields?.isv_payerAuthenticationTransactionId){ isv_payerAuthenticationTransactionId = response.data.consumerAuthenticationInformation?.authenticationTransactionId || isv_payerEnrollTransactionId; action.actions.push(...paymentUtils.setCustomFieldMapper({ isv_payerAuthenticationTransactionId })); + } } if (response.data?.id && 'PAYERAUTH_INVOKE' === response.action || 'PAYERAUTH_EXTERNAL' === response.action || ('04' === response?.requestData?.consumerAuthenticationInformation?.challengeCode && paymentUtils.toBoolean(process.env.PAYMENT_GATEWAY_DECISION_MANAGER))) { isv_dmpaFlag = true; diff --git a/src/utils/PaymentHandler.ts b/src/utils/PaymentHandler.ts index e40222a..191b2aa 100644 --- a/src/utils/PaymentHandler.ts +++ b/src/utils/PaymentHandler.ts @@ -61,7 +61,7 @@ const handleAuthorization = async (updatePaymentObj: Payment, updateTransactions const serviceResponse = await handlePaymentAuth(paymentMethod, updatePaymentObj, customerInfo, results[0], updateTransactions, cardTokens, orderNo); const authresponse = serviceResponse?.authResponse; if (authresponse) { - authResponse = serviceResponse.authResponse; + authResponse = paymentUtils.validateActionResponse(serviceResponse.authResponse); isError = serviceResponse.isError; } const paymentResponse = serviceResponse.paymentResponse; @@ -163,6 +163,63 @@ const handlePayerAuthReversal = async (updatePaymentObj: Payment, paymentRespons return updateActions; }; +/* START GENAI */ +/** + * Allowlist of Apple Pay validation domains and IP addresses. + * Only these endpoints are permitted for Apple Pay session validation requests. + */ +const applePayAllowedDomains = { + domains: [ + 'apple-pay-gateway.apple.com', + 'cn-apple-pay-gateway.apple.com', + 'apple-pay-gateway-cert.apple.com', + 'cn-apple-pay-gateway-cert.apple.com', + ], + ipAddresses: [ + '17.171.78.7', '17.171.78.71', '17.171.78.135', '17.171.78.199', '17.171.79.12', + '17.141.128.7', '17.141.128.71', '17.141.128.135', '17.141.128.199', '17.141.129.12', + '17.32.214.7', '17.157.96.181', '17.33.194.239', '17.33.192.38', '17.33.193.110', + '17.33.202.35', '17.33.201.101', '17.33.200.169', + '101.230.204.232', '101.230.204.242', '101.230.204.240', + '60.29.205.104', '60.29.205.106', '60.29.205.108', + '17.171.85.7', '17.179.124.181', '17.32.214.56', + '17.33.194.218', '17.33.192.145', '17.33.193.45', + '17.33.200.47', '17.33.202.99', '17.33.201.105', + '101.230.204.235', + ], +}; + +/** + * Validates that the Apple Pay validation URL is an allowed Apple endpoint. + * Checks URL scheme (must be https), and that the hostname matches + * an allowed domain or IP address from the allowlist. + * + * @param {string | undefined} validationUrl - The URL to validate. + * @returns {boolean} - True if the URL is allowed, false otherwise. + */ +const isValidApplePayValidationUrl = (validationUrl: string | undefined): boolean => { + if (!validationUrl) { + return false; + } + try { + const parsedUrl = new URL(validationUrl); + if (parsedUrl.protocol !== 'https:') { + return false; + } + const hostname = parsedUrl.hostname.toLowerCase(); + if (applePayAllowedDomains.domains.includes(hostname)) { + return true; + } + if (applePayAllowedDomains.ipAddresses.includes(hostname)) { + return true; + } + return false; + } catch { + return false; + } +}; +/* END GENAI */ + /** * Handles Apple Pay session. * @@ -177,10 +234,16 @@ const handleApplePaySession = async (fields: Partial): key: '', }); const { PAYMENT_GATEWAY_APPLE_PAY_CERTIFICATE_PATH, PAYMENT_GATEWAY_APPLE_PAY_KEY_PATH, PAYMENT_GATEWAY_APPLE_PAY_DOMAIN_NAME, PAYMENT_GATEWAY_APPLE_PAY_MERCHANT_ID, PAYMENT_GATEWAY_SERVERLESS_DEPLOYMENT } = process.env || {}; + /* START GENAI */ + if (!isValidApplePayValidationUrl(fields.isv_applePayValidationUrl)) { + paymentUtils.logData(__filename, FunctionConstant.FUNC_HANDLE_APPLE_PAY_SESSION, Constants.LOG_ERROR, '', CustomMessages.ERROR_MSG_APPLE_PAY_INVALID_VALIDATION_URL); + return serviceResponse; + } + /* END GENAI */ if (PAYMENT_GATEWAY_APPLE_PAY_CERTIFICATE_PATH && PAYMENT_GATEWAY_APPLE_PAY_KEY_PATH && PAYMENT_GATEWAY_APPLE_PAY_DOMAIN_NAME && PAYMENT_GATEWAY_APPLE_PAY_MERCHANT_ID) { const certificateString = PAYMENT_GATEWAY_APPLE_PAY_CERTIFICATE_PATH; const keyString = PAYMENT_GATEWAY_APPLE_PAY_KEY_PATH; - if (Constants.STRING_AWS === PAYMENT_GATEWAY_SERVERLESS_DEPLOYMENT || Constants.STRING_AZURE === PAYMENT_GATEWAY_SERVERLESS_DEPLOYMENT) { + if (Constants.STRING_AWS === PAYMENT_GATEWAY_SERVERLESS_DEPLOYMENT || Constants.STRING_AZURE === PAYMENT_GATEWAY_SERVERLESS_DEPLOYMENT || Constants.STRING_GCP === PAYMENT_GATEWAY_SERVERLESS_DEPLOYMENT) { const certData = await paymentUtils.getCertificatesData(certificateString); const keyData = await paymentUtils.getCertificatesData(keyString); if (Constants.HTTP_OK_STATUS_CODE === certData?.status && certData.data && Constants.HTTP_OK_STATUS_CODE === keyData.status && keyData.data) { @@ -320,7 +383,7 @@ const handleUpdateCard = async (tokens: Partial, customerId: const isError = false; let finalTokenIndex = -1; let parsedTokens: Partial; - let addressData: _BaseAddress | null = null; + let addressData: any = null; let updateServiceResponse: any; if (customerId) { const customerInfo = await commercetoolsApi.getCustomer(customerId); @@ -351,7 +414,9 @@ const handleUpdateCard = async (tokens: Partial, customerId: parsedTokens = JSON.parse(existingTokens[finalTokenIndex]); parsedTokens.cardExpiryMonth = updateServiceResponse?.card.expirationMonth; parsedTokens.cardExpiryYear = updateServiceResponse?.card.expirationYear; - parsedTokens.addressId = tokens.addressId; + if (addressData?.id) { + parsedTokens.addressId = addressData.id; + } existingTokens[finalTokenIndex] = JSON.stringify(parsedTokens); returnResponse = paymentActions.getUpdateTokenActions(existingTokens, isv_failedTokens, isError, customerObj, null); } else { diff --git a/src/utils/PaymentUtils.ts b/src/utils/PaymentUtils.ts index 70409e6..d2244df 100644 --- a/src/utils/PaymentUtils.ts +++ b/src/utils/PaymentUtils.ts @@ -19,7 +19,7 @@ import { CustomMessages } from '../constants/customMessages'; import { FunctionConstant } from '../constants/functionConstant'; import { Constants } from '../constants/paymentConstants'; import { Token } from '../models/TokenModel'; -import { ActionType, AddressType, AmountPlannedType, CertificateResponseType, CustomerCustomType, CustomerTokensType, ErrorType, LoggerConfigType, PaymentCustomFieldsType, PaymentTransactionType } from '../types/Types'; +import { ActionResponseType, ActionType, AddressType, AmountPlannedType, CertificateResponseType, CustomerCustomType, CustomerTokensType, ErrorType, LoggerConfigType, PaymentCustomFieldsType, PaymentTransactionType } from '../types/Types'; import { errorHandler, PaymentProcessingError, SystemError, ValidationError } from './ErrorHandler'; import paymentValidator from './PaymentValidator'; @@ -43,6 +43,7 @@ const logData = (filePath: string, method: string, type: string, id: string, log let logger: winston.Logger; let fileName = path.parse(path.basename(filePath)).name; let newDate = getDate(Date.now(), true); + const sanitizedLogMessage = logMessage.replace(/[\r\n]/g, ' '); loggingFormat = printf(({ label, methodName, level, message }) => { return `[${newDate}] [${label}] [${methodName}] [${level.toUpperCase()}]` + (id ? ` [${id}]` : '') + (consolidatedTime ? ` [Execution Time: ${consolidatedTime}] Ms` : '') + ` : ${message}`; }); @@ -64,7 +65,7 @@ const logData = (filePath: string, method: string, type: string, id: string, log label: fileName, methodName: method, level: type, - message: logMessage, + message: sanitizedLogMessage, } as Partial; if (id) { loggerConfig.id = encodeURI(id); @@ -72,7 +73,7 @@ const logData = (filePath: string, method: string, type: string, id: string, log if (consolidatedTime) { loggerConfig.consolidatedTime = `${consolidatedTime} Ms` } - logger.log(loggerConfig as LoggerConfigType); + logger.log(sanitizeLogData(loggerConfig) as LoggerConfigType); } }; @@ -809,8 +810,8 @@ const setCertificatecache = async (url: string, keyPass: string, merchantId: str }; const setCache = (certificate: any, timeStamp: Date) => { - cache.put("certificateLastModifideTimeStamp", timeStamp); - cache.put("certificateFromP12File", certificate); + cache.put(Constants.CACHE_CERTIFICATE_LAST_MODIFIED_TIMESTAMP, timeStamp); + cache.put(Constants.CACHE_CERTIFICATE_FROM_P12_FILE, certificate); } const sanitize = (input: any) => { @@ -961,6 +962,32 @@ const getRequestPayload = async (req: any) => { } } +/** + * Validates and sanitizes an action response before sending to commercetools + * Ensures the response structure is valid and contains only expected fields + * + * @param response - The response object to validate + * @returns Validated response object + */ +const validateActionResponse = (response: ActionResponseType): ActionResponseType => { + // Ensure response is an object + if (!response || typeof response !== 'object') { + return { actions: [], errors: [] }; + } + + // Validate actions array + const validatedActions = Array.isArray(response.actions) ? response.actions : []; + + // Validate errors array + const validatedErrors = Array.isArray(response.errors) ? response.errors : []; + + // Return validated response with only expected fields + return { + actions: validatedActions, + errors: validatedErrors, + }; +} + export default { logData, @@ -1005,5 +1032,6 @@ export default { getApiPath, injectScripts, getSetLinkScript, - getRequestPayload + getRequestPayload, + validateActionResponse }; diff --git a/src/utils/api/CommercetoolsApi.ts b/src/utils/api/CommercetoolsApi.ts index 891696a..47b4713 100644 --- a/src/utils/api/CommercetoolsApi.ts +++ b/src/utils/api/CommercetoolsApi.ts @@ -26,6 +26,19 @@ const clientSecret = process.env.CT_CLIENT_SECRET || ''; const authHost = process.env.CT_AUTH_HOST || ''; const apiHost = process.env.CT_API_HOST || ''; +/* START GENAI */ +/** + * Sanitizes a value for safe use in Commercetools query predicates. + * Escapes backslash and double-quote characters to prevent predicate injection. + * + * @param {string} value - The value to sanitize. + * @returns {string} - The sanitized value safe for embedding in predicate strings. + */ +const sanitizePredicateValue = (value: string): string => { + return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); +}; +/* END GENAI */ + const getClient = async () => { let client: ByProjectKeyRequestBuilder | null = null; const httpMiddlewareOptions: HttpMiddlewareOptions = { @@ -96,7 +109,7 @@ const queryCartById = async (id: string, idType: string): Promise => { .carts() .get({ queryArgs: { - where: `${Constants.ANONYMOUS_ID}="${id}" AND ${Constants.ACTIVE_CART_STATE}`, + where: `${Constants.ANONYMOUS_ID}="${sanitizePredicateValue(id)}" AND ${Constants.ACTIVE_CART_STATE}`, sort: `${Constants.LAST_MODIFIED_AT} ${Constants.DESC_ORDER}`, }, }); @@ -107,7 +120,7 @@ const queryCartById = async (id: string, idType: string): Promise => { .carts() .get({ queryArgs: { - where: `${Constants.CUSTOMER_ID}="${id}" AND ${Constants.ACTIVE_CART_STATE}`, + where: `${Constants.CUSTOMER_ID}="${sanitizePredicateValue(id)}" AND ${Constants.ACTIVE_CART_STATE}`, sort: `${Constants.LAST_MODIFIED_AT} ${Constants.DESC_ORDER}`, }, }); @@ -118,7 +131,7 @@ const queryCartById = async (id: string, idType: string): Promise => { .carts() .get({ queryArgs: { - where: `paymentInfo(payments(id="${id}"))`, + where: `paymentInfo(payments(id="${sanitizePredicateValue(id)}"))`, }, }); logIdType = 'Payment Id: '; @@ -154,11 +167,11 @@ const queryOrderById = async (id: string, idType: string) => { if (id && idType && client) { switch (idType) { case Constants.CART_ID: - query = client.orders().get({ queryArgs: { where: [`cart(id="${id}")`] } }); + query = client.orders().get({ queryArgs: { where: [`cart(id="${sanitizePredicateValue(id)}")`] } }); logIdType = 'CartId : '; break; case Constants.PAYMENT_ID: - query = client.orders().get({ queryArgs: { where: [`paymentInfo(payments(id="${id}"))`] } }); + query = client.orders().get({ queryArgs: { where: [`paymentInfo(payments(id="${sanitizePredicateValue(id)}"))`] } }); logIdType = 'PaymentId : '; break; default: @@ -738,7 +751,7 @@ const retrieveCustomObjectByContainer = async (container: string) => { let getCustomObjectsResponse: any; const client = await getClient(); if (container && client) { - const query = client.customObjects().get({ queryArgs: { where: [`container="${container}"`] } }); + const query = client.customObjects().get({ queryArgs: { where: [`container="${sanitizePredicateValue(container)}"`] } }); const startTime = new Date().getTime(); getCustomObjectsResponse = await query.execute(); const endTime = new Date().getTime(); @@ -794,7 +807,7 @@ const retrieveCustomerByCustomField = async (customFieldName: string, customFiel let retrieveCustomerByCustomObjectResponse; const client = await getClient(); if (customFieldName && customFieldValue && client) { - const query = client.customers().get({ queryArgs: { where: `custom(fields(${customFieldName} = "${customFieldValue}"))` } }); + const query = client.customers().get({ queryArgs: { where: `custom(fields(${customFieldName} = "${sanitizePredicateValue(customFieldValue)}"))` } }); retrieveCustomerByCustomObjectResponse = await makeCommercetoolsRequest(query); paymentUtils.logData(__filename, FunctionConstant.FUNC_RETRIEVE_CUSTOMER_BY_CUSTOM_FIELD, Constants.LOG_INFO, '', '', `${retrieveCustomerByCustomObjectResponse.consolidatedTime} `); } diff --git a/src/utils/helpers/AuthenticationHelper.ts b/src/utils/helpers/AuthenticationHelper.ts index ac0f57a..5187e28 100644 --- a/src/utils/helpers/AuthenticationHelper.ts +++ b/src/utils/helpers/AuthenticationHelper.ts @@ -95,9 +95,11 @@ const authenticateNetToken = async (signature: any, notification: any): Promise< const decodedKey = Buffer.from(subscriptionData.key, Constants.ENCODING_BASE_SIXTY_FOUR); const hmac = crypto.createHmac(Constants.ENCODING_SHA_TWO_FIFTY_SIX, decodedKey); const generatedSignature = hmac.update(payload).digest(Constants.ENCODING_BASE_SIXTY_FOUR); - if (generatedSignature === sign) { + /* START GENAI */ + if (generatedSignature && sign && generatedSignature.length === sign.length && crypto.timingSafeEqual(Buffer.from(generatedSignature), Buffer.from(sign))) { isValidNotification = true; } + /* END GENAI */ } } } diff --git a/src/utils/helpers/OrderManagementHelper.ts b/src/utils/helpers/OrderManagementHelper.ts index 3bb843f..77992c8 100644 --- a/src/utils/helpers/OrderManagementHelper.ts +++ b/src/utils/helpers/OrderManagementHelper.ts @@ -56,11 +56,13 @@ const getCapturedAmount = (refundPaymentObj: Payment): number => { if (refundPaymentObj) { const fractionDigits = refundPaymentObj.amountPlanned.fractionDigits; refundTransaction = refundPaymentObj.transactions; - const indexValue = refundTransaction.findIndex((transaction, index) => { + const indexValue = refundTransaction.findIndex((transaction, _index) => { if (Constants.CT_TRANSACTION_TYPE_CHARGE === transaction.type) { return true; } - return index; + /* START GENAI */ + return false; + /* END GENAI */ }); if (0 <= indexValue) { for (let transaction of refundTransaction) { @@ -90,11 +92,13 @@ const getAuthorizedAmount = (capturePaymentObj: Payment): number => { if (capturePaymentObj) { const captureTransaction = capturePaymentObj.transactions; const fractionDigits = capturePaymentObj.amountPlanned.fractionDigits; - const indexValue = captureTransaction.findIndex((transaction: Transaction, index: number) => { + const indexValue = captureTransaction.findIndex((transaction: Transaction, _index: number) => { if (Constants.CT_TRANSACTION_TYPE_AUTHORIZATION === transaction.type) { return true; } - return index; + /* START GENAI */ + return false; + /* END GENAI */ }); if (0 <= indexValue) { const authorizedAmount = Number(captureTransaction[indexValue]?.amount?.centAmount); diff --git a/src/utils/helpers/SyncHelper.ts b/src/utils/helpers/SyncHelper.ts index 829d4be..d33a9df 100644 --- a/src/utils/helpers/SyncHelper.ts +++ b/src/utils/helpers/SyncHelper.ts @@ -351,9 +351,11 @@ const retrieveSyncAmountDetails = async (paymentDetails: Payment, element: any, * @returns {Promise} - The updated response. */ const runSyncUpdateCaptureAmount = async (updatePaymentObj: Payment | null, amount: number): Promise => { - if (!updatePaymentObj || 0 <= amount) { + /* START GENAI */ + if (!updatePaymentObj || 0 >= amount) { return null; } + /* END GENAI */ const { id: paymentId, version: initialPaymentVersion, transactions: updateTransactions } = updatePaymentObj || {}; let paymentVersion = initialPaymentVersion; let updateResponse: any; diff --git a/src/views/javascript/paymentDetails.js b/src/views/javascript/paymentDetails.js index e2e894c..569f1ee 100644 --- a/src/views/javascript/paymentDetails.js +++ b/src/views/javascript/paymentDetails.js @@ -1,4 +1,4 @@ -import { amountConversion, roundOff, getPaymentId, formatCurrency, createTableRow, createAndSetAttributes, validatePaymentId, validateAmountValue, sanitizeResponseData, getApiPath } from './utils.js'; +import { amountConversion, roundOff, getPaymentId, formatCurrency, createTableRow, createAndSetAttributes, validatePaymentId, sanitizeResponseData, getApiPath, validateAmountValue } from './utils.js'; if (window.location.pathname.includes('paymentDetails')) { document.addEventListener('DOMContentLoaded', async function () { @@ -78,12 +78,18 @@ if (window.location.pathname.includes('paymentDetails')) { buttonsDiv.classList.add('div-padding'); buttonsDiv.id = 'buttonsDiv'; - const authorizedAmount = validateAmountValue(paymentsData?.authorizedAmount); + const authorizedAmountValue = validateAmountValue(paymentsData?.authorizedAmount); + + const authorizedAmount = authorizedAmountValue > 0 ? String(authorizedAmountValue) : ''; + const captureAmount = validateAmountValue(paymentsData?.captureAmount); + if (authPresent && !authReversalPresent && (!refundPresent || (refundPresent && authorizedAmount)) && ((capturePresent && authorizedAmount) || (!capturePresent && authorizedAmount))) { const captureMsgDiv = document.createElement('div'); captureMsgDiv.classList.add('div-padding'); - captureMsgDiv.textContent = `You can capture amount ${authorizedAmount} `; + /* START GENAI */ + captureMsgDiv.textContent = 'Capture is available. Enter the amount to capture:'; + /* END GENAI */ const partialCaptureForm = document.createElement('form'); partialCaptureForm.action = getApiPath('capture'); partialCaptureForm.classList.add('div-padding'); @@ -105,7 +111,9 @@ if (window.location.pathname.includes('paymentDetails')) { if ((capturePresent && !authReversalPresent && refundPresent && captureAmount) || (!refundPresent && capturePresent)) { const refundMsgDiv = document.createElement('div'); refundMsgDiv.classList.add('div-padding'); - refundMsgDiv.textContent = `You can refund amount ${captureAmount}`; + /* START GENAI */ + refundMsgDiv.textContent = 'Refund is available. Enter the amount to refund:'; + /* END GENAI */ const refundForm = document.createElement('form'); refundForm.action = getApiPath('refund'); diff --git a/src/views/orders.html b/src/views/orders.html index 11c24f8..6ab8d34 100644 --- a/src/views/orders.html +++ b/src/views/orders.html @@ -10,15 +10,51 @@ display: none; } - diff --git a/src/views/paymentDetails.html b/src/views/paymentDetails.html index 62d67de..f9984d4 100644 --- a/src/views/paymentDetails.html +++ b/src/views/paymentDetails.html @@ -10,15 +10,51 @@ display: none; } -