Zoom web sdk integration is not working

Hey @michael.harrington,

Please help with this. They are following your sample app. :slight_smile:

Thanks,
Tommy

@taushifali @tommy

For future reference, I don’t believe this issue is related to the sample app used.

Todd, can you provide us any info on the errors you’re receiving? This is not expected behavior (or true); an API Key/Secret is used by the owner of the Web SDK app. With appropriate Meeting IDs, email / username fields when joining, and user access (like passwords), the Web SDK methods can be used to join any number of users into a meeting.

Thanks @michael.harrington for your response over this.

Let me clarify more on this issue.
I am trying to use same API key and API secret to host/join two parallel meetings. But I am not able to join two parallel meetings(different meeting Ids), where API Key and API Secret are same.

Error: Your connection has timed out and you cannot join the meeting. Verify your network connectivity and try again.

How can I achieve this, is there anyway that I don’t need to generate API Key and API Secret for all the users.

Hey @taushifali,

This should be possible when using role 0.

Can you share your signature so I can debug further?

Thanks,
Tommy

Hey @tommy,
Thanks for replying.

I am looking this for role 1.

If it is not possible to join as host, with same API key and API secret, in two or more parallel meetings.
Is there any automated way, like some zoom API’s, to generate API key and API secret for all my users?
Or I have to create API key and API secret from zoom market place?

Hey @taushifali,

You should be able to start multiple different meetings that you own using the Web SDK.

Are you generating a new seperate signature for each one?

Thanks,
Tommy

Hey @tommy,
As signature is dependent on time and meetingId. Hence yes, I am generating different signatures for different meetings.

const generateSignature = (credentials, meetingNumber, role) => {
  const timestamp = new Date().getTime() - 30000;
  const msg = Buffer.from(credentials.apiKey + meetingNumber + timestamp + role).toString('base64');
  const hash = Crypto.createHmac('sha256', credentials.apiSecret).update(msg).digest('base64');
  return Buffer.from(`${credentials.apiKey}.${meetingNumber}.${timestamp}.${role}.${hash}`).toString('base64');
};

And I am not able to join two meetings in parallel as host.

Can you please elaborate on what you mean by:

start multiple different meetings that you own using the Web SDK.

As I am able to start multiple meetings with same Web SDK, but not able to start two meetings in parallel as host.

Thanks
Taushif

Hey @taushifali,

To clarify, my question is, are the multiple meetings being created for the same user (host)?

It should work if each meeting is created for a seperate user, see my teammates post here:

For example it should work in this scenario:

Meeting A created by user A on your account.

Meeting B created by user B on your account.

Not, Meeting A and B created by user A.

Thanks,
Tommy

Hello, Im solving same problem as you did in the past and I cant move from that “black screen” as you described. I followed all your steps but I still cant move from that place. It seems that I have problem with some ZoomMtg settings because in console I see “Before mounting” and “After mounting” but also only blackscreen in browser. Can you please describe to me, how you solved it? Thank you for answer. Here are all my files connected to Stream React component. I tried also variants without css styling component and with CDN imports in index.html, but still not working.
Stream.tsx

import { Component } from “react”;
import React from “react”;
import {ZoomMtg} from ‘@zoomus/websdk’;
const zoomMeeting = document.getElementById(“zmmtg-root”)
const meetConfig = {
apiKey: MY_JWT_API_KEY,
apiSecret: MY_JWT_API_SECRET,
meetingNumber: MY_PERSONAL_ID_NUMBER,
leaveUrl: ‘https://zoom.us’,
userName: USER_NAME,
passWord: ‘’, // if required
role: 1 // 1 for host; 0 for attendee or webinar
};

