This is a sample code page for nodejs. It shows the common code sample when interacting with Zoom Webhook, Zoom Meeting SDK Auth Signature, Zoom OAuth and Zoom REST API.
// Define a function to handle webhook requests
function handleWebhookRequest(req, res, secretToken, path) {
if (req.method === 'POST') {
// Check if the event type is "endpoint.url_validation"
if (req.body.event === 'endpoint.url_validation') {
const hashForValidate = crypto.createHmac('sha256', secretToken)
.update(req.body.payload.plainToken)
.digest('hex');
res.status(200).json({
"plainToken": req.body.payload.plainToken,
"encryptedToken": hashForValidate
});
} else {
res.status(200).send();
}
}else if (req.method === 'GET') {
} else {
// Handle unsupported HTTP methods
res.status(405).send("Method Not Allowed");
}
}
app.post('/webhook/', (req, res) => {handleWebhookRequest(req,res, process.env.ZOOM_WEBHOOK_SECRET_TOKEN,"webhook");});
app.get('/webhook/', (req, res) => {handleWebhookRequest(req,res, process.env.ZOOM_WEBHOOK_SECRET_TOKEN,"webhook");});
// Function to fetch a bearer token
async function fetchBearerToken() {
try {
// Create a Basic Authorization header with client credentials
const credentials = Buffer.from(`${process.env.ZOOM_S2S_CLIENT_ID}:${process.env.ZOOM_S2S_CLIENT_SECRET}`).toString('base64');
const apiUrl = `https://zoom.us/oauth/token?grant_type=account_credentials&account_id=${process.env.ZOOM_S2S_ACCOUNTID}`;
// Define the token request parameters
const tokenRequestData = {
method: 'POST',
url: apiUrl,
headers: {
'Authorization': `Basic ${credentials}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
};
// Send the token request
const response = await axios(tokenRequestData);
// Extract the access token from the response
const accessToken = response.data.access_token;
// Return
return accessToken;
} catch (error) {
return error.message;
}
}
// Define a function to handle the common logic for saving and retrieving data
function handleRedirectURLDataRequest(path, clientId,clientSecret, req, res){
//post doesn't seem to be used
var filename = "/var/www/asdc.cc/zoom-sdk-signature-generator/"+path+".txt"
if (req.method === 'POST') {
//handle get
} else if (req.method === 'GET') {
const codeFromQueryString = req.query.code; // Get the token from the query string
if (codeFromQueryString && codeFromQueryString.length>=1){
//get the request token from zoom's oauth
const url = 'https://zoom.us/oauth/token';
const data = {
code: codeFromQueryString,
grant_type: 'authorization_code',
redirect_uri: 'https://asdc.cc/'+path
};
const headers = {
Authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,
'Content-Type': 'application/x-www-form-urlencoded'
};
axios.post(url, new URLSearchParams(data).toString(), { headers })
.then(response => {
fs.writeFile(filename, JSON.stringify(response.data), 'utf8', function (err) {
if (err) {
return console.log(err);
}
console.log("The file was saved!");
});
console.log(response.data);
res.status(200).json(response.data);
// You can access the access_token in response.data.access_token
})
.catch(error => {
console.error(error);
res(error);
// Handle any errors here
});
}
//if there is no querystring entered
else{
fs.readFile(filename, 'utf8', (err, data) => {
if (err) {
return res.status(500).json({ error: 'Error reading file' });
}
try {
// Parse the JSON data
const jsonData = JSON.parse(data);
// Send the JSON data as a response
res.status(200).json(jsonData);
} catch (parseError) {
res.status(500).json({ error: 'Error parsing JSON data' });
}
});
}
}
}
// Define routes for different endpoints
app.post('/redirecturlformsdkoauth/', (req, res) => {
var clientid=process.env.ZOOM_CLIENT_ID_NEW;
var clientsecret=process.env.ZOOM_CLIENT_SECRET_NEW;
handleRedirectURLDataRequest("redirecturlformsdkoauth",clientid,clientsecret, req, res);
});
app.post('/meeting/', (req, res) => {
const now = Math.round((new Date().getTime()) / 1000)
//make it valid 5 minute ago
const iat =now - 5 * 60;
//make it expire 30 minutes later
const exp = now + 30 * 60;
const oHeader = { alg: 'HS256', typ: 'JWT' }
const oPayload = {
sdkKey: process.env.ZOOM_SDK_KEY,
mn: req.body.meetingNumber,
role: req.body.role,
iat: iat,
exp: exp,
appKey: process.env.ZOOM_SDK_KEY,
tokenExp: exp
}
const sHeader = JSON.stringify(oHeader)
const sPayload = JSON.stringify(oPayload)
const signature = KJUR.jws.JWS.sign('HS256', sHeader, sPayload, process.env.ZOOM_SDK_SECRET)
res.json({
signature: signature,
sdkKey:process.env.ZOOM_SDK_KEY
})
})
app.get('/oauthrefreshtoken', async (req, res) => {
try {
console.log("handle_oauth_refresh_token_data_request");
var oauth_client_id="";
var oauth_client_secret="";
const code = req.query.code; // Get the token from the query string
if (code && code.length>=1){
// Encode the client ID and client secret
const credentials = `${oauth_client_id}:${oauth_client_secret}`;
const credentials_encoded = base64.encode(credentials);
console.log(credentials);
console.log(code);
const url = 'https://zoom.us/oauth/token';
const data = {
refresh_token: code,
grant_type: 'refresh_token'
};
const headers = {
Authorization: `Basic ${Buffer.from(`${oauth_client_id}:${oauth_client_secret}`).toString('base64')}`,
'Content-Type': 'application/x-www-form-urlencoded'
};
axios.post(url, new URLSearchParams(data).toString(), { headers })
.then(response => {
console.log(response.data);
res.status(200).json(response.data);
// You can access the access_token in response.data.access_token
})
.catch(error => {
console.error(error);
res(error);
// Handle any errors here
});
}
else{
console.log("issue with ?code query string");
}
} catch (error) {
console.error("Error:", error.message);
res.status(500).send("Internal Server Error");
}
});
// Function to make a REST API request using the bearer token
async function makeApiRequestWithToken(bearerToken,meetingNumber) {
try {
const apiUrl = `https://api.zoom.us/v2/meetings/${meetingNumber}/jointoken/local_recording`;
// Define your API request parameters
const apiRequestData = {
method: 'GET', // Change to the HTTP method you need
url: apiUrl, // Replace with your API endpoint URL
headers: {
'Authorization': `Bearer ${bearerToken}`,
// Add other headers as needed
},
};
// Send the API request with the bearer token
const response = await axios(apiRequestData);
const recordingToken = response.data.token;
// Return the response data
return recordingToken ;
} catch (error) {
console.error('Error making API request:', error.message);
return error.message ; // Optionally rethrow the error
}
}
ZOOM_VIDEO_SDK_KEY="xxxxxxx"
ZOOM_VIDEO_SDK_SECRET="xxxxxxx"
#ZOOM_SDK_KEY="xxxxxxx"
#ZOOM_SDK_SECRET="xxxxxxx"
ZOOM_WEBHOOK_SECRET_TOKEN="xxxxxxx"
ZOOM_MSDKWEBHOOK_SECRET_TOKEN="xxxxxxx"
ZOOM_SDK_KEY="xxxxxxx"
ZOOM_SDK_SECRET="xxxxxxx"
ZOOM_CLIENT_ID_NEW="xxxxxxx"
ZOOM_CLIENT_SECRET_NEW="xxxxxxx"
ZOOM_VSDK_WEBHOOK_SECRET_TOKEN="xxxxxxx"
ZOOM_S2SOAUTH_WEBHOOK_SECRET_TOKEN="xxxxxxx"
ZOOM_S2S_CLIENT_ID="xxxxxxx"
ZOOM_S2S_CLIENT_SECRET="xxxxxxx"
ZOOM_S2S_ACCOUNTID="xxxxxxx"
ZOOM_OAUTH_ACCOUNTLEVEL_WEBHOOK_SECRET_TOKEN="xxxxxxx"
ZOOM_OAUTH_ACCOUNTLEVEL_CLIENT_ID="xxxxxxx"
ZOOM_OAUTH_ACCOUNTLEVEL_CLIENT_SECRET="xxxxxxx"
ZOOM_OAUTH_USERLEVEL_WEBHOOK_SECRET_TOKEN="xxxxxxx"
ZOOM_OAUTH_USERLEVEL_CLIENT_ID="xxxxxxx"
ZOOM_OAUTH_USERLEVEL_CLIENT_SECRET="xxxxxxx"