Sunday, July 18, 2021

How to manage Zoom meeting programmatically - PART 2

Part 1 link:  How to manage Zoom meeting programmatically - PART 1

In part 1 of this blog, we understood how to register our application with Zoom to get API Key and Secret Key to be used in programmatic interaction of your application with Zoom services. Now, we will understand how to create, update and delete a zoom meeting.

package.json

{
  "name""node_zoom_exp",
  "version""1.0.0",
  "description""Manage zoom meeting programmatically",
  "main""index.js",
  "scripts": {
    "devStart""nodemon server.js",
    "test""echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "node",
    "express",
    "jsonwebtoken"
  ],
  "author""Jitendra Kumar Singh",
  "license""ISC",
  "dependencies": {
    "axios""^0.21.1",
    "dotenv""^8.2.0",
    "express""^4.17.1",
    "jsonwebtoken""^8.5.1",
    "request""^2.88.2",
    "request-promise""^4.2.6"
  },
  "devDependencies": {
    "nodemon""^2.0.7"
  }
}

Different routes in our node js service

var express = require('express');
const util = require("../utils/util");
const ctrl = require("../controllers/mycontroller");
const auth = require("../middlewares/auth");

var router = express.Router();

router.get('/'ctrl.healthCheck);
router.post('/zoomuserInfo'auth.addTokenctrl.zoomuserInfo);
router.post('/createzoommeeting'auth.addTokenctrl.createZoomMeeting);
router.post('/zoommeeting'auth.addTokenctrl.getMeeting);
router.patch('/updatezoommeeting'auth.addTokenctrl.updateMeeting);
router.delete('/deletezoommeeting'auth.addTokenctrl.deleteMeeting);

module.exports = router;

JWT Token for authentication and authorization on zoom side

In every interaction of our application with Zoom services, we have to send JWT token for authentication and authorization to Zoom service. This JWT token is created by using API Key and Secret key that we have received during registration of our application with zoom market place. I am creating this JWT token in a middleware function in auth.js file

const config = require("../../config");
const jwt = require("jsonwebtoken");

//Use the ApiKey and APISecret from config.js
const payload = {
    iss: config.APIKey,
    exp: ((new Date()).getTime() + 5000)
};
const token = jwt.sign(payloadconfig.APISecret);

function addToken(reqresnext) {
    req.body["token"] = token;
    next();
}

module.exports = { addToken }

I have kept API Key and Secret Key in a config file named as config.js as follows:

const env = process.env.NODE_ENV || 'production'

/**
 * insert your API Key & Secret for each environment 
 * keep this file local and never push it to a public repo for security purposes.
 */
const config = {
    development :{
        APIKey : 'my_apikey_dev_env',
        APISecret : 'my_apisecretkey_dev_env'
    },
    production:{    
        APIKey : 'my_apikey_prod_env',
        APISecret : 'my_apisecretkey_prod_env'
    }
};

module.exports = config[env]

Code for different operation with Zoom meeting

Here, I am giving the code for below operation like 

  • Get details of the user whose email Id is registered with Zoom market place and going to be used as a host email id for all zoom meetings
  • Creating a zoom meeting
  • Update a meeting by changing the meeting time, meeting agenda etc.
  • Delete a meeting
  • Get the details of a meeting
I have added all these code a file mycontroller.js

const SendResponse = require("../utils/sendresponse");
const axios = require('axios');
const sendResponse = new SendResponse();