export class Stream extends Component<{},{meetingLaunched: boolean}> {

constructor(props) {
    super(props);
    this.state = { meetingLaunched : false}
}

joinZoomMeeting = () => {
console.log(‘checkSystemRequirements’);
console.log(JSON.stringify(ZoomMtg.checkSystemRequirements()));
ZoomMtg.generateSignature({
meetingNumber: meetConfig.meetingNumber,
apiKey: meetConfig.apiKey,
apiSecret: meetConfig.apiSecret,
role: meetConfig.role,
success(res) {
console.log(‘signature’, res.result);
ZoomMtg.init({
leaveUrl: meetConfig.leaveUrl,
success() {
ZoomMtg.join(
{
meetingNumber: meetConfig.meetingNumber,
userName: meetConfig.userName,
signature: res.result,
apiKey: meetConfig.apiKey,
passWord: meetConfig.passWord,
success() {
console.log(‘join meeting success’);
},
error(respo) {
console.log(respo);
}
}
);
},
error(response) {
console.log(response);
}
});
}
});
};

render() {
return (


{this.state.meetingLaunched ?
Launch Meeting
:
<></>
}

)
}

componentDidMount() {
console.log(“Before mounting.”)
setTimeout(() => {
ZoomMtg.setZoomJSLib(“https://source.zoom.us/1.7.7/lib”, “/av”);
ZoomMtg.preLoadWasm();
ZoomMtg.prepareJssdk();
}, 6000);
console.log(“After mounting.”)
}

}
index.html

App.css

#zmmtg-root {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  background-color: black;

}

Hey @hrondor,
What are you getting for checkSystemRequirements in console?
Is your ZoomMtg loading fine?

Did you managed properly the zmmtg-root display properties as from the post Zoom Meeting Custom Ui.

What are you seeing in DOM’s network tab for the bootstrap.css and react-select.css?

I am pasting my current code, let me know if you get it worked with this.

import React, { Component } from 'react';
import { ZoomMtg } from '@zoomus/websdk';
import connect from 'src/apiClient';
import PropTypes from 'prop-types';
import { PromiseState } from 'react-refetch';
import PromiseStateContainer from '../../PromiseStateContainer';
import { createVideoConference } from '../../../services/videoConferencing.service';
import { selfUrl } from 'src/config';

const zoomMeeting = document.getElementById('zmmtg-root');

class ZoomConference extends Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    meetingDetails: PropTypes.instanceOf(PromiseState).isRequired
  };

  constructor(props) {
    super(props);
    this.state = {
      userEmail: 'myemail'
    };
  }

  componentDidMount() {
    ZoomMtg.setZoomJSLib('https://source.zoom.us/1.7.7/lib', '/av');
    ZoomMtg.preLoadWasm();
    ZoomMtg.prepareJssdk();
  }

  launchMeeting = () => {
    
    // change state of meeting
    this.setState({ meetingLaunched: !this.state.meetingLaunched })

    // generateSignature should only be used in development
    ZoomMtg.generateSignature({
        meetingNumber: meetConfig.meetingNumber,
        apiKey: meetConfig.apiKey,
        apiSecret: meetConfig.apiSecret,
        role: meetConfig.role,
        success(res) {
            console.log('signature', res.result);
            ZoomMtg.init({
                leaveUrl: 'http://www.zoom.us',
                success() {
                    ZoomMtg.join(
                        {
                            meetingNumber: meetConfig.meetingNumber,
                            userName: meetConfig.userName,
                            signature: res.result,
                            apiKey: meetConfig.apiKey,
                            userEmail: 'email@gmail.com',
                            passWord: meetConfig.passWord,
                            success() {
                                console.log('join meeting success');
                            },
                            error(res) {
                                console.log(res);
                            }
                        }
                    );
                },
                error(res) {
                    console.log(res);
                }
            });
        }
    });
}


  render() {
    zoomMeeting.style.display = 'none';
    zoomMeeting.style.height = '0px';
    zoomMeeting.style.width = '0px';
    zoomMeeting.style.position = 'relative';
    zoomMeeting.style.backgroundColor = 'black';
    zoomMeeting.style.zIndex = '1';
    return (
      <span>{this.launchMeeting()}</span>
    );
  }
}

Index.html

<!DOCTYPE html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0" />
  <link type="text/css" rel="stylesheet" href="https://source.zoom.us/1.7.7/css/bootstrap.css" />
  <link type="text/css" rel="stylesheet" href="https://source.zoom.us/1.7.7/css/react-select.css" />
