Part 1: Section 2 - Building a meeting application in React with Zoom APIs and SDKs

justzoomit

just-zoomit

Posted on February 7, 2023

Part 1: Section 2 - Building a meeting application in React with Zoom APIs and SDKs

Set up Zoom Rest APIs & Meeting SDK Backend integrations

In the first part of this blog we setup Node.js/Express, organized the files in a way that makes maintenance easy, and used the .env file to securely store the API & SDK keys and secrets. Now we ready to add the backend logic.

Install dependencies for Meeting SDK JWT

Now let's set up our Meeting SDK JWT SDK signature endpoint which will be used to authorize the Meeting SDK. To begin, in the root folder, run the following command to install the required dependencies:

npm i axios btoa jsrsasign
Enter fullscreen mode Exit fullscreen mode

API File

Now we are ready to add our functions to api file which making the HTTP requests and processing the responses from the Zoom Rest APIs. In the api/api.js file, add the following functions to the code:


// Working File: api/api.js

require("dotenv").config();
const axios = require("axios");
const btoa = require("btoa");

const getAccessToken = async () => {
  try {
    base_64 = btoa(process.env.CLIENT_ID + ":" + process.env.CLIENT_SECRET);

    const resp = await axios({
      method: "POST",
      url:
        "https://zoom.us/oauth/token?grant_type=account_credentials&account_id=" +
        `${process.env.ACCOUNT_ID}`,
      headers: {
        Authorization: "Basic " + `${base_64} `,
      },
    });

    return resp.data.access_token;
  } catch (err) {
    // Handle Error Here
    console.error(err);
  }
};

const listZoomMeetings = async () => {
  try {
    const resp = await axios({
      method: "get",
      url: "https://api.zoom.us/v2/users/me/meetings",
      headers: {
        Authorization: "Bearer " + `${await getAccessToken()} `,
        "Content-Type": "application/json",
      },
    });
    const meetings = resp.data.meetings;

    const newArray = meetings.map((obj) =>
      ["id", "topic"].reduce((newObj, key) => {
        newObj[key] = obj[key];
        return newObj;
      }, {})
    );

    return newArray;
  } catch (err) {
    if (err.status == undefined) {
      console.log("Error : ", err);
    }
  }
};

const createZoomMeeting = async (type) => {
  try {


    const data = JSON.stringify({
      type: type,
    });

    const resp = await axios({
      method: "post",
      url: "https://api.zoom.us/v2/users/me/meetings",
      headers: {
        Authorization: "Bearer " + `${await getAccessToken()} `,
        "Content-Type": "application/json",
      },
      data: data,
    });

    const { id, password } = resp.data;

    return { id, password };
  } catch (err) {
    if (err.status == undefined) {
      console.log("Error : ", err);
    }
  }
};
function generateOTP() {
  var digits = "0123456789";
  let OTP = "";
  for (let i = 0; i < 6; i++) {
    OTP += digits[Math.floor(Math.random() * 10)];
  }
  return OTP;
}

// ...

module.exports = {
  createZoomMeeting, 
  listZoomMeetings,
  thirdPartyAPICall,
};

Enter fullscreen mode Exit fullscreen mode

Controllers File

The next thing we need to implement are the functions that will be called from the routes to perform the desired actions. In controllers/Zoomcontrollers.js file, add the following Application functions:

  • Meeting SDK JWT signature generation endpoint for authorized use of the Meeting SDK.

  • Create Appointment Endpoint, which handle creating Zoom Meetings.

  • List Meeting Endpoint, which handles get Zoom Meetings.

// Working File: controllers/Zoomcontrollers.js

const asyncHandler = require("express-async-handler");

require("dotenv").config();
const KJUR = require("jsrsasign");