//Health check function
function healthCheck(reqresnext) {
  try {
    sendResponse.setSuccess(200'Success'"API is running");
    return sendResponse.send(res);
  } catch (error) {
    console.log(error);
  }
}
//Get user detail of host user
async function zoomuserInfo(reqresnext) {
  try {
    const token = req.body.token;
    const email = 'abc@xyz.com'; //host email id
    const result = await axios.get("https://api.zoom.us/v2/users/" + email, {
      headers: {
        'Authorization': 'Bearer ' + token,
        'User-Agent': 'Zoom-api-Jwt-Request',
        'content-type': 'application/json'
      }
    });
    sendResponse.setSuccess(200'Success'result.data);
    return sendResponse.send(res);
  } catch (error) {
    console.log(error.message);
    next();
  }
}
//Create a zoom meeting
async function createZoomMeeting(reqresnext) {
  try {
    const token = req.body.token;
    const email = 'abc@xyz.com'; //host email id;
    const result = await axios.post("https://api.zoom.us/v2/users/" + email + "/meetings", {
      "topic": "Discussion about today's Demo",
      "type": 2,
      "start_time": "2021-03-18T17:00:00",
      "duration": 20,
      "timezone": "India",
      "password": "1234567",
      "agenda": "We will discuss about Today's Demo process",
      "settings": {
        "host_video": true,
        "participant_video": true,
        "cn_meeting": false,
        "in_meeting": true,
        "join_before_host": false,
        "mute_upon_entry": false,
        "watermark": false,
        "use_pmi": false,
        "approval_type": 2,
        "audio": "both",
        "auto_recording": "local",
        "enforce_login": false,
        "registrants_email_notification": false,
        "waiting_room": true,
        "allow_multiple_devices": true
      }
    }, {
      headers: {
        'Authorization': 'Bearer ' + token,
        'User-Agent': 'Zoom-api-Jwt-Request',
        'content-type': 'application/json'
      }
    });
    sendResponse.setSuccess(200'Success'result.data);
    return sendResponse.send(res);
  } catch (error) {
    console.log(error.message);
    next();
  }
}
//Update a zoom meeting
async function updateMeeting(reqresnext) {
  try {
    const token = req.body.token;
    const meetingId = req.body.meetingId;
    const result = await axios.patch("https://api.zoom.us/v2/meetings/" + meetingId, {
      "topic": "UPDATE: Discussion about today's Demo",
      "type": 2,
      "start_time": "2021-03-18T17:00:00",
      "duration": 20,
      "timezone": "India",
      "password": "1234567",
      "agenda": "Discussion about how to update zoome meeting programatically",
      "settings": {
        "host_video": true,
        "participant_video": true,
        "cn_meeting": false,
        "in_meeting": true,
        "join_before_host": false,
        "mute_upon_entry": false,
        "watermark": false,
        "use_pmi": false,
        "approval_type": 2,
        "audio": "both",
        "auto_recording": "local",
        "enforce_login": false,
        "registrants_email_notification": false,
        "waiting_room": true,
        "allow_multiple_devices": true
      }
    }, {
      headers: {
        'Authorization': 'Bearer ' + token,
        'User-Agent': 'Zoom-api-Jwt-Request',
        'content-type': 'application/json'
      }
    });
    sendResponse.setSuccess(200'Success'result.data);
    return sendResponse.send(res);
  } catch (error) {
    console.log(error.message);
    next();
  }
}
//Delete a zoom meeting
async function deleteMeeting(reqresnext) {
  try {
    const token = req.body.token;
    const meetingId = req.body.meetingId;
    const result = await axios.delete("https://api.zoom.us/v2/meetings/" + meetingId, {
      headers: {
        'Authorization': 'Bearer ' + token,
        'User-Agent': 'Zoom-api-Jwt-Request',
        'content-type': 'application/json'
      }
    });
    sendResponse.setSuccess(200'Success'result.data);
    return sendResponse.send(res);
  } catch (error) {
    console.log(error.message);
    next();
  }
}
//Get details of a zoom meeting
async function getMeeting(reqresnext) {
  try {
    const token = req.body.token;
    const meetingId = req.body.meetingId;
    const result = await axios.get("https://api.zoom.us/v2/meetings/" + meetingId, {
      headers: {
        'Authorization': 'Bearer ' + token,
        'User-Agent': 'Zoom-api-Jwt-Request',
        'content-type': 'application/json'
      }
    });
    sendResponse.setSuccess(200'Success'result.data);
    return sendResponse.send(res);
  } catch (error) {
    console.log(error.message);
    next();
  }
}

module.exports = { 
  healthCheckzoomuserInfocreateZoomMeetinggetMeeting
  updateMeetingdeleteMeeting 
}

Thus, we can trigger different services of zoom to perform several operation. We can create recurance meeting too programmatically. We can follow below link to get more information about several zoom services available for programmatica use.

https://marketplace.zoom.us/docs/api-reference/zoom-api/meetings/

4 comments:

  1. how can I add registrants_email_notification :false here

    ReplyDelete
    Replies
    1. I haven't tried with this email notification flag in my poc. Once I will try, I will update you. By that time, once you try to go through the discussion on zoom dev forum(link given below). You may get some idea. https://devforum.zoom.us/t/registrants-confirmation-email-vs-registrants-email-notification/12113/6

      Delete
  2. can you please provide source code?

    ReplyDelete
  3. Right now I dont have the source code. I had made the POC and forgot to commit in github.

    ReplyDelete

Please provide your precious comments and suggestion