</head>
<body>
<div id='root'></div>
<script src="https://source.zoom.us/1.7.7/lib/vendor/jquery.min.js"></script>
</body>
1 Like

Thank you very much for help and fast answer!:slight_smile: So I advanced, when I give render and ZoomMeeting this parameters, I see 100x200px blue window in left of my page(empty without call). When I click to button Im redirected to full screen Zoom call, but when I put

<div id="zmmtg-root"></div>

instead of that button in render, I see again only black screen.

render() {
console.log(“Rendering.”)
if (zoomMeeting != null) {
zoomMeeting.style.height = ‘100px’;
zoomMeeting.style.width = ‘200px’;
zoomMeeting.style.position = ‘relative’;
zoomMeeting.style.backgroundColor = ‘blue’;
zoomMeeting.style.zIndex = ‘1’;
}
return (
<>
{!this.state.meetingLaunched ?

        <button className="launchButton" onClick={this.joinZoomMeeting}>Launch Meeting</button> 
    : 
    <></>
    }
</>
)
}

App.css

#zmmtg-root {
  width: 200px;
  height: 200px;
  position: relative;
}

Hey @hrondor,
You need to change the state this.state.meetingLaunched in joinZoomMeeting function, do this in first line => this.setState({ meetingLaunched: !this.state.meetingLaunched }).
As render function will be called again.

You need to turn off display of div “zmmtg-root” while rendering your page.

As div “zmmtg-root” is where zoom meeting UI loads.
You need to turn on again display of div “zmmtg-root” when you are joining zoom call.

For example you can call turnItOff in render method and turnItOn in joinZoomMeeting method.

 const turnItOn = () => {
    zoomMeeting.style.display = 'flex'
    zoomMeeting.style.height = '100%'
    zoomMeeting.style.width = '100%'
    zoomMeeting.style.position = 'fixed'
    zoomMeeting.style.zIndex = '1'
    zoomMeeting.style.backgroundColor = 'black'
  }

  const turnItOff = () => {
    zoomMeeting.style.display = 'none'
    zoomMeeting.style.height = '0px'
    zoomMeeting.style.width = '0px'
    zoomMeeting.style.position = 'relative'
    zoomMeeting.style.backgroundColor = 'black'
    zoomMeeting.style.zIndex = '1'
  }

It will be be more helpful if you add your whole file and attach screenshots in order to debug this.

One more thank you for help!:slight_smile: If I run site with that Stream.tsx component, I can see button and normal white site, If I click to the button, which should invoke Zoom call, site is black with blue square in the left. And no call is invoked. I tried variant without switch, only with button component and no else method,call was started, but in full screen.
https://pastebin.com/pqba8G9s (App.tsx + Stream.tsx without meetConfig object only)
https://pastebin.com/ZNa7Mv0y(index.html + App.css) - I dont think its problem in App.css because all changes here seems without effect

Sorry I can attach only 2 links, so I had to connect 2 files in one paste bin:)

Hey @hrondor,
I think you are missing meeting configs, you need to generate API key and API secret as well as you need valid meeting Id and password to join meeting.

Check this out, it is working fine:-

import { Component } from 'react';
import React from 'react';
import { ZoomMtg } from '@zoomus/websdk';
import { Card } from 'dashboard-modules/atoms';

const zoomMeeting = document.getElementById('zmmtg-root');
const meetConfig = {
  apiKey: 'YOUR_API_KEY',
  apiSecret: 'YOUR_API_SECRET',
  meetingNumber: YOUR_MEETING_ID,
  leaveUrl: 'https://zoom.us',
  userName: 'USER_NAME',
  passWord: 'YOUR_PASSWORD', // if required
  role: 1 // 1 for host; 0 for attendee or webinar
};

class ZoomConference extends Component {
  constructor(props) {
    super(props);
    this.state = { meetingLaunched: false };
    this.turnItOff();
  }

  componentDidMount() {
    console.log('Before mounting.');
    setTimeout(() => {
      ZoomMtg.setZoomJSLib('https://source.zoom.us/1.7.7/lib', '/av');
      ZoomMtg.preLoadWasm();
      ZoomMtg.prepareJssdk();
    }, 6000);
    console.log('After mounting.');
  }

  turnItOn = () => {
    if (zoomMeeting != null) {
      zoomMeeting.style.display = 'flex';
      zoomMeeting.style.height = '100%';
      zoomMeeting.style.width = '100%';
      zoomMeeting.style.position = 'fixed';
      zoomMeeting.style.zIndex = '1';
      zoomMeeting.style.backgroundColor = 'blue';
    }
  }

  turnItOff = () => {
    if (zoomMeeting != null) {
      zoomMeeting.style.display = 'none';
      zoomMeeting.style.height = '0px';
      zoomMeeting.style.width = '0px';
      zoomMeeting.style.position = 'relative';
      zoomMeeting.style.backgroundColor = 'black';
      zoomMeeting.style.zIndex = '1';
    }
  };

  joinZoomMeeting = () => {
    this.setState({ meetingLaunched: !this.state.meetingLaunched });
    console.log('checkSystemRequirements');
    console.log(JSON.stringify(ZoomMtg.checkSystemRequirements()));
    ZoomMtg.generateSignature({
      meetingNumber: meetConfig.meetingNumber,
      apiKey: meetConfig.apiKey,
      apiSecret: meetConfig.apiSecret,
      role: meetConfig.role,
      success(res) {
        console.log('signature', res.result);
        ZoomMtg.init({
          leaveUrl: meetConfig.leaveUrl,
          success() {
            console.log('Sucess');
            ZoomMtg.join(
              {
                meetingNumber: meetConfig.meetingNumber,
                userName: meetConfig.userName,
                signature: res.result,
                apiKey: meetConfig.apiKey,
                passWord: meetConfig.passWord,
                success() {
                  console.log('join meeting success');
                },
                error(respo) {
                  console.log(respo);
                }
              }
            );
          },
          error(response) {
            console.log(response);
          }
        });
      }
    });
  };

  render() {
    if (!this.state.meetingLaunched) {
      this.turnItOff();
    } else {
      this.turnItOn();
    }
    console.log('Rendering.');
    if (zoomMeeting != null) {
      zoomMeeting.style.height = '500px';
      zoomMeeting.style.width = '200px';
      zoomMeeting.style.position = 'relative';
      zoomMeeting.style.zIndex = '1';
    }
    return (
      <Card>
        {!this.state.meetingLaunched ?

          <button className="launchButton" onClick={this.joinZoomMeeting}>Launch Meeting</button>
          :
          <div id="zmmtg-root" />
        }
      </Card>
    );
  }
}
export default ZoomConference;

To generate API key and API secret:

  1. Create zoom account, sign in your account if already have.
  2. Go to https://marketplace.zoom.us/, and click sign in on top right corner.
  3. Go to develop -> Build App
  4. Create JWT app.
  5. Add details and not down your API key and API secret.

I only deleted my meetConfig details, because I didnt want to share API + API_SECRET but it shouldnt be problem with it, because as I wrote I was able to connect properly when I had only without switch to

.

Hey @hrondor,
I didn’t get the switch part, anyways seems it is working for you.

Thanks for all help, I did some steps to finish my problems but its still not working properly, I think that the problem is that Call from Zoom isnt showing in

<div id="zmmtg-root" />

component and rest of screen is black when call should be started. I will try to go through all steps again and maybe I would be succesfull. In every possible way thanks for you help and time:)

EDIT:I can see 2

<div id="zmmtg-root" />

components in browser debugger.

Hey @hrondor,
There are 2 div zmmtg-root cause one is loaded by zoom web sdk and other one is coming from your render method, you don’t need to add div zmmtg-root explicitly.

Yes, so I can probably manipulate only by CSS attributes and dont add

explicitly, I hope this solve my problem. Thank you for your help and have a nice weekend!:slight_smile:

Yeah, try after removing that. Though it worked for me with that also.