How to access iparams.json values in server.js code?

Hello. I have a problem creating the first freshdesk application. Specifically, server.js and iparams.json collaboration:

iparams.json:
{
“domain”: {
“display_name”: “Freshdesk Domain”,
“description”: “Please enter your Freshdesk domain”,
“type”: “text”,
“required”: true
}
}

Server.js:
const axios = require(‘axios’);
const { Base64 } = require(‘js-base64’);

const axiosInstance = axios.create({
headers: {
‘Content-Type’: ‘application/json’
}
});

axiosInstance.interceptors.request.use(request => {
const apiKey = ‘XXXXXXXXXXXXXX’;
if (!request.headers[‘Authorization’]) {
const encodedApiKey = Base64.encode(apiKey + ‘:’);
request.headers[‘Authorization’] = Basic ${encodedApiKey};
}
return request;
}, error => {
// Handle request error here
return Promise.reject(error);
});

exports = {
events: [
{
event: ‘onTicketCreate’,
callback: ‘onTicketCreateHandler’
}
],

onTicketCreateHandler: async function(args) {
const client = args.client;
const iparams = await client.iparams.get();
const freshdeskDomain = iparams.domain;
const ticketId = args.data.ticket.id;
const ticketDescription = “Hello world”;

const noteData = {
  body: ticketDescription,
  private: false
};

axiosInstance.post(`${freshdeskDomain}/api/v2/tickets/${ticketId}/notes`, noteData)
  .then() // Handle success
  .catch(() => {
    // Handle error
  });

}
};

The server.js file is in the server folder
The iparams.json file is in the config folder
The structure is how it was generated by the default call to fdk create

The original code where I did not use iparams.json and called the URL and API code directly in server.js created the note, but as soon as I move the domain call to iparams.json the code does not work.

Does anyone have a sample code that reads the ticket and inserts a note and at the same time can load the URL and API code from iparams.json?

Thank you for your help.

Pavel

Hi @PavelCZ,

In the server.js file, the domain is fetched differently. The client object Is not available in the serverless components.

You can get the iparam values with the args.iparams.domain syntax, assuming you have an iparam called domain.

Check out the attributes you get in the arguments of the serverless function in the documentation.

Tests working properly:
iparams:
{
“domain”: {
“display_name”: “Freshdesk Domain”,
“description”: “Please enter your Freshdesk domain”,
“type”: “text”,
“required”: true
}
}

Server.js:
const axios = require(‘axios’);
const { Base64 } = require(‘js-base64’);
const axiosInstance = axios.create({
headers: {
‘Content-Type’: ‘application/json’
}
});

axiosInstance.interceptors.request.use(request => {
const apiKey = ‘XXXXXXXXX’;
if (!request.headers[‘Authorization’]) {
const encodedApiKey = Base64.encode(apiKey + ‘:’);
request.headers[‘Authorization’] = Basic ${encodedApiKey};
}
return request;
}, error => {

return Promise.reject(error);
});

exports = {
events: [
{
event: ‘onTicketCreate’,
callback: ‘onTicketCreateHandler’
}
],

onTicketCreateHandler: async function(args) {

const freshdeskDomain = args.iparams.domain;
const ticketId = args.data.ticket.id;
const ticketDescription = "Hello world"; 

const noteData = {
  body: ticketDescription,
  private: false
};


axiosInstance.post(`${freshdeskDomain}/api/v2/tickets/${ticketId}/notes`, noteData)
  .then(response => {
    console.log('Note added successfully:', response.data);
  })
  .catch(error => {
    console.error('Error adding note:', error);
  });

}
};

I tried to extend the code by calling the API key ( const apiKey = args.iparams.apiKey; ) but it’s simply not possible anymore. Is there a simple solution?

Thank You

Freddy said Hi @PavelCZ,

You can store the API key as an installation parameter in the iparams.json file, just like you did with the domain.

iparams.json:

{
  "domain": {
    "display_name": "Freshdesk Domain",
    "description": "Please enter your Freshdesk domain",
    "type": "text",
    "required": true
  },
  "apiKey": {
    "display_name": "API Key",
    "description": "Please enter your Freshdesk API key",
    "type": "text",
    "required": true,
    "secure": true
  }
}

Then, in your server.js file, access the API key the same way you accessed the domain. Replace this line:

const apiKey = 'XXXXXXXXX';

with this:

const apiKey = args.iparams.apiKey;

This should make your code work with the API key

Code:
const axiosInstance = axios.create({
headers: {
‘Content-Type’: ‘application/json’
}
});
axiosInstance.interceptors.request.use(request => {
const apiKey = args.iparams.apiKey;
if (!request.headers[‘Authorization’]) {
const encodedApiKey = Base64.encode(apiKey + ‘:’);
request.headers[‘Authorization’] = Basic ${encodedApiKey};
}
return request;
}, error => {
return Promise.reject(error);
});

