diff --git a/.version b/.version
index b1bc230b93..4023a07f73 100644
--- a/.version
+++ b/.version
@@ -1 +1 @@
-3.20.48-lts
+3.20.49-lts
diff --git a/frontend/.version b/frontend/.version
index b1bc230b93..4023a07f73 100644
--- a/frontend/.version
+++ b/frontend/.version
@@ -1 +1 @@
-3.20.48-lts
+3.20.49-lts
diff --git a/marketplace/plugins/authorizenet/.gitignore b/marketplace/plugins/authorizenet/.gitignore
new file mode 100644
index 0000000000..23e6609462
--- /dev/null
+++ b/marketplace/plugins/authorizenet/.gitignore
@@ -0,0 +1,5 @@
+node_modules
+lib/*.d.*
+lib/*.js
+lib/*.js.map
+dist/*
\ No newline at end of file
diff --git a/marketplace/plugins/authorizenet/README.md b/marketplace/plugins/authorizenet/README.md
new file mode 100644
index 0000000000..079272d987
--- /dev/null
+++ b/marketplace/plugins/authorizenet/README.md
@@ -0,0 +1,4 @@
+
+# Authorize.Net
+
+Documentation on: https://docs.tooljet.com/docs/data-sources/authorizenet
\ No newline at end of file
diff --git a/marketplace/plugins/authorizenet/__tests__/index.js b/marketplace/plugins/authorizenet/__tests__/index.js
new file mode 100644
index 0000000000..2b11716ca4
--- /dev/null
+++ b/marketplace/plugins/authorizenet/__tests__/index.js
@@ -0,0 +1,7 @@
+'use strict';
+
+const authorizenet = require('../lib');
+
+describe('authorizenet', () => {
+ it.todo('needs tests');
+});
diff --git a/marketplace/plugins/authorizenet/lib/icon.svg b/marketplace/plugins/authorizenet/lib/icon.svg
new file mode 100644
index 0000000000..db3d64cf69
--- /dev/null
+++ b/marketplace/plugins/authorizenet/lib/icon.svg
@@ -0,0 +1,6 @@
+
diff --git a/marketplace/plugins/authorizenet/lib/index.ts b/marketplace/plugins/authorizenet/lib/index.ts
new file mode 100644
index 0000000000..091014670f
--- /dev/null
+++ b/marketplace/plugins/authorizenet/lib/index.ts
@@ -0,0 +1,126 @@
+import { QueryError, QueryResult, QueryService, ConnectionTestResult } from '@tooljet-marketplace/common';
+import { SourceOptions, QueryOptions } from './types';
+import ApiContracts from 'authorizenet/lib/apicontracts';
+import ApiControllers from 'authorizenet/lib/apicontrollers';
+import * as operations from './query_operations';
+
+export default class Authorizenet implements QueryService {
+
+ async testConnection(sourceOptions: SourceOptions): Promise {
+ try {
+ const merchantAuth = operations.getMerchantAuth(sourceOptions);
+ const getRequest = new ApiContracts.GetMerchantDetailsRequest();
+ getRequest.setMerchantAuthentication(merchantAuth);
+
+ const ctrl = new ApiControllers.GetMerchantDetailsController(getRequest.getJSON());
+ ctrl.setEnvironment(operations.getEnvironment(sourceOptions.environment));
+ return new Promise((resolve, reject) => {
+ ctrl.execute(() => {
+ const apiResponse = ctrl.getResponse();
+ const response = new ApiContracts.GetMerchantDetailsResponse(apiResponse);
+
+ if (response.getMessages().getResultCode() === ApiContracts.MessageTypeEnum.OK) {
+ resolve({
+ status: 'ok',
+ });
+ } else {
+ const errorMessage = response.getMessages().getMessage()[0].getText();
+ reject(
+ new QueryError(errorMessage, errorMessage, {
+ code: response.getMessages().getMessage()[0].getCode(),
+ message: errorMessage,
+ })
+ );
+ }
+ });
+ });
+ } catch (error: any) {
+ throw new QueryError('Connection test failed', error.message, {
+ message: error.message,
+ name: error.name,
+ });
+ }
+ }
+
+ async run(sourceOptions: SourceOptions, queryOptions: QueryOptions, dataSourceId: string): Promise {
+ const { operation } = queryOptions;
+
+ if (!operation) {
+ throw new QueryError('Invalid configuration', 'Operation is required', {
+ message: 'Operation parameter is missing',
+ });
+ }
+ try {
+ let result: any;
+
+ switch (operation) {
+ case 'charge_credit_card':
+ result = await operations.chargeCreditCard(sourceOptions, queryOptions);
+ break;
+ case 'authorize_credit_card':
+ result = await operations.authorizeCreditCard(sourceOptions, queryOptions);
+ break;
+ case 'capture_authorized_amount':
+ result = await operations.captureAuthorizedAmount(sourceOptions, queryOptions);
+ break;
+ case 'refund_transaction':
+ result = await operations.refundTransaction(sourceOptions, queryOptions);
+ break;
+ case 'void_transaction':
+ result = await operations.voidTransaction(sourceOptions, queryOptions);
+ break;
+ case 'charge_customer_profile':
+ result = await operations.chargeCustomerProfile(sourceOptions, queryOptions);
+ break;
+ case 'create_customer_pofile':
+ result = await operations.createCustomerProfile(sourceOptions,queryOptions);
+ break;
+ case 'get_customer_profile':
+ result = await operations.getCustomerProfile(sourceOptions,queryOptions);
+ break;
+ case 'get_customer_profileIds':
+ result = await operations.getCustomerProfileIds(sourceOptions,queryOptions);
+ break;
+ case 'update_customer_profile':
+ result = await operations.updateCustomerProfile(sourceOptions,queryOptions);
+ break;
+ case 'delete_customer_profile':
+ result = await operations.deleteCustomerProfile(sourceOptions,queryOptions);
+ break;
+ case 'create_customer_payment_profile':
+ result = await operations.createCustomerPaymentProfile(sourceOptions,queryOptions);
+ break;
+ case 'get_customer_payment_profile':
+ result = await operations.getCustomerPaymentProfile(sourceOptions,queryOptions);
+ break;
+ case 'validate_customer_payment_profile':
+ result = await operations.validateCustomerPaymentProfile(sourceOptions,queryOptions);
+ break;
+ case 'update_customer_payment_profile':
+ result = await operations.updateCustomerPaymentProfile(sourceOptions,queryOptions);
+ break;
+ case 'delete_customer_payment_profile':
+ result = await operations.deleteCustomerPaymentProfile(sourceOptions,queryOptions);
+ break;
+ case 'create_customer_profile_from_transaction':
+ result = await operations.createCustomerProfileFromTransaction(sourceOptions,queryOptions);
+ break;
+ default:
+ throw new QueryError('Invalid operation', `Operation '${operation}' is not supported`, {
+ operation,
+ });
+ }
+
+ return {
+ status: 'ok',
+ data: result,
+ };
+ } catch (error: any) {
+ throw new QueryError('Operation failed', error.data.message, {
+ name : error.name,
+ code : error.data.code,
+ message : error.data.message
+ });
+ }
+ }
+}
diff --git a/marketplace/plugins/authorizenet/lib/manifest.json b/marketplace/plugins/authorizenet/lib/manifest.json
new file mode 100644
index 0000000000..aa271c92a5
--- /dev/null
+++ b/marketplace/plugins/authorizenet/lib/manifest.json
@@ -0,0 +1,64 @@
+{
+ "$schema": "https://raw.githubusercontent.com/ToolJet/ToolJet/develop/plugins/schemas/manifest.schema.json",
+ "title": "Authorize.Net datasource",
+ "description": "A schema defining Authorize.Net datasource",
+ "type": "api",
+ "source": {
+ "name": "Authorize.Net",
+ "kind": "authorizenet",
+ "exposedVariables": {
+ "isLoading": false,
+ "data": {},
+ "rawData": {}
+ },
+ "options": {
+ "apiLoginId": {
+ "type": "string"
+ },
+ "transactionKey": {
+ "type": "string",
+ "encrypted": true
+ },
+ "environment": {
+ "type": "string"
+ }
+ }
+ },
+ "defaults": {
+ "environment": {
+ "value": "sandbox"
+ }
+ },
+ "properties": {
+ "apiLoginId": {
+ "label": "API login ID",
+ "key": "apiLoginId",
+ "type": "text",
+ "description": "Your Authorize.Net API login ID"
+ },
+ "transactionKey": {
+ "label": "Transaction key",
+ "key": "transactionKey",
+ "type": "text",
+ "description": "Your Authorize.Net transaction key",
+ "encrypted": true
+ },
+ "environment": {
+ "label": "Environment",
+ "key": "environment",
+ "type": "dropdown",
+ "description": "Select the API environment",
+ "list": [
+ {
+ "label": "Sandbox [https://apitest.authorize.net]",
+ "value": "sandbox"
+ },
+ {
+ "label": "Production [https://api.authorize.net]",
+ "value": "production"
+ }
+ ]
+ }
+ },
+ "required": ["apiLoginId", "transactionKey"]
+}
\ No newline at end of file
diff --git a/marketplace/plugins/authorizenet/lib/operations.json b/marketplace/plugins/authorizenet/lib/operations.json
new file mode 100644
index 0000000000..0e1d3a8ad4
--- /dev/null
+++ b/marketplace/plugins/authorizenet/lib/operations.json
@@ -0,0 +1,238 @@
+{
+ "$schema": "https://raw.githubusercontent.com/ToolJet/ToolJet/develop/plugins/schemas/operations.schema.json",
+ "title": "Authorize.Net datasource",
+ "description": "A schema defining Authorize.Net datasource",
+ "type": "api",
+ "defaults": {
+ "operation": "chargeCreditCard"
+ },
+ "properties": {
+ "operation": {
+ "label": "Operation",
+ "key": "operation",
+ "type": "dropdown-component-flip",
+ "description": "Select an operation",
+ "list": [
+ { "value": "charge_credit_card", "name": "Charge a Credit Card" },
+ { "value": "authorize_credit_card", "name": "Authorize a Credit Card" },
+ { "value": "capture_authorized_amount", "name": "Capture a Previously Authorized Amount" },
+ { "value": "refund_transaction", "name": "Refund a Transaction" },
+ { "value": "void_transaction", "name": "Void a Transaction" },
+ { "value": "charge_customer_profile", "name": "Charge a Customer Profile" },
+ { "value": "create_customer_pofile", "name": "Create a Customer Profile" },
+ { "value": "get_customer_profile", "name": "Get Customer Profile" },
+ { "value": "get_customer_profileIds", "name": "Get Customer Profile IDs" },
+ { "value": "update_customer_profile", "name": "Update Customer Profile" },
+ { "value": "delete_customer_profile", "name": "Delete Customer Profile" },
+ { "value": "create_customer_payment_profile", "name": "Create Customer Payment Profile" },
+ { "value": "get_customer_payment_profile", "name": "Get Customer Payment Profile" },
+ { "value": "validate_customer_payment_profile", "name": "Validate Customer Payment Profile" },
+ { "value": "update_customer_payment_profile", "name": "Update Customer Payment Profile" },
+ { "value": "delete_customer_payment_profile", "name": "Delete Customer Payment Profile" },
+ { "value": "create_customer_profile_from_transaction", "name": "Create Customer Profile from Transaction" }
+ ]
+ },
+ "charge_credit_card": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for charging a credit card",
+ "placeholder": "{\n \"amount\": \"5.00\",\n \"cardNumber\": \"4111111111111111\",\n \"expirationDate\": \"2025-12\",\n \"cardCode\": \"123\",\n \"refId\": \"123456\",\n \"lineItems\": {\n \"lineItem\": [\n {\n \"itemId\": \"1\",\n \"name\": \"Product Name\",\n \"description\": \"Product Description\",\n \"quantity\": \"1\",\n \"unitPrice\": \"5.00\"\n }\n ]\n },\n \"tax\": {\n \"amount\": \"0.50\",\n \"name\": \"Sales Tax\",\n \"description\": \"State Tax\"\n },\n \"billTo\": {\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"address\": \"123 Main St\",\n \"city\": \"Seattle\",\n \"state\": \"WA\",\n \"zip\": \"98101\",\n \"country\": \"US\"\n }\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Required: amount, cardNumber, expirationDate. Optional: cardCode (CVV), refId (max 20 chars), lineItems, tax, duty, shipping, poNumber, customer, billTo, shipTo, customerIP, transactionSettings, userFields, processingOptions, subsequentAuthInformation, authorizationIndicatorType. See Authorize.Net documentation for complete field specifications."
+ }
+ },
+ "authorize_credit_card": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for authorizing a credit card",
+ "placeholder": "{\n \"amount\": \"5.00\",\n \"cardNumber\": \"4111111111111111\",\n \"expirationDate\": \"2025-12\",\n \"cardCode\": \"123\",\n \"refId\": \"123456\",\n \"lineItems\": {\n \"lineItem\": [\n {\n \"itemId\": \"1\",\n \"name\": \"Product Name\",\n \"description\": \"Product Description\",\n \"quantity\": \"1\",\n \"unitPrice\": \"5.00\"\n }\n ]\n },\n \"tax\": {\n \"amount\": \"0.50\",\n \"name\": \"Sales Tax\",\n \"description\": \"State Tax\"\n },\n \"billTo\": {\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"address\": \"123 Main St\",\n \"city\": \"Seattle\",\n \"state\": \"WA\",\n \"zip\": \"98101\",\n \"country\": \"US\"\n }\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Required: amount, cardNumber, expirationDate. Optional: cardCode (CVV), refId (max 20 chars), lineItems, tax, duty, shipping, poNumber, customer, billTo, shipTo, customerIP, userFields, processingOptions, subsequentAuthInformation, authorizationIndicatorType. See Authorize.Net documentation for complete field specifications."
+ }
+ },
+ "capture_authorized_amount": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for capturing a previously authorized amount",
+ "placeholder": "{\n \"refTransId\": \"1234567890\",\n \"amount\": \"5.00\",\n \"refId\": \"123456\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Required: refTransId (original authorization transaction ID), amount (must be <= authorized amount). Optional: refId (max 20 chars for reference tracking). See Authorize.Net documentation for complete request format."
+ }
+ },
+ "refund_transaction": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for refunding a transaction",
+ "placeholder": "{\n \"transId\": \"80048625878\",\n \"amount\": \"1.00\",\n \"cardNumber\": \"0015\",\n \"expirationDate\": \"XXXX\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Provide the refund details as JSON. See Authorize.Net documentation for complete request format."
+ }
+ },
+ "void_transaction": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for voiding a transaction",
+ "placeholder": "{\n \"transId\": \"12345678\",\n \"refId\": \"optional-ref-123\",\n \"terminalNumber\": \"optional-terminal\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Required: transId (transaction ID to void). Optional: refId (your reference ID, max 20 chars), terminalNumber (in-store terminal identifier)."
+ }
+ },
+ "charge_customer_profile": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for charging a customer profile",
+ "placeholder": "{\n \"customerProfileId\": \"40338125\",\n \"customerPaymentProfileId\": \"1000177237\",\n \"amount\": \"45.00\",\n \"refId\": \"123456\",\n \"lineItems\": {\n \"lineItem\": [\n {\n \"itemId\": \"1\",\n \"name\": \"vase\",\n \"description\": \"Cannes logo\",\n \"quantity\": \"18\",\n \"unitPrice\": \"45.00\"\n }\n ]\n }\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Required: customerProfileId, customerPaymentProfileId (or use nested profile structure), amount. Optional: refId (max 20 chars), lineItems, tax, duty, shipping, poNumber, customer, billTo, shipTo, customerIP, processingOptions, subsequentAuthInformation, authorizationIndicatorType. See Authorize.Net documentation for complete request format."
+ }
+ },
+ "create_customer_pofile": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for creating a customer profile",
+ "placeholder": "{\n \"email\": \"customer@example.com\",\n \"description\": \"Customer Name\",\n \"merchantCustomerId\": \"12345\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Provide the customer profile details as JSON. See Authorize.Net documentation for complete request format."
+ }
+ },
+ "get_customer_profile": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for getting a customer profile",
+ "placeholder": "{\n \"customerProfileId\": \"123456\",\n \"refId\": \"ref123\",\n \"includeIssuerInfo\": true\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Provide customer profile retrieval parameters as JSON.\n\nParameters:\n• customerProfileId (required): Payment gateway-assigned ID\n• refId (optional): Merchant reference ID (up to 20 chars)\n• merchantCustomerId (optional): Merchant customer ID (up to 20 chars)\n• email (optional): Customer email (up to 255 chars)\n• unmaskExpirationDate (optional): Return unmasked expiration date (boolean)\n• includeIssuerInfo (optional): Include issuer number (IIN) in response (boolean)\n\nSee Authorize.Net documentation for complete details."
+ }
+ },
+ "get_customer_profileIds": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for getting customer profile IDs (optional)",
+ "placeholder": "{}",
+ "height": "300px",
+ "mandatory": false,
+ "tooltip": "Optionally provide parameters as JSON. See Authorize.Net documentation for complete request format."
+ }
+ },
+ "update_customer_profile": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for updating a customer profile",
+ "placeholder": "{\n \"customerProfileId\": \"123456\",\n \"email\": \"newemail@example.com\",\n \"description\": \"Updated Name\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Provide the updated customer profile details as JSON. See Authorize.Net documentation for complete request format."
+ }
+ },
+ "delete_customer_profile": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for deleting a customer profile",
+ "placeholder": "{\n \"customerProfileId\": \"123456\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Provide the customer profile ID as JSON. See Authorize.Net documentation for complete request format."
+ }
+ },
+ "create_customer_payment_profile": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for creating a customer payment profile",
+ "placeholder": "{\n \"customerProfileId\": \"123456\",\n \"cardNumber\": \"4111111111111111\",\n \"expirationDate\": \"2025-12\",\n \"cardCode\": \"123\",\n \"billTo\": {\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"address\": \"123 Main St\",\n \"city\": \"Bellevue\",\n \"state\": \"WA\",\n \"zip\": \"98004\",\n \"country\": \"US\",\n \"phoneNumber\": \"000-000-0000\"\n },\n \"defaultPaymentProfile\": false,\n \"validationMode\": \"liveMode\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Required: customerProfileId, cardNumber, expirationDate. Optional: cardCode, billTo (firstName, lastName, company, address, city, state, zip, country, phoneNumber, faxNumber), defaultPaymentProfile (boolean), validationMode ('liveMode' or 'testMode'), refId (max 20 chars). See Authorize.Net documentation for complete request format."
+ }
+ },
+ "get_customer_payment_profile": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for getting a customer payment profile",
+ "placeholder": "{\n \"customerProfileId\": \"10000\",\n \"customerPaymentProfileId\": \"20000\",\n \"includeIssuerInfo\": \"true\",\n \"refId\": \"get-payment-001\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Required: customerProfileId, customerPaymentProfileId. Optional: includeIssuerInfo (string 'true' or 'false' to include issuer information in response), refId (max 20 chars for reference tracking). See Authorize.Net documentation for complete request format." }
+ },
+ "validate_customer_payment_profile": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for validating a customer payment profile",
+ "placeholder": "{\n \"customerProfileId\": \"123456\",\n \"customerPaymentProfileId\": \"234567\",\n \"validationMode\": \"testMode\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Provide the validation details as JSON. See Authorize.Net documentation for complete request format."
+ }
+ },
+ "update_customer_payment_profile": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for updating a customer payment profile",
+ "placeholder": "{\n \"customerProfileId\": \"10000\",\n \"customerPaymentProfileId\": \"20000\",\n \"cardNumber\": \"4111111111111111\",\n \"expirationDate\": \"2026-01\",\n \"billTo\": {\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"address\": \"123 Main St.\",\n \"city\": \"Bellevue\",\n \"state\": \"WA\",\n \"zip\": \"98004\",\n \"country\": \"US\",\n \"phoneNumber\": \"000-000-0000\"\n },\n \"defaultPaymentProfile\": false,\n \"validationMode\": \"liveMode\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Required: customerProfileId, customerPaymentProfileId, cardNumber, expirationDate. Optional: cardCode, billTo (firstName, lastName, company, address, city, state, zip, country, phoneNumber, faxNumber), defaultPaymentProfile (boolean), validationMode ('liveMode' or 'testMode'), refId (max 20 chars). See Authorize.Net documentation for complete request format."
+ }
+ },
+ "delete_customer_payment_profile": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for deleting a customer payment profile",
+ "placeholder": "{\n \"customerProfileId\": \"123456\",\n \"customerPaymentProfileId\": \"234567\",\n \"refId\": \"delete-payment-001\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Required: customerProfileId (customer profile ID), customerPaymentProfileId (payment profile ID to delete). Optional: refId (max 20 chars for reference tracking). See Authorize.Net documentation for complete request format."
+ }
+ },
+ "create_customer_profile_from_transaction": {
+ "requestBody": {
+ "label": "Request body",
+ "key": "requestBody",
+ "type": "codehinter",
+ "description": "JSON request body for creating a customer profile from a transaction",
+ "placeholder": "{\n \"transId\": \"1234567890\",\n \"customer\": {\n \"merchantCustomerId\": \"CUST123\",\n \"description\": \"Customer description\",\n \"email\": \"customer@example.com\"\n },\n \"profileType\": \"regular\",\n \"refId\": \"create-profile-001\"\n}",
+ "height": "300px",
+ "mandatory": true,
+ "tooltip": "Required: transId (transaction ID from successful transaction). At least one of the following must be provided in customer object: merchantCustomerId (max 20 chars), description (max 255 chars), or email (max 255 chars). Optional: profileType ('guest' or 'regular', defaults to 'regular'), refId (max 20 chars). See Authorize.Net documentation for complete request format." }
+ }
+ }
+}
\ No newline at end of file
diff --git a/marketplace/plugins/authorizenet/lib/query_operations.ts b/marketplace/plugins/authorizenet/lib/query_operations.ts
new file mode 100644
index 0000000000..6d2f59c659
--- /dev/null
+++ b/marketplace/plugins/authorizenet/lib/query_operations.ts
@@ -0,0 +1,839 @@
+import { QueryError, QueryResult, QueryService, ConnectionTestResult } from '@tooljet-marketplace/common';
+import { SourceOptions, QueryOptions } from './types';
+import ApiContracts from 'authorizenet/lib/apicontracts';
+import ApiControllers from 'authorizenet/lib/apicontrollers';
+import Constants from 'authorizenet/lib/constants';
+
+
+export function getEnvironment(env: string) {
+ const endpoints = Constants.constants?.endpoint;
+ if (!endpoints) {
+ throw new Error("Authorize.net endpoints not found in Constants");
+ }
+ return env === "production"
+ ? endpoints.production
+ : endpoints.sandbox;
+}
+
+ export function getMerchantAuth(sourceOptions: SourceOptions): any {
+ const merchantAuthenticationType = new ApiContracts.MerchantAuthenticationType();
+ merchantAuthenticationType.setName(sourceOptions.apiLoginId);
+ merchantAuthenticationType.setTransactionKey(sourceOptions.transactionKey);
+ return merchantAuthenticationType;
+ }
+// helpers
+function parseRequestBody(queryOptions: any): any {
+ try {
+ return typeof queryOptions.requestBody === 'string'
+ ? JSON.parse(queryOptions.requestBody)
+ : queryOptions.requestBody;
+ } catch (error) {
+ throw new QueryError(
+ 'Request parsing failed',
+ 'Invalid JSON format in request body',
+ {
+ code: 'INVALID_JSON',
+ message: error instanceof Error ? error.message : 'Failed to parse request body',
+ }
+ );
+ }
+}
+function createCustomerAddress(addressData: any): any {
+ if (!addressData) return null;
+
+ const address = new ApiContracts.CustomerAddressType();
+
+ if (addressData.firstName) address.setFirstName(addressData.firstName);
+ if (addressData.lastName) address.setLastName(addressData.lastName);
+ if (addressData.company) address.setCompany(addressData.company);
+ if (addressData.address) address.setAddress(addressData.address);
+ if (addressData.city) address.setCity(addressData.city);
+ if (addressData.state) address.setState(addressData.state);
+ if (addressData.zip) address.setZip(addressData.zip);
+ if (addressData.country) address.setCountry(addressData.country);
+ if (addressData.phoneNumber) address.setPhoneNumber(addressData.phoneNumber);
+ if (addressData.faxNumber) address.setFaxNumber(addressData.faxNumber);
+
+ return address;
+}
+function createExtendedAmountType(data: any): any {
+ if (!data) return null;
+
+ const extendedAmount = new ApiContracts.ExtendedAmountType();
+
+ if (data.amount) extendedAmount.setAmount(data.amount);
+ if (data.name) extendedAmount.setName(data.name);
+ if (data.description) extendedAmount.setDescription(data.description);
+
+ return extendedAmount;
+}
+function setLineItemsIfExists(transactionRequest: any, lineItemsData: any): void {
+ if (!lineItemsData) return;
+
+ const lineItemsArray = Array.isArray(lineItemsData.lineItem)
+ ? lineItemsData.lineItem
+ : [lineItemsData.lineItem];
+
+ const lineItems = [];
+ lineItemsArray.forEach(item => {
+ if (item) {
+ const lineItem = new ApiContracts.LineItemType();
+ if (item.itemId) lineItem.setItemId(item.itemId);
+ if (item.name) lineItem.setName(item.name);
+ if (item.description) lineItem.setDescription(item.description);
+ if (item.quantity) lineItem.setQuantity(item.quantity);
+ if (item.unitPrice) lineItem.setUnitPrice(item.unitPrice);
+ lineItems.push(lineItem);
+ }
+ });
+
+ if (lineItems.length > 0) {
+ const lineItemsList = new ApiContracts.ArrayOfLineItem();
+ lineItemsList.setLineItem(lineItems);
+ transactionRequest.setLineItems(lineItemsList);
+ }
+}
+function setTransactionAmounts(transactionRequest: any, params: any): void {
+ const tax = createExtendedAmountType(params.tax);
+ if (tax) {
+ transactionRequest.setTax(tax);
+ }
+
+ const duty = createExtendedAmountType(params.duty);
+ if (duty) {
+ transactionRequest.setDuty(duty);
+ }
+
+ const shipping = createExtendedAmountType(params.shipping);
+ if (shipping) {
+ transactionRequest.setShipping(shipping);
+ }
+}
+function setTransactionAddresses(transactionRequest: any, params: any): void {
+ const billTo = createCustomerAddress(params.billTo);
+ if (billTo) {
+ transactionRequest.setBillTo(billTo);
+ }
+
+ const shipTo = createCustomerAddress(params.shipTo);
+ if (shipTo) {
+ transactionRequest.setShipTo(shipTo);
+ }
+}
+function createCreditCard(cardData: any): any {
+ if (!cardData) return null;
+
+ const creditCard = new ApiContracts.CreditCardType();
+ creditCard.setCardNumber(cardData.cardNumber);
+ creditCard.setExpirationDate(cardData.expirationDate);
+ if (cardData.cardCode) {
+ creditCard.setCardCode(cardData.cardCode);
+ }
+
+ return creditCard;
+}
+function executeController(ctrl: any, ResponseClass: any, errorTitle: string,timeoutMs: number = 30000 ): Promise {
+ return new Promise((resolve, reject) => {
+ let isResolved = false;
+ const timeoutId = setTimeout(() => {
+ if (!isResolved) {
+ isResolved = true;
+ reject(new QueryError(errorTitle,`Request timed out after ${timeoutMs}ms`,{code: 'TIMEOUT_ERROR',message: `Request timed out after ${timeoutMs}ms`,}));}
+ }, timeoutMs);
+ ctrl.execute(() => {
+ clearTimeout(timeoutId);
+ if (isResolved) return;
+ isResolved = true;
+
+ const apiResponse = ctrl.getResponse();
+ const response = new ResponseClass(apiResponse);
+
+ if (response.getMessages().getResultCode() === ApiContracts.MessageTypeEnum.OK) {
+ resolve(response);
+ } else {
+ const messages = response.getMessages()?.getMessage();
+ const errorMessage = messages?.[0]?.getText() ?? 'Unknown error';
+ const errorCode = messages?.[0]?.getCode() ?? 'UNKNOWN_ERROR';
+ reject(new QueryError(errorTitle, errorMessage, {
+ code: errorCode,
+ message: errorMessage,
+ }));
+ }
+ });
+ });
+}
+function setProcessingOptions(transactionRequest: any, params: any): void {
+ if (!params.processingOptions) return;
+
+ const processingOptions = new ApiContracts.ProcessingOptions();
+ if (params.processingOptions.isSubsequentAuth) {
+ processingOptions.setIsSubsequentAuth(params.processingOptions.isSubsequentAuth);
+ }
+ transactionRequest.setProcessingOptions(processingOptions);
+}
+function setSubsequentAuthInformation(transactionRequest: any, params: any): void {
+ if (!params.subsequentAuthInformation) return;
+
+ const subsequentAuthInfo = new ApiContracts.SubsequentAuthInformation();
+ if (params.subsequentAuthInformation.originalNetworkTransId) {
+ subsequentAuthInfo.setOriginalNetworkTransId(params.subsequentAuthInformation.originalNetworkTransId);
+ }
+ if (params.subsequentAuthInformation.originalAuthAmount) {
+ subsequentAuthInfo.setOriginalAuthAmount(params.subsequentAuthInformation.originalAuthAmount);
+ }
+ if (params.subsequentAuthInformation.reason) {
+ subsequentAuthInfo.setReason(params.subsequentAuthInformation.reason);
+ }
+ transactionRequest.setSubsequentAuthInformation(subsequentAuthInfo);
+}
+function setAuthorizationIndicatorType(transactionRequest: any, params: any): void {
+ if (!params.authorizationIndicatorType) return;
+
+ const authIndicatorType = new ApiContracts.AuthorizationIndicatorType();
+ if (params.authorizationIndicatorType.authorizationIndicator) {
+ authIndicatorType.setAuthorizationIndicator(params.authorizationIndicatorType.authorizationIndicator);
+ }
+ transactionRequest.setAuthorizationIndicatorType(authIndicatorType);
+}
+function setCustomerData(transactionRequest: any, params: any): void {
+ if (params.customer) {
+ const customer = new ApiContracts.CustomerDataType();
+ if (params.customer.id) customer.setId(params.customer.id);
+ transactionRequest.setCustomer(customer);
+ }
+
+ if (params.customerIP) {
+ transactionRequest.setCustomerIP(params.customerIP);
+ }
+}
+function setUserFields(transactionRequest: any, params: any): void {
+ if (!params.userFields) return;
+
+ const userFieldsArray = Array.isArray(params.userFields.userField)
+ ? params.userFields.userField
+ : [params.userFields.userField];
+
+ const userFields = [];
+ userFieldsArray.forEach(uf => {
+ if (uf) {
+ const userField = new ApiContracts.UserField();
+ if (uf.name) userField.setName(uf.name);
+ if (uf.value) userField.setValue(uf.value);
+ userFields.push(userField);
+ }
+ });
+
+ if (userFields.length > 0) {
+ const userFieldsList = new ApiContracts.TransactionRequestType.UserFields();
+ userFieldsList.setUserField(userFields);
+ transactionRequest.setUserFields(userFieldsList);
+ }
+}
+function setTransactionSettings(transactionRequest: any, params: any): void {
+ if (!params.transactionSettings) return;
+
+ const settingsList = new ApiContracts.ArrayOfSetting();
+ const settingsArray = Array.isArray(params.transactionSettings.setting)
+ ? params.transactionSettings.setting
+ : [params.transactionSettings.setting];
+
+ settingsArray.forEach(s => {
+ const setting = new ApiContracts.SettingType();
+ if (s.settingName) setting.setSettingName(s.settingName);
+ if (s.settingValue) setting.setSettingValue(s.settingValue);
+ settingsList.getSetting().push(setting);
+ });
+ transactionRequest.setTransactionSettings(settingsList);
+}
+function validateAmount(amount: any, operationName: string): void {
+ if (!amount || amount <= 0) {
+ throw new QueryError(
+ `${operationName} failed`,
+ 'Amount must be a positive number',
+ {
+ code: 'INVALID_AMOUNT',
+ message: 'Amount must be greater than 0',
+ }
+ );
+ }
+}
+
+//main operations
+export async function chargeCreditCard(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+
+ validateAmount(params.amount, 'Transaction');
+
+ const creditCard = createCreditCard(params);
+
+ const paymentType = new ApiContracts.PaymentType();
+ paymentType.setCreditCard(creditCard);
+
+ const transactionRequestType = new ApiContracts.TransactionRequestType();
+ transactionRequestType.setTransactionType(ApiContracts.TransactionTypeEnum.AUTHCAPTURETRANSACTION);
+ transactionRequestType.setPayment(paymentType);
+ transactionRequestType.setAmount(params.amount);
+
+ setLineItemsIfExists(transactionRequestType, params.lineItems);
+ setTransactionAmounts(transactionRequestType, params);
+ setTransactionAddresses(transactionRequestType, params);
+
+ if (params.poNumber) {
+ transactionRequestType.setPoNumber(params.poNumber);
+ }
+
+ setCustomerData(transactionRequestType, params);
+ setTransactionSettings(transactionRequestType, params);
+ setUserFields(transactionRequestType, params);
+ setProcessingOptions(transactionRequestType, params);
+ setSubsequentAuthInformation(transactionRequestType, params);
+ setAuthorizationIndicatorType(transactionRequestType, params);
+
+ const createRequest = new ApiContracts.CreateTransactionRequest();
+ createRequest.setMerchantAuthentication(merchantAuth);
+ createRequest.setTransactionRequest(transactionRequestType);
+ createRequest.setRefId(params.refId);
+
+ const ctrl = new ApiControllers.CreateTransactionController(createRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.CreateTransactionResponse,"Transaction failed");
+}
+
+export async function authorizeCreditCard(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+ validateAmount(params.amount, 'Authorization');
+ const cardData = params.payment?.creditCard || params;
+ const creditCard = createCreditCard(cardData);
+
+ const paymentType = new ApiContracts.PaymentType();
+ paymentType.setCreditCard(creditCard);
+
+ const transactionRequestType = new ApiContracts.TransactionRequestType();
+ transactionRequestType.setTransactionType(ApiContracts.TransactionTypeEnum.AUTHONLYTRANSACTION);
+ transactionRequestType.setPayment(paymentType);
+ transactionRequestType.setAmount(params.amount);
+
+ setLineItemsIfExists(transactionRequestType, params.lineItems);
+ setTransactionAmounts(transactionRequestType, params);
+ setTransactionAddresses(transactionRequestType, params);
+
+ if (params.poNumber) {
+ transactionRequestType.setPoNumber(params.poNumber);
+ }
+
+ setCustomerData(transactionRequestType, params);
+ setUserFields(transactionRequestType, params);
+ setProcessingOptions(transactionRequestType, params);
+ setSubsequentAuthInformation(transactionRequestType, params);
+ setAuthorizationIndicatorType(transactionRequestType, params);
+
+ const createRequest = new ApiContracts.CreateTransactionRequest();
+ createRequest.setMerchantAuthentication(merchantAuth);
+ createRequest.setTransactionRequest(transactionRequestType);
+ if (params.refId) {
+ createRequest.setRefId(params.refId);
+ }
+
+ const ctrl = new ApiControllers.CreateTransactionController(createRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.CreateTransactionResponse,"Authorization failed");
+}
+
+export async function captureAuthorizedAmount(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+ validateAmount(params.amount, 'Capture');
+ const transactionRequestType = new ApiContracts.TransactionRequestType();
+ transactionRequestType.setTransactionType(ApiContracts.TransactionTypeEnum.PRIORAUTHCAPTURETRANSACTION);
+ transactionRequestType.setAmount(params.amount);
+ transactionRequestType.setRefTransId(params.refTransId);
+
+ const createRequest = new ApiContracts.CreateTransactionRequest();
+ createRequest.setMerchantAuthentication(merchantAuth);
+ createRequest.setTransactionRequest(transactionRequestType);
+ if (params.refId) {
+ createRequest.setRefId(params.refId);
+ }
+
+ const ctrl = new ApiControllers.CreateTransactionController(createRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.CreateTransactionResponse,"Capture failed");
+}
+
+export async function refundTransaction(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+ validateAmount(params.amount, 'Refund');
+ const creditCard = new ApiContracts.CreditCardType();
+ creditCard.setCardNumber(params.cardNumber);
+ creditCard.setExpirationDate(params.expirationDate);
+ const paymentType = new ApiContracts.PaymentType();
+ paymentType.setCreditCard(creditCard);
+
+ const transactionRequestType = new ApiContracts.TransactionRequestType();
+ transactionRequestType.setTransactionType(ApiContracts.TransactionTypeEnum.REFUNDTRANSACTION);
+ transactionRequestType.setAmount(params.amount);
+ transactionRequestType.setPayment(paymentType);
+ transactionRequestType.setRefTransId(params.transId);
+
+ const createRequest = new ApiContracts.CreateTransactionRequest();
+ createRequest.setMerchantAuthentication(merchantAuth);
+ createRequest.setTransactionRequest(transactionRequestType);
+
+ const ctrl = new ApiControllers.CreateTransactionController(createRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.CreateTransactionResponse,"Refund failed");
+}
+
+export async function voidTransaction(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+
+ if (!params.transId) {
+ throw new QueryError(
+ 'Void failed',
+ 'Missing required parameter: transId',
+ {
+ code: 'MISSING_PARAM',
+ message: 'transId is required for void transaction',
+ }
+ );
+ }
+
+ const transactionRequestType = new ApiContracts.TransactionRequestType();
+ transactionRequestType.setTransactionType(ApiContracts.TransactionTypeEnum.VOIDTRANSACTION);
+ transactionRequestType.setRefTransId(params.transId);
+
+ if (params.terminalNumber) {
+ transactionRequestType.setTerminalNumber(params.terminalNumber);
+ }
+
+ const createRequest = new ApiContracts.CreateTransactionRequest();
+ createRequest.setMerchantAuthentication(merchantAuth);
+ createRequest.setTransactionRequest(transactionRequestType);
+
+ if (params.refId) {
+ const refId = params.refId.toString().substring(0, 20);
+ createRequest.setRefId(refId);
+ }
+
+ const ctrl = new ApiControllers.CreateTransactionController(createRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+ return executeController(ctrl,ApiContracts.CreateTransactionResponse,"Void failed");
+}
+
+export async function chargeCustomerProfile(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+ validateAmount(params.amount, 'Charge customer profile');
+ const profileData = params.profile || params;
+
+ const profileToCharge = new ApiContracts.CustomerProfilePaymentType();
+ profileToCharge.setCustomerProfileId(
+ profileData.customerProfileId || params.customerProfileId
+ );
+
+ const paymentProfile = new ApiContracts.PaymentProfile();
+ paymentProfile.setPaymentProfileId(
+ profileData.paymentProfile?.paymentProfileId || params.customerPaymentProfileId
+ );
+ profileToCharge.setPaymentProfile(paymentProfile);
+
+ const transactionRequestType = new ApiContracts.TransactionRequestType();
+ transactionRequestType.setTransactionType(ApiContracts.TransactionTypeEnum.AUTHCAPTURETRANSACTION);
+ transactionRequestType.setProfile(profileToCharge);
+ transactionRequestType.setAmount(params.amount);
+
+ setLineItemsIfExists(transactionRequestType, params.lineItems);
+ setTransactionAmounts(transactionRequestType, params);
+ setTransactionAddresses(transactionRequestType, params);
+
+ if (params.poNumber) {
+ transactionRequestType.setPoNumber(params.poNumber);
+ }
+
+ setCustomerData(transactionRequestType, params);
+ setProcessingOptions(transactionRequestType, params);
+ setSubsequentAuthInformation(transactionRequestType, params);
+ setAuthorizationIndicatorType(transactionRequestType, params);
+
+ const createRequest = new ApiContracts.CreateTransactionRequest();
+ createRequest.setMerchantAuthentication(merchantAuth);
+ createRequest.setTransactionRequest(transactionRequestType);
+
+ if (params.refId) {
+ createRequest.setRefId(params.refId);
+ }
+
+ const ctrl = new ApiControllers.CreateTransactionController(createRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+ return executeController(ctrl,ApiContracts.CreateTransactionResponse,"Charge customer profile failed");
+}
+
+export async function createCustomerProfile(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+
+ const customerProfile = new ApiContracts.CustomerProfileType();
+
+ if (params.merchantCustomerId) {
+ customerProfile.setMerchantCustomerId(params.merchantCustomerId);
+ }
+ if (params.description) {
+ customerProfile.setDescription(params.description);
+ }
+ if (params.email) {
+ customerProfile.setEmail(params.email);
+ }
+
+ if (params.profileType) {
+ customerProfile.setProfileType(params.profileType);
+ }
+
+ if (params.paymentProfiles && Array.isArray(params.paymentProfiles)) {
+ const paymentProfilesList = params.paymentProfiles.map((profile: any) => {
+ const paymentProfile = new ApiContracts.CustomerPaymentProfileType();
+
+ if (profile.customerType) {
+ paymentProfile.setCustomerType(profile.customerType);
+ }
+
+ const billTo = createCustomerAddress(profile.billTo);
+ if (billTo) {
+ paymentProfile.setBillTo(billTo);
+ }
+
+ if (profile.payment) {
+ const payment = new ApiContracts.PaymentType();
+
+ if (profile.payment.creditCard) {
+ const creditCard = createCreditCard(profile.payment.creditCard);
+ payment.setCreditCard(creditCard);
+ }
+
+ if (profile.payment.bankAccount) {
+ const bankAccount = new ApiContracts.BankAccountType();
+ bankAccount.setAccountType(profile.payment.bankAccount.accountType);
+ bankAccount.setRoutingNumber(profile.payment.bankAccount.routingNumber);
+ bankAccount.setAccountNumber(profile.payment.bankAccount.accountNumber);
+ bankAccount.setNameOnAccount(profile.payment.bankAccount.nameOnAccount);
+ if (profile.payment.bankAccount.echeckType) {
+ bankAccount.setEcheckType(profile.payment.bankAccount.echeckType);
+ }
+ if (profile.payment.bankAccount.bankName) {
+ bankAccount.setBankName(profile.payment.bankAccount.bankName);
+ }
+ payment.setBankAccount(bankAccount);
+ }
+
+ if (profile.payment.opaqueData) {
+ const opaqueData = new ApiContracts.OpaqueDataType();
+ opaqueData.setDataDescriptor(profile.payment.opaqueData.dataDescriptor);
+ opaqueData.setDataValue(profile.payment.opaqueData.dataValue);
+ payment.setOpaqueData(opaqueData);
+ }
+
+ paymentProfile.setPayment(payment);
+ }
+
+ return paymentProfile;
+ });
+
+ customerProfile.setPaymentProfiles(paymentProfilesList);
+ }
+
+ if (params.shipToList && Array.isArray(params.shipToList)) {
+ const shipToList = params.shipToList.map((address: any) => createCustomerAddress(address));
+ customerProfile.setShipToList(shipToList);
+ }
+
+ const createRequest = new ApiContracts.CreateCustomerProfileRequest();
+ createRequest.setMerchantAuthentication(merchantAuth);
+ createRequest.setProfile(customerProfile);
+
+ if (params.refId) {
+ createRequest.setRefId(params.refId);
+ }
+
+ if (params.validationMode) {
+ createRequest.setValidationMode(params.validationMode);
+ }
+
+ const ctrl = new ApiControllers.CreateCustomerProfileController(createRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.CreateCustomerProfileResponse,"Create customer profile failed");
+}
+
+export async function getCustomerProfile(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+
+ const getRequest = new ApiContracts.GetCustomerProfileRequest();
+ getRequest.setMerchantAuthentication(merchantAuth);
+ getRequest.setCustomerProfileId(params.customerProfileId);
+
+ if (params.refId !== undefined && params.refId !== null) {
+ getRequest.setRefId(params.refId);
+ }
+
+ if (params.merchantCustomerId !== undefined && params.merchantCustomerId !== null) {
+ getRequest.setMerchantCustomerId(params.merchantCustomerId);
+ }
+
+ if (params.email !== undefined && params.email !== null) {
+ getRequest.setEmail(params.email);
+ }
+
+ if (params.unmaskExpirationDate !== undefined) {
+ getRequest.setUnmaskExpirationDate(
+ params.unmaskExpirationDate === true || params.unmaskExpirationDate === "true"
+ );
+ }
+
+ if (params.includeIssuerInfo !== undefined) {
+ getRequest.setIncludeIssuerInfo(
+ params.includeIssuerInfo === true || params.includeIssuerInfo === "true"
+ );
+ }
+
+ const ctrl = new ApiControllers.GetCustomerProfileController(getRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.GetCustomerProfileResponse,"Get customer profile failed");
+}
+
+export async function getCustomerProfileIds(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+
+ const params = parseRequestBody(queryOptions);
+
+ const getRequest = new ApiContracts.GetCustomerProfileIdsRequest();
+ getRequest.setMerchantAuthentication(merchantAuth);
+
+ const ctrl = new ApiControllers.GetCustomerProfileIdsController(getRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.GetCustomerProfileIdsResponse,"Get customer profile IDs failed");
+}
+
+export async function updateCustomerProfile(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+
+ const customerProfile = new ApiContracts.CustomerProfileExType();
+ customerProfile.setCustomerProfileId(params.customerProfileId);
+ if (params.merchantCustomerId) {
+ customerProfile.setMerchantCustomerId(params.merchantCustomerId);
+ }
+ if (params.description) {
+ customerProfile.setDescription(params.description);
+ }
+ if (params.email) {
+ customerProfile.setEmail(params.email);
+ }
+
+ const updateRequest = new ApiContracts.UpdateCustomerProfileRequest();
+ updateRequest.setMerchantAuthentication(merchantAuth);
+ updateRequest.setProfile(customerProfile);
+
+ const ctrl = new ApiControllers.UpdateCustomerProfileController(updateRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.UpdateCustomerProfileResponse,"Update customer profile failed");
+}
+
+export async function deleteCustomerProfile(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+
+ const deleteRequest = new ApiContracts.DeleteCustomerProfileRequest();
+ deleteRequest.setMerchantAuthentication(merchantAuth);
+ deleteRequest.setCustomerProfileId(params.customerProfileId);
+ if (params.refId) {
+ deleteRequest.setRefId(params.refId);
+ }
+
+ const ctrl = new ApiControllers.DeleteCustomerProfileController(deleteRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl, ApiContracts.DeleteCustomerProfileResponse,"Delete customer profile failed");
+}
+
+export async function createCustomerPaymentProfile(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+ const cardData = params.payment?.creditCard || params;
+ const creditCard = createCreditCard(cardData);
+
+ const paymentType = new ApiContracts.PaymentType();
+ paymentType.setCreditCard(creditCard);
+
+ const customerPaymentProfile = new ApiContracts.CustomerPaymentProfileType();
+ customerPaymentProfile.setPayment(paymentType);
+
+ const billTo = createCustomerAddress(params.billTo);
+ if (billTo) {
+ customerPaymentProfile.setBillTo(billTo);
+ }
+
+ if (params.defaultPaymentProfile !== undefined) {
+ customerPaymentProfile.setDefaultPaymentProfile(params.defaultPaymentProfile);
+ }
+
+ const createRequest = new ApiContracts.CreateCustomerPaymentProfileRequest();
+ createRequest.setMerchantAuthentication(merchantAuth);
+ createRequest.setCustomerProfileId(params.customerProfileId);
+ createRequest.setPaymentProfile(customerPaymentProfile);
+
+ if (params.validationMode) {
+ createRequest.setValidationMode(params.validationMode);
+ }
+
+ if (params.refId) {
+ createRequest.setRefId(params.refId);
+ }
+
+ const ctrl = new ApiControllers.CreateCustomerPaymentProfileController(createRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl, ApiContracts.CreateCustomerPaymentProfileResponse,"Create customer payment profile failed");
+}
+
+export async function getCustomerPaymentProfile(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+
+ const getRequest = new ApiContracts.GetCustomerPaymentProfileRequest();
+ getRequest.setMerchantAuthentication(merchantAuth);
+ getRequest.setCustomerProfileId(params.customerProfileId);
+ getRequest.setCustomerPaymentProfileId(params.customerPaymentProfileId);
+
+ const ctrl = new ApiControllers.GetCustomerPaymentProfileController(getRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.GetCustomerPaymentProfileResponse, "Get customer payment profile failed");
+}
+
+export async function validateCustomerPaymentProfile(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+
+ const validateRequest = new ApiContracts.ValidateCustomerPaymentProfileRequest();
+ validateRequest.setMerchantAuthentication(merchantAuth);
+ validateRequest.setCustomerProfileId(params.customerProfileId);
+ validateRequest.setCustomerPaymentProfileId(params.customerPaymentProfileId);
+ validateRequest.setValidationMode(
+ params.validationMode === 'liveMode'
+ ? ApiContracts.ValidationModeEnum.LIVEMODE
+ : ApiContracts.ValidationModeEnum.TESTMODE
+ );
+
+ const ctrl = new ApiControllers.ValidateCustomerPaymentProfileController(validateRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.ValidateCustomerPaymentProfileResponse,"Validate customer payment profile failed");
+}
+
+export async function updateCustomerPaymentProfile(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+ const profileData = params.paymentProfile || params;
+ const cardData = profileData.payment?.creditCard || profileData;
+ const creditCard = createCreditCard(cardData);
+ const paymentType = new ApiContracts.PaymentType();
+ paymentType.setCreditCard(creditCard);
+
+ const customerPaymentProfile = new ApiContracts.CustomerPaymentProfileExType();
+ customerPaymentProfile.setPayment(paymentType);
+ customerPaymentProfile.setCustomerPaymentProfileId(
+ profileData.customerPaymentProfileId || params.customerPaymentProfileId
+ );
+
+ const billTo = createCustomerAddress(profileData.billTo);
+ if (billTo) {
+ customerPaymentProfile.setBillTo(billTo);
+ }
+
+ if (profileData.defaultPaymentProfile !== undefined) {
+ customerPaymentProfile.setDefaultPaymentProfile(profileData.defaultPaymentProfile);
+ }
+
+ const updateRequest = new ApiContracts.UpdateCustomerPaymentProfileRequest();
+ updateRequest.setMerchantAuthentication(merchantAuth);
+ updateRequest.setCustomerProfileId(params.customerProfileId);
+ updateRequest.setPaymentProfile(customerPaymentProfile);
+
+ if (params.validationMode) {
+ updateRequest.setValidationMode(params.validationMode);
+ }
+
+ if (params.refId) {
+ updateRequest.setRefId(params.refId);
+ }
+
+ const ctrl = new ApiControllers.UpdateCustomerPaymentProfileController(updateRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.UpdateCustomerPaymentProfileResponse,"Update customer payment profile failed");
+}
+
+export async function deleteCustomerPaymentProfile(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+
+ const deleteRequest = new ApiContracts.DeleteCustomerPaymentProfileRequest();
+ deleteRequest.setMerchantAuthentication(merchantAuth);
+ deleteRequest.setCustomerProfileId(params.customerProfileId);
+ deleteRequest.setCustomerPaymentProfileId(params.customerPaymentProfileId);
+
+ if (params.refId) {
+ deleteRequest.setRefId(params.refId);
+ }
+ const ctrl = new ApiControllers.DeleteCustomerPaymentProfileController(deleteRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.DeleteCustomerPaymentProfileResponse,"Delete customer payment profile failed");
+}
+
+export async function createCustomerProfileFromTransaction(sourceOptions: SourceOptions, queryOptions: any): Promise {
+ const merchantAuth = getMerchantAuth(sourceOptions);
+ const params = parseRequestBody(queryOptions);
+
+ const createRequest = new ApiContracts.CreateCustomerProfileFromTransactionRequest();
+ createRequest.setMerchantAuthentication(merchantAuth);
+ createRequest.setTransId(params.transId);
+
+ if (params.customer) {
+ const customer = new ApiContracts.CustomerProfileBaseType();
+ if (params.customer.merchantCustomerId) {
+ customer.setMerchantCustomerId(params.customer.merchantCustomerId);
+ }
+ if (params.customer.description) {
+ customer.setDescription(params.customer.description);
+ }
+ if (params.customer.email) {
+ customer.setEmail(params.customer.email);
+ }
+ createRequest.setCustomer(customer);
+ }
+
+ if (params.profileType) {
+ createRequest.setProfileType(params.profileType);
+ }
+
+ if (params.refId) {
+ createRequest.setRefId(params.refId);
+ }
+
+ const ctrl = new ApiControllers.CreateCustomerProfileFromTransactionController(createRequest.getJSON());
+ ctrl.setEnvironment(getEnvironment(sourceOptions.environment));
+
+ return executeController(ctrl,ApiContracts.CreateCustomerProfileResponse,"Create customer profile from transaction failed");
+}
\ No newline at end of file
diff --git a/marketplace/plugins/authorizenet/lib/types.ts b/marketplace/plugins/authorizenet/lib/types.ts
new file mode 100644
index 0000000000..c651b3e705
--- /dev/null
+++ b/marketplace/plugins/authorizenet/lib/types.ts
@@ -0,0 +1,10 @@
+export type SourceOptions = {
+ apiLoginId: string;
+ transactionKey: string;
+ environment: 'sandbox' | 'production';
+};
+
+export type QueryOptions = {
+ operation: string;
+ requestBody?: string;
+};
diff --git a/marketplace/plugins/authorizenet/package.json b/marketplace/plugins/authorizenet/package.json
new file mode 100644
index 0000000000..257b18fb9c
--- /dev/null
+++ b/marketplace/plugins/authorizenet/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "@tooljet-marketplace/authorizenet",
+ "version": "1.0.0",
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "directories": {
+ "lib": "lib",
+ "test": "__tests__"
+ },
+ "files": [
+ "lib"
+ ],
+ "scripts": {
+ "test": "echo \"Error: run tests from root\" && exit 1",
+ "build": "ncc build lib/index.ts -o dist",
+ "watch": "ncc build lib/index.ts -o dist --watch"
+ },
+ "homepage": "https://github.com/tooljet/tooljet#readme",
+ "dependencies": {
+ "@tooljet-marketplace/common": "^1.0.0",
+ "authorizenet": "^1.0.10"
+ },
+ "devDependencies": {
+ "@vercel/ncc": "^0.34.0",
+ "typescript": "^4.7.4"
+ }
+}
diff --git a/marketplace/plugins/authorizenet/tsconfig.json b/marketplace/plugins/authorizenet/tsconfig.json
new file mode 100644
index 0000000000..a18a801b14
--- /dev/null
+++ b/marketplace/plugins/authorizenet/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "dist",
+ "rootDir": "lib"
+ },
+ "exclude": [
+ "node_modules",
+ "dist"
+ ]
+}
\ No newline at end of file
diff --git a/server/.version b/server/.version
index b1bc230b93..4023a07f73 100644
--- a/server/.version
+++ b/server/.version
@@ -1 +1 @@
-3.20.48-lts
+3.20.49-lts
diff --git a/server/src/assets/marketplace/plugins.json b/server/src/assets/marketplace/plugins.json
index b056280c6a..e2d6ad1740 100644
--- a/server/src/assets/marketplace/plugins.json
+++ b/server/src/assets/marketplace/plugins.json
@@ -320,5 +320,16 @@
"id": "fedex",
"author": "Tooljet",
"timestamp": "Fri, 05 Sep 2025 05:46:39 GMT"
+ },
+ {
+ "name": "Authorize.Net",
+ "description": "Plugin for payment processing and customer profile management",
+ "version": "1.0.0",
+ "id": "authorizenet",
+ "author": "Tooljet",
+ "timestamp": "Tue, 25 Nov 2025 16:27:22 GMT",
+ "tags": [
+ "Payment"
+ ]
}
]
\ No newline at end of file