- 
                Notifications
    You must be signed in to change notification settings 
- Fork 5.5k
[Components] fiserv - new components #14687
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,126 @@ | ||||||||||||||||||||||||||
| import app from "../../fiserv.app.mjs"; | ||||||||||||||||||||||||||
| import utils from "../../common/utils.mjs"; | ||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||
| export default { | ||||||||||||||||||||||||||
| key: "fiserv-create-checkout", | ||||||||||||||||||||||||||
| name: "Create Checkout", | ||||||||||||||||||||||||||
| description: "Initiate a payment request by passing all the required parameters. It creates a new payment transaction and returns the redirect URL that includes transaction ID. [See the documentation](https://docs.fiserv.dev/public/reference/postcheckouts).", | ||||||||||||||||||||||||||
| version: "0.0.1", | ||||||||||||||||||||||||||
| type: "action", | ||||||||||||||||||||||||||
| props: { | ||||||||||||||||||||||||||
| app, | ||||||||||||||||||||||||||
| storeId: { | ||||||||||||||||||||||||||
| type: "string", | ||||||||||||||||||||||||||
| label: "Store ID", | ||||||||||||||||||||||||||
| description: "Store id to be used for processing this payment. It also acts as an identifier for your store to load the checkout pages linked to it. If no checkout pages are found, default payment page will be rendered for that transaction.", | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| merchantTransactionId: { | ||||||||||||||||||||||||||
| type: "string", | ||||||||||||||||||||||||||
| label: "Merchant Transaction ID", | ||||||||||||||||||||||||||
| description: "You can use this parameter to tag a unique identifier to this transaction for future reference.", | ||||||||||||||||||||||||||
| optional: true, | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| transactionOrigin: { | ||||||||||||||||||||||||||
| type: "string", | ||||||||||||||||||||||||||
| label: "Transaction Origin", | ||||||||||||||||||||||||||
| description: "This parameter is used to flag the transaction source correctly. The possible values are `ECOM` (if the order was recieved from online shop), `MAIL` & `PHONE`.", | ||||||||||||||||||||||||||
| options: [ | ||||||||||||||||||||||||||
| "ECOM", | ||||||||||||||||||||||||||
| "MAIL", | ||||||||||||||||||||||||||
| "PHONE", | ||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| transactionType: { | ||||||||||||||||||||||||||
| type: "string", | ||||||||||||||||||||||||||
| label: "Transaction Type", | ||||||||||||||||||||||||||
| description: "You can use this parameter to specify the type of transaction you want to perform. Allowed values are: `SALE`, `PRE-AUTH`, `ZERO-AUTH`", | ||||||||||||||||||||||||||
| options: [ | ||||||||||||||||||||||||||
| "SALE", | ||||||||||||||||||||||||||
| "PRE-AUTH", | ||||||||||||||||||||||||||
| "ZERO-AUTH", | ||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| transactionAmount: { | ||||||||||||||||||||||||||
| type: "object", | ||||||||||||||||||||||||||
| label: "Transaction Amount", | ||||||||||||||||||||||||||
| description: "Object contains `total` transaction amount, `currency`, tax and discount details. Example: `{\"total\":123,\"currency\":\"EUR\",\"components\":{\"subtotal\":115,\"vat\":3,\"shipping\":2.5}}`", | ||||||||||||||||||||||||||
| optional: true, | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| order: { | ||||||||||||||||||||||||||
| type: "string", | ||||||||||||||||||||||||||
| label: "Order", | ||||||||||||||||||||||||||
| description: "Object contains order related details. [See the documentation](https://docs.fiserv.dev/public/reference/postcheckouts).", | ||||||||||||||||||||||||||
| optional: true, | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| 
      Comment on lines
    
      +49
     to 
      +54
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistent type definition for  The  Apply this diff:  order: {
-  type: "string",
+  type: "object",
   label: "Order",
   description: "Object contains order related details. [See the documentation](https://docs.fiserv.dev/public/reference/postcheckouts).",
   optional: true,
 },📝 Committable suggestion
 
        Suggested change
       
 | ||||||||||||||||||||||||||
| checkoutSettings: { | ||||||||||||||||||||||||||
| type: "string", | ||||||||||||||||||||||||||
| label: "Checkout Settings", | ||||||||||||||||||||||||||
| description: "Object contains checkout related settings. [See the documentation](https://docs.fiserv.dev/public/reference/postcheckouts).", | ||||||||||||||||||||||||||
| default: JSON.stringify({ | ||||||||||||||||||||||||||
| locale: "en_US", | ||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| paymentMethodDetails: { | ||||||||||||||||||||||||||
| type: "string", | ||||||||||||||||||||||||||
| label: "Payment Method Details", | ||||||||||||||||||||||||||
| description: "Object contains payment method related details. [See the documentation](https://docs.fiserv.dev/public/reference/postcheckouts).", | ||||||||||||||||||||||||||
| default: JSON.stringify({ | ||||||||||||||||||||||||||
| cards: { | ||||||||||||||||||||||||||
| authenticationPreferences: { | ||||||||||||||||||||||||||
| challengeIndicator: "01", | ||||||||||||||||||||||||||
| skipTra: false, | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| createToken: { | ||||||||||||||||||||||||||
| declineDuplicateToken: false, | ||||||||||||||||||||||||||
| reusable: true, | ||||||||||||||||||||||||||
| toBeUsedFor: "UNSCHEDULED", | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| tokenBasedTransaction: { | ||||||||||||||||||||||||||
| transactionSequence: "FIRST", | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| sepaDirectDebit: { | ||||||||||||||||||||||||||
| transactionSequenceType: "SINGLE", | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| methods: { | ||||||||||||||||||||||||||
| createCheckout(args = {}) { | ||||||||||||||||||||||||||
| return this.app.post({ | ||||||||||||||||||||||||||
| path: "/checkouts", | ||||||||||||||||||||||||||
| ...args, | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| async run({ $ }) { | ||||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||||
| createCheckout, | ||||||||||||||||||||||||||
| storeId, | ||||||||||||||||||||||||||
| merchantTransactionId, | ||||||||||||||||||||||||||
| transactionOrigin, | ||||||||||||||||||||||||||
| transactionType, | ||||||||||||||||||||||||||
| transactionAmount, | ||||||||||||||||||||||||||
| order, | ||||||||||||||||||||||||||
| checkoutSettings, | ||||||||||||||||||||||||||
| paymentMethodDetails, | ||||||||||||||||||||||||||
| } = this; | ||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||
| const response = await createCheckout({ | ||||||||||||||||||||||||||
| $, | ||||||||||||||||||||||||||
| data: { | ||||||||||||||||||||||||||
| storeId, | ||||||||||||||||||||||||||
| merchantTransactionId, | ||||||||||||||||||||||||||
| transactionOrigin, | ||||||||||||||||||||||||||
| transactionType, | ||||||||||||||||||||||||||
| transactionAmount: utils.parseJson(transactionAmount), | ||||||||||||||||||||||||||
| order: utils.parseJson(order), | ||||||||||||||||||||||||||
| checkoutSettings: utils.parseJson(checkoutSettings), | ||||||||||||||||||||||||||
| paymentMethodDetails: utils.parseJson(paymentMethodDetails), | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
| 
      Comment on lines
    
      +109
     to 
      +121
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add response validation to ensure required fields are present. The Fiserv API response should be validated to ensure it contains the expected fields before using them. Add validation before using the response:  const response = await createCheckout({
   $,
   data: {
     storeId,
     merchantTransactionId,
     transactionOrigin,
     transactionType,
     transactionAmount: utils.parseJson(transactionAmount),
     order: utils.parseJson(order),
     checkoutSettings: utils.parseJson(checkoutSettings),
     paymentMethodDetails: utils.parseJson(paymentMethodDetails),
   },
 });
+
+if (!response?.redirectionUrl) {
+  throw new Error('Invalid response: missing redirectionUrl');
+}
 | ||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||
| $.export("$summary", `Successfully created checkout. Redirect URL: ${response.redirectionUrl}`); | ||||||||||||||||||||||||||
| return response; | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| 
      Comment on lines
    
      +96
     to 
      +125
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Ensure proper error handling for JSON parsing and API requests. When parsing JSON inputs ( Consider wrapping the parsing calls with try-catch blocks or using a safe parsing method that returns meaningful errors if parsing fails. | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,42 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import app from "../../fiserv.app.mjs"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| key: "fiserv-retrieve-checkout-details", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: "Retrieve Checkout Details", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: "Retrieve details about a specific checkout using the identifier returned when it was created. [See the documentation](https://docs.fiserv.dev/public/reference/get-checkouts-id).", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| version: "0.0.1", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: "action", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| props: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| app, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkoutId: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: "string", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| label: "Checkout ID", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: "The unique identifier for the checkout.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| optional: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| methods: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getCheckoutDetails({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkoutId, ...args | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } = {}) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return this.app._makeRequest({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path: `/checkouts/${checkoutId}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...args, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 
      Comment on lines
    
      +18
     to 
      +27
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add input validation and error handling The current implementation could be more robust. Consider these improvements: 
  methods: {
   getCheckoutDetails({
     checkoutId, ...args
   } = {}) {
+    if (!checkoutId || typeof checkoutId !== 'string') {
+      throw new Error('Invalid checkoutId provided');
+    }
+    const allowedParams = ['$'];
+    const invalidParams = Object.keys(args).filter(key => !allowedParams.includes(key));
+    if (invalidParams.length > 0) {
+      throw new Error(`Invalid parameters provided: ${invalidParams.join(', ')}`);
+    }
     return this.app._makeRequest({
       path: `/checkouts/${checkoutId}`,
-      ...args,
+      $: args.$,
     });
   },
 },📝 Committable suggestion
 
        Suggested change
       
 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async run({ $ }) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getCheckoutDetails, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkoutId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } = this; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const response = await getCheckoutDetails({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkoutId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $.export("$summary", `Successfully retrieved details for checkout ID ${this.checkoutId}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return response; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 
      Comment on lines
    
      +28
     to 
      +41
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling and fix inconsistent property access The run function needs several improvements: 
  async run({ $ }) {
   const {
     getCheckoutDetails,
     checkoutId,
   } = this;
+  try {
     const response = await getCheckoutDetails({
       $,
       checkoutId,
     });
 
-    $.export("$summary", `Successfully retrieved details for checkout ID ${this.checkoutId}`);
+    if (!response || typeof response !== 'object') {
+      throw new Error('Invalid response received from API');
+    }
+
+    $.export("$summary", `Successfully retrieved details for checkout ID ${checkoutId}`);
     return response;
+  } catch (error) {
+    throw new Error(`Failed to retrieve checkout details: ${error.message}`);
+  }
 },📝 Committable suggestion
 
        Suggested change
       
 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| const ENVIRONMENT = { | ||
| SANDBOX: "sandbox", | ||
| PRODUCTION: "production", | ||
| }; | ||
|  | ||
| const SANDBOX_PATH = "/sandbox"; | ||
|  | ||
| const API_PATH = { | ||
| DEFAULT: "/exp/v1", | ||
| PAYMENTS: "/ipp/payments-gateway/v2", | ||
| FRAUD: "/ipp/fraud/v1", | ||
| }; | ||
|  | ||
| export default { | ||
| ENVIRONMENT, | ||
| SANDBOX_PATH, | ||
| API_PATH, | ||
| }; | 
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,26 @@ | ||||||||||||||||||||||||||||||||||||||||
| const parseJson = (input) => { | ||||||||||||||||||||||||||||||||||||||||
| const parse = (value) => { | ||||||||||||||||||||||||||||||||||||||||
| if (typeof(value) === "string") { | ||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||
| return parseJson(JSON.parse(value)); | ||||||||||||||||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||||||||||||||||
| return value; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } else if (typeof(value) === "object" && value !== null) { | ||||||||||||||||||||||||||||||||||||||||
| 
      Comment on lines
    
      +3
     to 
      +9
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add safety measures to prevent recursion-related issues. The current implementation has potential security and stability issues: 
 Consider implementing these safety measures: +const MAX_DEPTH = 100; // Prevent excessive recursion
-const parse = (value) => {
+const parse = (value, depth = 0) => {
+  if (depth > MAX_DEPTH) {
+    throw new Error('Maximum parsing depth exceeded');
+  }
   if (typeof(value) === "string") {
     try {
-      return parseJson(JSON.parse(value));
+      return parse(JSON.parse(value), depth + 1);
     } catch (e) {
+      // Log parsing errors in development
+      if (process.env.NODE_ENV === 'development') {
+        console.warn('JSON parsing failed:', e.message);
+      }
       return value;
     }
   }📝 Committable suggestion
 
        Suggested change
       
 | ||||||||||||||||||||||||||||||||||||||||
| return Object.entries(value) | ||||||||||||||||||||||||||||||||||||||||
| .reduce((acc, [ | ||||||||||||||||||||||||||||||||||||||||
| key, | ||||||||||||||||||||||||||||||||||||||||
| val, | ||||||||||||||||||||||||||||||||||||||||
| ]) => Object.assign(acc, { | ||||||||||||||||||||||||||||||||||||||||
| [key]: parse(val), | ||||||||||||||||||||||||||||||||||||||||
| }), {}); | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| 
      Comment on lines
    
      +9
     to 
      +17
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve object handling robustness and efficiency. The current implementation has several areas for improvement: 
 Consider this enhanced implementation: -} else if (typeof(value) === "object" && value !== null) {
+} else if (value && typeof(value) === "object") {
+  // Handle circular references
+  if (seen.has(value)) {
+    throw new Error('Circular reference detected');
+  }
+  seen.add(value);
+
+  // Handle arrays
+  if (Array.isArray(value)) {
+    return value.map(item => parse(item, depth + 1));
+  }
+
+  // Handle objects more efficiently
+  const result = {};
+  for (const [key, val] of Object.entries(value)) {
+    result[key] = parse(val, depth + 1);
+  }
+  seen.delete(value);
+  return result;
-  return Object.entries(value)
-    .reduce((acc, [
-      key,
-      val,
-    ]) => Object.assign(acc, {
-      [key]: parse(val),
-    }), {});
 | ||||||||||||||||||||||||||||||||||||||||
| return value; | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||
| return parse(input); | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||
| export default { | ||||||||||||||||||||||||||||||||||||||||
| parseJson, | ||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,11 +1,93 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { v4 as uuid } from "uuid"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import crypto from "crypto"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { axios } from "@pipedream/platform"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import constants from "./common/constants.mjs"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: "app", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| app: "fiserv", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| propDefinitions: {}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| methods: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // this.$auth contains connected account data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| authKeys() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(Object.keys(this.$auth)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getAuth() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| url, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| api_key: apiKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| secret_key: secretKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| environment = constants.ENVIRONMENT.SANDBOX, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } = this.$auth; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| url, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| apiKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| secretKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| environment, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 
      Comment on lines
    
      +10
     to 
      +23
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add validation for required authentication properties. While the method correctly extracts auth properties, it should validate that required properties ( Consider adding validation:  getAuth() {
   const {
     url,
     api_key: apiKey,
     secret_key: secretKey,
     environment = constants.ENVIRONMENT.SANDBOX,
   } = this.$auth;
+  if (!url || !apiKey || !secretKey) {
+    throw new Error('Missing required authentication properties: url, api_key, and secret_key must be provided');
+  }
   return {
     url,
     apiKey,
     secretKey,
     environment,
   };
 },📝 Committable suggestion
 
        Suggested change
       
 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getUrl(path, apiPath = constants.API_PATH.DEFAULT) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| url, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| environment, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } = this.getAuth(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const baseUrl = environment === constants.ENVIRONMENT.SANDBOX | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? `${url}${constants.SANDBOX_PATH}${apiPath}` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : `${url}${apiPath}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return `${baseUrl}${path}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Example at https://docs.fiserv.dev/public/docs/message-signature#example-of-code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getSignatureHeaders(data) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| apiKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| secretKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| environment, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } = this.getAuth(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (environment === constants.ENVIRONMENT.SANDBOX) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const clientRequestId = uuid(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const timestamp = Date.now().toString(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const requestBody = JSON.stringify(data) || ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const rawSignature = apiKey + clientRequestId + timestamp + requestBody; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const computedHmac = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| crypto.createHmac("sha256", secretKey) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .update(rawSignature) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .digest("base64"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Client-Request-Id": clientRequestId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Message-Signature": computedHmac, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Timestamp": timestamp, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 
      Comment on lines
    
      +37
     to 
      +63
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure  In the  Apply this diff to fix the issue:           if (environment === constants.ENVIRONMENT.SANDBOX) {
-            return;
+            return {};
          }📝 Committable suggestion
 
        Suggested change
       
 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| getHeaders(headers) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...headers, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Content-Type": "application/json", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Accept": "application/json", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "API-Key": this.$auth.api_key, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _makeRequest({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $ = this, path, headers, data, apiPath, ...args | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } = {}) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return axios($, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...args, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| debug: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| url: this.getUrl(path, apiPath), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...this.getHeaders(headers), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...this.getSignatureHeaders(data), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| post(args = {}) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return this._makeRequest({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| method: "POST", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...args, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
| "name": "@pipedream/fiserv", | ||||
| "version": "0.0.1", | ||||
| "version": "0.1.0", | ||||
| "description": "Pipedream Fiserv Components", | ||||
| "main": "fiserv.app.mjs", | ||||
| "keywords": [ | ||||
|  | @@ -11,5 +11,10 @@ | |||
| "author": "Pipedream <[email protected]> (https://pipedream.com/)", | ||||
| "publishConfig": { | ||||
| "access": "public" | ||||
| }, | ||||
| "dependencies": { | ||||
| "@pipedream/platform": "3.0.3", | ||||
| "crypto": "^1.0.1", | ||||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unnecessary  The  Apply this diff to remove the unnecessary dependency:   "dependencies": {
    "@pipedream/platform": "3.0.3",
-   "crypto": "^1.0.1",
    "uuid": "^11.0.3"
  }📝 Committable suggestion
 
        Suggested change
       
 | ||||
| "uuid": "^11.0.3" | ||||
| } | ||||
| } | ||||
| } | ||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent handling of 'transactionAmount' prop type and unnecessary JSON parsing.
The
transactionAmountprop is declared as typeobject, but in therunmethod (line 116), it is parsed usingutils.parseJson(transactionAmount). SincetransactionAmountis already an object, parsing it as JSON is unnecessary and may cause errors if the object is not serializable. Consider either changing the prop type tostringif you expect JSON input as a string, or removing the JSON parsing if an object is expected.If you expect
transactionAmountto be an object, apply this diff:Alternatively, if you expect input as a JSON string, change the prop type to
string: