Integrating zoom in a meteor application or any web application isn't hard by any means, nevertheless I needed a week or so to figure out everything from reading countless pages of documentation, forum articles, code samples, and also from a lot of trial and error.
So here I put a step by step guide to how I did it.
this tutorial is not limited to a meteor project, the steps will apply to any web application.
I. Get your credentials
1. Create a zoom account:
First of all, you need to have a zoom account, you can create it from here zoom.
2. Creating a Jwt application
JWT or Json Web Token is an Internet standard for creating data with optional signature and/or optional encryption whose payload holds JSON that asserts some number of claims.
You will need it to make calls to the zoom API to create,update,end... meetings.
- Go to zoom marketplace, and go to Developer > Build app:
- create a JWT app, and complete your informations to get your api key and secret: You must keep your api key and secret in the backend, They are used to generate Jwt tokens and signatures.
II. On the server side
1. generate Jwt token
Add this method to generate the token
import { Meteor } from "meteor/meteor";
import { JWT } from "jose";
const { ZOOM_JWT_API_KEY, ZOOM_JWT_API_SECRET } = Meteor.settings.private;
export const generateJWTToken = () => {
const header = { alg: "HS256", typ: "JWT" };
const payload = { iss: ZOOM_JWT_API_KEY, exp: new Date().getTime() + 30 * 60 * 1000 };
return JWT.sign(payload, ZOOM_JWT_API_SECRET, { header });
};
2. create a meeting:
// prepare the request body
const data = {
topic: "a topic for the meeting",
type: 1, // this is an instant meeting
duration: 90,
password: Random.secret(9), // a passphrase to secure access to the meeting
agenda: "description",
settings: { // you can override settings as you wish
host_video: true,
participant_video: false,
cn_meeting: false,
in_meeting: false,
waiting_room: false,
join_before_host: false,
mute_upon_entry: true,
watermark: false,
use_pmi: false,
approval_type: 0,
registration_type: 1,
audio: "voip",
auto_recording: false,
show_share_button: true,
},
};
// prepare the request headers
const zoomHeaders = {
Authorization: `Bearer ${ generateJWTToken() }`,
};
const result = HTTP.post("https://api.zoom.us/v2/users/me/meetings", { data, headers: zoomHeaders });
The result returned will contain the meeting id and password, you need to store them somewhere.
3. generate the signature to join a meeting:
Add this method to your backend when a user want to join a meeting he needs to call it to generate a signature
const { ZOOM_JWT_API_KEY, ZOOM_JWT_API_SECRET } = Meteor.settings.private;
const generateSignature = (meetingNumber: number, role: number) => {
const timestamp = new Date().getTime() - 30000;
const msg = Buffer.from(ZOOM_JWT_API_KEY + meetingNumber + timestamp + role).toString("base64");
const hash = crypto.createHmac("sha256", ZOOM_JWT_API_SECRET).update(msg).digest("base64");
const signature = Buffer.from(`${ ZOOM_JWT_API_KEY }.${ meetingNumber }.${ timestamp }.${ role }.${ hash }`).toString("base64");
return signature;
};
meetingNumber: is the meeting id.
role: is an integer that take the values 0 for a participant and 1 for a host.
The server will also need to return this informations:
{
signature, //using generateSignature
meetingNumber: id,
password, //returned from create meeting
userName: `${ lastName } ${ firstName }`,
role,
apiKey: ZOOM_JWT_API_KEY,
}
4. End the meeting:
This is similar to creating a meeting:
const data = {
action: "end",
};
const zoomHeaders = {
Authorization: `Bearer ${ generateJWTToken() }`,
};
const result = HTTP.put(`https://api.zoom.us/v2/meetings/${ meeting.id }/status`, { data, headers: zoomHeaders });
console.error(result);
III. On the client side:
1. add zoom web-sdk
- Using CDN
<!-- CSS -->
<link type="text/css" rel="stylesheet" href="https://source.zoom.us/1.8.1/css/bootstrap.css" />
<link type="text/css" rel="stylesheet" href="https://source.zoom.us/1.8.1/css/react-select.css" />
<!-- JS -->
<script src="https://source.zoom.us/1.8.1/lib/vendor/react.min.js"></script>
<script src="https://source.zoom.us/1.8.1/lib/vendor/react-dom.min.js"></script>
<script src="https://source.zoom.us/1.8.1/lib/vendor/redux.min.js"></script>
<script src="https://source.zoom.us/1.8.1/lib/vendor/redux-thunk.min.js"></script>
<script src="https://source.zoom.us/1.8.1/lib/vendor/jquery.min.js"></script>
<script src="https://source.zoom.us/1.8.1/lib/vendor/lodash.min.js"></script>
<script src="https://source.zoom.us/zoom-meeting-1.8.1.min.js"></script>
This may varry if you are in China or India
more details in this page.
- Using a package manager
npm i @zoomus/websdk
```
####2. Joining a meeting
* Config
You will need this config returned from the serve:
```js
var meetingConfig = {
apiKey: tmpArgs.apiKey, // required
meetingNumber: tmpArgs.meetingNumber, // required
userName: tmpArgs.userName, // required
passWord: tmpArgs.password, // required
leaveUrl: "/index.html", //if a user quite or couldn't join the meeting he will be redirected to this Url
userEmail: tmpArgs.email, // optional
lang: tmpArgs.lang, // optional
signature: tmpArgs.signature, // required
};
```
* Prepare dependencies:
```js
ZoomMtg.preLoadWasm();
ZoomMtg.prepareJssdk();
```
* Join:
```js
ZoomMtg.init({
leaveUrl: meetingConfig.leaveUrl,
webEndpoint: meetingConfig.webEndpoint,
isSupportAV: true, //optional,
isSupportChat: false, //optional,
isSupportQA: false, //optional,
isSupportCC: false, //optional,
screenShare: true, //optional,
sharingMode: 'both',
disableInvite: true, //optional
disableRecord: false, //optional
audioPanelAlwaysOpen: false,
success: function () {
console.log(meetingConfig);
$.i18n.reload(meetingConfig.lang);
ZoomMtg.join({
meetingNumber: meetingConfig.meetingNumber,
userName: meetingConfig.userName,
signature: signature,
apiKey: meetingConfig.apiKey,
userEmail: meetingConfig.userEmail,
passWord: meetingConfig.passWord,
success: function (res) {
console.log("join meeting success");
console.log("get attendeelist");
ZoomMtg.getAttendeeslist({});
ZoomMtg.getCurrentUser({
success: function (res) {
console.log("success getCurrentUser", res.result.currentUser);
},
});
},
error: function (res) {
console.error(res);
},
});
},
error: function (res) {
console.error(res);
},
});
```
####3. Add events to log user activities
```js
ZoomMtg.inMeetingServiceListener('onUserJoin', function (data) {
console.log('inMeetingServiceListener onUserJoin', "*", data);
});
ZoomMtg.inMeetingServiceListener('onUserLeave', function (data) {
console.log('inMeetingServiceListener onUserLeave', "*", data);
});
ZoomMtg.inMeetingServiceListener('onUserIsInWaitingRoom', function (data) {
console.log('inMeetingServiceListener onUserIsInWaitingRoom', data);
});
ZoomMtg.inMeetingServiceListener('onMeetingStatus', function (data) {
console.log('inMeetingServiceListener onMeetingStatus', data);
});
```
###IV. Conclusion
Now you should have a working zoom integration. I hope this article was useful.
Thanks for reading, and I will be in the comments for your suggestions, remarks, advice...
Top comments (3)
Hi I am having error
It was working in a non meteor environment.
Any Idea on this? Thanks
Hello, make sure you test it on chrome and in a normal tab, in my experience it doesn't load some libraries in incognito mode.
Also don't forget to call
ZoomMtg.preLoadWasm();
ZoomMtg.prepareJssdk();
And if nothing works, call this before preLoadWasm
ZoomMtg.setZoomJSLib("source.zoom.us/1.8.1/lib", "/av");
Here you can find a working example
github.com/medelmourabite/ttp-zoom...
Hi Do you have a working sample on a meteor environment?