exports = {
events: [
{
event: ‘onTicketCreate’,
callback: ‘onTicketCreateHandler’
}
],
onTicketCreateHandler: async function(args) {
const freshdeskDomain = args.iparams.domain;
const ticketId = args.data.ticket.id;
const ticketDescription = “Hello world”;
const noteData = {
body: ticketDescription,
private: false
};
axiosInstance.post(${freshdeskDomain}/api/v2/tickets/${ticketId}/notes, noteData)
.then(response => {
console.log(‘Note added successfully:’, response.data);
})
.catch(error => {
console.error(‘Error adding note:’, error);
});
}
};

Error:
Error adding note: ReferenceError: args is not defined at server.js:13:16

Thank you for your help.

or other sample functional code ? (ZIP) ?

It’s because you are accessing args outside of the handler context.

Try moving this code inside the handler function and do console.log(args) to find everything in it.

Here are some links to sample apps that demonstrate how to use iparams and interact with the Freshdesk APIs:

  1. Freshdesk sample app - This app demonstrates how to use data binding to access event data and iparams for basic authentication.
  2. Freshdesk ticket merging app - This app enables two or more Freshdesk tickets to be merged together.
  3. Freshdesk notifier app - This app uses iparams to access Slack configuration and to send messages from Freshdesk tickets to a Slack channel.

These sample apps should provide a good starting point to understand how to access iparams from the config and interact with the Freshdesk APIs.

Current code:
const axios = require(‘axios’);
const { Base64 } = require(‘js-base64’);
const axiosInstance = axios.create({
headers: {
‘Content-Type’: ‘application/json’
}
});

function createAuthHeader(apiKey) {
const encodedApiKey = Base64.encode(apiKey + ‘:’);
return Basic ${encodedApiKey};
}

exports = {
events: [
{
event: ‘onTicketCreate’,
callback: ‘onTicketCreateHandler’
}
],

onTicketCreateHandler: async function(args) {
const freshdeskDomain = args.iparams.domain;
const apiKey = args.iparams.apiKey;
const ticketId = args.data.ticket.id;
const ticketDescription = “Hello world”;

const noteData = {
  body: ticketDescription,
  private: false
};

const authHeader = createAuthHeader(apiKey);
 axiosInstance.post(`${freshdeskDomain}/api/v2/tickets/${ticketId}/notes`, noteData, {
  headers: { 'Authorization': authHeader }
})
.then(response => {
  console.log('Note added successfully:', response.data);
})
.catch(error => {
  console.error('Error adding note:', error);
});

}
};

Error:
29. 11. 2023 7:00:28 0f91b
Error adding note: [AxiosError: Request failed with status code 401] { code: ‘ERR_BAD_REQUEST’, config: { transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false }, adapter: [Function: httpAdapter], transformRequest: [ [Function: transformRequest] ], transformResponse: [ [Function: transformResponse] ], timeout: 0, xsrfCookieName: ‘XSRF-TOKEN’, xsrfHeaderName: ‘X-XSRF-TOKEN’, maxContentLength: -1, maxBodyLength: -1, env: { FormData: [Function] }, validateStatus: [Function: validateStatus], headers: { ‘Content-Type’: ‘application/json’, ‘User-Agent’: ‘axios/0.27.2’, ‘Content-Length’: 38 }, method: ‘post’, url: ‘https://xxxxxxxtestapi.freshdesk.com/api/v2/tickets/7/notes’, data: ‘{“body”:“Hello world”,“private”:false}’ }, request: <ref *1> ClientRequest { _events: [Object: null prototype] { abort: [Function (anonymous)], aborted: [Function (anonymous)], connect: [Function (anonymous)], error: [Function (anonymous)], socket: [Function (anonymous)], timeout: [Function (anonymous)], finish: [Function: requestOnFinish] }, _eventsCount: 7, _maxListeners: undefined, outputData: , outputSize: 0, writable: true, destroyed: false, _last: true, chunkedEncoding: false, shouldKeepAlive: false, maxRequestsOnConnectionReached: false, _defaultKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, strictContentLength: false, _contentLength: 38, _hasBody: true, _trailer: ‘’, finished: true, _headerSent: true, _closed: false, socket: TLSSocket { _tlsOptions: [Object], _secureEstablished: true, _securePending: false, _newSessionPending: false, _controlReleased: true, secureConnecting: false, _SNICallback: null, s

The sample codes helped, but they are an older version of Freshdesk.

The conclusion is that I did not find a working hello world code. The code I have here in the sandbox works correctly. It doesn’t work on production :frowning:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.