const {
  createZoomMeeting,
  listZoomMeetings,
  thirdPartyAPICall,
  } = require("../api/zoomAPI.js");

  const getMsdkSignature = asyncHandler(async (req, res) => {
    const iat = Math.round(new Date().getTime() / 1000) - 30;
    const exp = iat + 60 * 60 * 2;

    const oHeader = { alg: "HS256", typ: "JWT" };

    const oPayload = {
      sdkKey: process.env.ZOOM_MSDK_KEY,
      mn: req.body.meetingNumber,
      role: req.body.role,
      iat: iat,
      exp: exp,
      tokenExp: iat + 60 * 60 * 2,
    };

    const sHeader = JSON.stringify(oHeader);
    const sPayload = JSON.stringify(oPayload);
    const signature = KJUR.jws.JWS.sign(
      "HS256",
      sHeader,
      sPayload,
      process.env.ZOOM_MSDK_SECRET
    );

    res.json({
      signature: signature,
    });
  });

const CreateAppointment = asyncHandler(async (req, res) => {
  const { type} = req.body;

  if (!type) {
    res.status(400);
    throw new Error("Please Fill all the fields");
  } else {
    const { id, password } = await createZoomMeeting(type);

    res.status(201).json({ id, password });
  }
});


  const ListMeeting = asyncHandler(async (req, res) => {
    const meetings = await listZoomMeetings();
    if (meetings === undefined) {
      res.status(400);
      throw new Error("No meeting found");
    } else {
      res.status(201).json({ meetings });
    }
  });


// ...

   module.exports = {
    getMsdkSignature,
    CreateAppointment,
    ListMeeting,
    ThirdPartyAPICall,
  };


Enter fullscreen mode Exit fullscreen mode

routes File

Next, all we need to do is define the endpoint URLs that will maps incoming requests to the functions. In the zoomRoutes.js, add the getMsdkSignature, CreateAppointment, and ListMeeting endpoints.

// WorkDirectory : backend/routes/
// File : zoomRoutes.js

const express = require('express');
const router = express.Router();
const {
    getMsdkSignature,
    CreateAppointment,
    ListMeeting,
    ThirdPartyAPICall,
  } = require("../controllers/zoomControllers.js");

router.route('/').post();

// Get MSDK Signature Route
router.route("/msig").post(getMsdkSignature);

// Create routes. Test with Postman
router.route("/create").post(CreateAppointment);

// Create routes Test with Postman
router.route("/listmeetings").get(ListMeeting);

// Get routes Test with Postman
router.route("/thirdparty").get(ThirdPartyAPICall);

module.exports = router; // Export the router so it can be used in server.js

Enter fullscreen mode Exit fullscreen mode

The last thing we need to configure before testing the backend integration with Zoom API and SDK service is the .env file. This file contains the Zoom Rest APIs and MSDK credentials that should not be accessible to others. It is important to note,your Zoom credential should be stored locally and not be uploaded to code repositories online for everyone to read.

In the .env file, add the following code, and insert your Zoom API and Meeting SDK Apps's Key and Secret found on the App Credentials page in the Zoom App Marketplace.

PORT = 30010

# Zoom API Credentials
ACCOUNT_ID = YOUR_ACCOUNT_ID

CLIENT_ID = YOUR_CLIENT_ID

CLIENT_SECRET = YOUR_CLIENT_SECRET

ZOOM_MSDK_KEY =YOUR_ZOOM_MSDK_KEY

ZOOM_MSDK_SECRET =YOUR_ZOOM_MSDK_SECRET

Enter fullscreen mode Exit fullscreen mode

Test with Postman

Now it is time to test with Postman and observe the results of GET request for listmeeting and msig endpoints.You should see your Zoom meeting in the response, assuming you have meetings scheduled !

Image description

You should see your Zoom MSDK Signature in the response!

Image description

{
    "signature": "YOUR_SIGNATURE_RETURNED"
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this tutorial, you created a Node.js / Express server that generates a Zoom Server-to-Server OAuth Token and a Meeting SDK signature via an http request from your frontend for use in the Meeting Conference React Application. In the next section, we will add the frontend for the application to the project.

πŸ’– πŸ’ͺ πŸ™… 🚩
justzoomit
just-zoomit

Posted on February 7, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related