mirror of
https://github.com/ToolJet/ToolJet
synced 2026-04-21 21:47:17 +00:00
Feat: Authorise.net plugin (#14652)
* Authorise net source code files * fix for the claude genereted code for the authorizenet * Removed repeted code * Resolved review Commits * Logo Changed * parsing and some review comments * fixed transaction key * Fixed Error Messages for config Page * chore: update version to 3.20.49-lts across all components --------- Co-authored-by: Pratush <pratush@Pratushs-MacBook-Pro.local> Co-authored-by: gsmithun4 <gsmithun4@gmail.com>
This commit is contained in:
parent
302350f33c
commit
8dbaa5e4e2
15 changed files with 1351 additions and 3 deletions
2
.version
2
.version
|
|
@ -1 +1 @@
|
|||
3.20.48-lts
|
||||
3.20.49-lts
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.20.48-lts
|
||||
3.20.49-lts
|
||||
|
|
|
|||
5
marketplace/plugins/authorizenet/.gitignore
vendored
Normal file
5
marketplace/plugins/authorizenet/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
node_modules
|
||||
lib/*.d.*
|
||||
lib/*.js
|
||||
lib/*.js.map
|
||||
dist/*
|
||||
4
marketplace/plugins/authorizenet/README.md
Normal file
4
marketplace/plugins/authorizenet/README.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
# Authorize.Net
|
||||
|
||||
Documentation on: https://docs.tooljet.com/docs/data-sources/authorizenet
|
||||
7
marketplace/plugins/authorizenet/__tests__/index.js
Normal file
7
marketplace/plugins/authorizenet/__tests__/index.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const authorizenet = require('../lib');
|
||||
|
||||
describe('authorizenet', () => {
|
||||
it.todo('needs tests');
|
||||
});
|
||||
6
marketplace/plugins/authorizenet/lib/icon.svg
Normal file
6
marketplace/plugins/authorizenet/lib/icon.svg
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="20" height="20" transform="translate(2 2)" fill="white"/>
|
||||
<path d="M2 2H22V22H2V2Z" fill="#1F2C45"/>
|
||||
<path d="M9.61584 4.0817C13.0604 3.86439 16.0284 6.48193 16.2433 9.92664C16.4581 13.3714 13.8386 16.3375 10.3937 16.55C6.95221 16.7623 3.98966 14.1458 3.77496 10.7045C3.56028 7.26318 6.17467 4.29879 9.61584 4.0817Z" fill="#3974FD"/>
|
||||
<path d="M16.5359 15.0708C17.8519 15.0154 18.964 16.0363 19.0214 17.3521C19.0787 18.6679 18.0595 19.7816 16.7437 19.8409C15.4252 19.9004 14.3086 18.8786 14.2512 17.56C14.1937 16.2413 15.2172 15.1263 16.5359 15.0708Z" fill="#FEC401"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 684 B |
126
marketplace/plugins/authorizenet/lib/index.ts
Normal file
126
marketplace/plugins/authorizenet/lib/index.ts
Normal file
|
|
@ -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<ConnectionTestResult> {
|
||||
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<QueryResult> {
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
64
marketplace/plugins/authorizenet/lib/manifest.json
Normal file
64
marketplace/plugins/authorizenet/lib/manifest.json
Normal file
|
|
@ -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"]
|
||||
}
|
||||
238
marketplace/plugins/authorizenet/lib/operations.json
Normal file
238
marketplace/plugins/authorizenet/lib/operations.json
Normal file
|
|
@ -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." }
|
||||
}
|
||||
}
|
||||
}
|
||||
839
marketplace/plugins/authorizenet/lib/query_operations.ts
Normal file
839
marketplace/plugins/authorizenet/lib/query_operations.ts
Normal file
|
|
@ -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<T>(ctrl: any, ResponseClass: any, errorTitle: string,timeoutMs: number = 30000 ): Promise<T> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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<any> {
|
||||
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");
|
||||
}
|
||||
10
marketplace/plugins/authorizenet/lib/types.ts
Normal file
10
marketplace/plugins/authorizenet/lib/types.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
export type SourceOptions = {
|
||||
apiLoginId: string;
|
||||
transactionKey: string;
|
||||
environment: 'sandbox' | 'production';
|
||||
};
|
||||
|
||||
export type QueryOptions = {
|
||||
operation: string;
|
||||
requestBody?: string;
|
||||
};
|
||||
27
marketplace/plugins/authorizenet/package.json
Normal file
27
marketplace/plugins/authorizenet/package.json
Normal file
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
11
marketplace/plugins/authorizenet/tsconfig.json
Normal file
11
marketplace/plugins/authorizenet/tsconfig.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "lib"
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
3.20.48-lts
|
||||
3.20.49-lts
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
Loading…
Reference in a new issue