Calling the Genesys API from Lambda using Node js

309 views Asked by At

I need to get a list of users and queues from Genesys and display them in a React/NodeJS app hosted on Amazon AWS. I want to use a Lambda function to get the lists and return them to the app.

The code here https://github.com/PrinceMerluza/prince-purecloud-aws-lambda-function/blob/master/main.py seems to be exactly what I need, once I translate from Python, but my attempt at authentication here returns an undefined access token:

 const base64 = require('../../../../../node_modules/base-64');
//import { base64 } from 'js-base64';
const { resolve } = require('path');
const platformClient = require('purecloud-platform-client-v2/dist/node/purecloud-platform-client-v2.js');
const requests = require('../../../../../node_modules/request');
   
const usersApi = new platformClient.UsersApi();
const routingApi = new platformClient.RoutingApi();
const client = platformClient.ApiClient.instance;

const CLIENT_ID = '691982c9-ef27-4c8a-b41e-181db6aecc39';
const CLIENT_SECRET = 'U2gaFlTTkou46hEF-Rwi5pFho1nu0GCnh67nHdwX_3k';

//const authorization = base64.b64encode(`${CLIENT_ID}:${CLIENT_SECRET}`).decode('ascii');

const authorization = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64');
const aut2 = Buffer.from(authorization, 'base64').toString('ascii');

const requestHeaders = {
  Authorization: `Basic ${aut2}`,
  'Content-Type': 'application/x-www-form-urlencoded',
};
const requestBody = {
  grant_type: 'client_credentials',
};

exports.handler = async (event) => {

    const response = requests.post('https://login.mypurecloud.com/oauth/token', { data: requestBody, headers: requestHeaders });

    const accessTokenInfo = response.json().access_token;

    console.log("Access Token", accessTokenInfo);
    
    return "success";
};

I think the issue is down to base64 encoding of the authorisation, but I've tried a few things and nothing works.

Is it even possible to call a Genesys API from a Lambda function? I've only found the one example and that isn't working.

1

There are 1 answers

0
Jerry Jeremiah On

So, this is how I would do it:

import platformClient from 'purecloud-platform-client-v2';

exports.handler = async (event, context, callback) => {
    // using your values
    const clientId = '691982c9-ef27-4c8a-b41e-181db6aecc39';
    const clientSecret = 'U2gaFlTTkou46hEF-Rwi5pFho1nu0GCnh67nHdwX_3k';
    
    const client = platformClient.ApiClient.instance;
    client.setEnvironment(platformClient.PureCloudRegionHosts.ap_southeast_2);
    await client.loginClientCredentialsGrant(clientId,clientSecret);
    
    let apiInstance = new platformClient.OrganizationApi();
    const organization = await apiInstance.getOrganizationsMe();
    console.log(organization);
    
    return organization;
}

But if you want to do it with request (filename is test.handler):

import request from 'request';

exports.handler = async (event, context, callback) => {

    // I do this so that I can use await on the request    
    const httpsRequest = async function(options) {
        try {
            return new Promise((resolve, reject) => {
                request(options, function (error, response) {
                    if (error) return reject(new Error(error));
                    console.log('Response: ', response.statusCode);
                    resolve(response.body);
                });
            });
        }
        catch(err) {
            return {error: err};
        }
    };
    
    // using your values
    const CLIENT_ID = '691982c9-ef27-4c8a-b41e-181db6aecc39';
    const CLIENT_SECRET = 'U2gaFlTTkou46hEF-Rwi5pFho1nu0GCnh67nHdwX_3k';
    
    const authorization = Buffer
        .from(`${CLIENT_ID}:${CLIENT_SECRET}`)
        .toString('base64');
    
    const loginHeaders = {
      Host: 'login.mypurecloud.com.au',
      Authorization: `Basic ${authorization}`,
      'Content-Type': 'application/x-www-form-urlencoded',
    };
    
    const loginBody = {
      grant_type: 'client_credentials',
    };
    
    const login_response = await httpsRequest({
        method: 'POST',
        url: 'https://login.mypurecloud.com.au/oauth/token',
        form: loginBody,
        headers: loginHeaders
    });
    
    const login = JSON.parse(login_response);
    
    const access_token = login.access_token;
    
    const requestHeaders = {
       Host: 'api.mypurecloud.com.au',
       Authorization: `Bearer ${access_token}`,
      'Content-Type': 'application/x-www-form-urlencoded',
    };
    
    const organization_response = await httpsRequest({
        method: 'GET',
        url: 'https://api.mypurecloud.com.au/api/v2/organizations/me',
        headers: requestHeaders
    });
    
    const organization = JSON.parse(organization_response);
    
    return organization;
}

If you do want to use serverless to deploy this file (like I did), you will also need a package.json:

{
  "devDependencies": {
    "serverless": "^3.17.0",
    "serverless-bundle": "^4.4.0",
    "serverless-better-credentials": "^1.1.3"
  },
  "dependencies": {
    "request": "^2.88.2"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {
      "no-unused-vars": "off"
    }
  }
}

And a serverless.yml:

service: test

frameworkVersion: ">=2.25.0"
useDotenv: true

plugins:
  - serverless-bundle
  - serverless-better-credentials

package:
  individually: true

provider:
  name: aws
  runtime: nodejs18.x
  stage: ${opt:stage, 'dev'}
  profile: ${env:SERVERLESS_PROFILE}
  region: ${opt:region, '${env:AWS_DEFAULT_REGION}'}
  deploymentBucket:
    name: ${env:SERVERLESS_DEPLOYMENT_BUCKET}
  deploymentPrefix: ${self:provider.region}
  iam:
    deploymentRole: ${env:SERVERLESS_DEPLOYMENT_ROLE}
  logRetentionInDays: 7

functions:
  test:
    handler: test.handler
    description: test - Created by Serverless
    name: ${self:service}-${self:provider.stage}-test
    memorySize: 512
    timeout: 8

And the env.dev configuration properties file:

AWS_DEFAULT_REGION=...
SERVERLESS_PROFILE=...
SERVERLESS_DEPLOYMENT_ROLE=....
SERVERLESS_DEPLOYMENT_BUCKET=...