Tình hình dịch bệnh covid lan tràn, các công ty, trường học, trung tâm ... đều chuyển sang làm việc online chiếm phần lớn. Chính vì thế Zoom đã ra đời và là nền tảng kết nối các cuộc họp, hội nghị hay các buổi học trực tuyến một cách nhanh chóng và hiệu quả nhất. Ngoài việc sử dụng app của Zoom thì chúng ta có thể tích hợp riêng cho website và quản lý dữ liệu thông qua Web SDK của Zoom thuận tiện hơn.

Ở bài viết này, tại hạn sẽ hướng dẫn các đồng dev tích hợp zoom vào website đồng thời quản lý các phần cơ bản nhất của zoom. Nó sẽ bao gồm các bước như sau:

- Đăng ký App và tạo 1 JWT app để sử dụng được service của Zoom hỗ trợ S2S (Server-to-server là cách giao tiếp trực tiếp giữa 2 hoặc nhiều server với nhau) mà không cần ủy quyền từ người dùng.

- Tích hợp các thư viện cần thiết của Zoom cho website

- Chạy thử =))

Đăng ký App và tạo 1 JWT token

- Đầu tiên để đăng ký App từ Zoom các đồng dev vào https://marketplace.zoom.us/develop/create để đăng ký. Nếu chưa có tài khoản thì đăng nhập qua google hoặc facebook cho nhanh =)))

Khi vào link trên, các đồng dev sẽ thấy có các kiểu App khác nhau, như yêu cầu tại hạ chọn Create App của JWT

laravel zoom

 

Tại hạ tạo tên app là Laravel

laravel zoom

Tiếp tục nhập đủ các thông tin của App, các phần Optional các đồng dev có thể bỏ qua hoặc thích thì nhập vào cũng chả sao =)), xong thì click Continue

laravel zoom

Ở tab App Credentials, các đồng dev chú ý các phần về API key, API secret, Thiết lập ngày hết hạn của token, tại hạ khuyên anh em cứ set càng lâu càng tốt =)) ở đây tại hạ set 10 năm luôn cho máu laugh, cái JWT này để sau anh em có dùng tạo Meeting qua API thì sẽ dùng đến để tạo, sửa, xóa, lấy danh sách người tham gia, lấy các record đã ghi lại .....

laravel zoom

Tiếp tục đến tab Feature, ở đây nếu các anh em đồng dev dùng tới webhook sau này thì bật nó lên, còn hiện tại tại hạ không dùng thì thôi không bật

laravel zoom

Và cúối cùng thì App cũng được Active rồi =))

laravel zoom

Để xem trên Zoom đã đăng ký các App nào để phát triển thì các đồng dev truy cập https://marketplace.zoom.us/user/build sẽ hiện ra list các App đã tạo. Như ở đây là App JWT tại hạ vừa tạo có tên là Laravel

laravel zoom

Vậy là đã xong phần đăng ký ứng dụng cần thiết để tích hợp.

Tích hợp Zoom vào Laravel

- Zoom ngoài bản miễn phí chỉ sử dụng được 40 phút và giới hạn số lượng user tham gia thì nó còn cung cấp  các bản trả phí giới hạn 300, 500 hoặc lớn hơn là các webinar tới hàng ngàn người tham gia cùng lúc và không giới hạn thời gian sử dụng.

- Tại hạ sẽ tạo 1 contrller là Zoom và 1 view là zoom như sau 

FIle ZoomController 

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ZoomController extends Controller
{

    protected $api_key = 'tXGpw7niSdODbke8ZQoB8w';
    protected $api_secret = 'aersT0pOCNj8NR8gbENaPaqh73eklqqCIQ5B';



    public function index()
    {
        $data = [
                    'meeting_name' => 'Demo Zoom with Laravel', // Tên meeting 
                    'route_back_to_wait_room' => 'https://zoom.us', // Url sau khi kết thúc meeting zoom sẽ điều hướng đến
                    'id_meeting_zoom' => '86935768887', // Id của meeting 
                    'password' => 'wG4v6y', // Mật khẩu truy cập meeting đó (nếu có)
                    'name' => 'Larvel', // Chính là tên chủ tạo ra meeting đó 
                    'api_key' => $this->api_key, // là api key trong app đã tạo 
                    'invite_zoom' => true, // chức năng muốn  hiển  thị danh sách đã mời hay không 
                    'signature' => $this->generate_signature($this->api_key,$this->api_secret,'86935768887',1), // chữ kỹ định danh cho meeting // Ở đây role có 3 kiểu 1: người chủ meeting , 0: người tham gia meeting , 5: người support cho người chủ meeting 

                ];
        return view('zoom',['data' => $data]);
    }


    private function generate_signature ( $api_key, $api_secret, $meeting_number, $role){

        $time = time() * 1000 - 30000;//time in milliseconds (or close enough)

        $data = base64_encode($api_key . $meeting_number . $time . $role);

        $hash = hash_hmac('sha256', $data, $api_secret, true);

        $_sig = $api_key . "." . $meeting_number . "." . $time . "." . $role . "." . base64_encode($hash);

        //return signature, url safe base64 encoded
        return rtrim(strtr(base64_encode($_sig), '+/', '-_'), '=');
    }

}

File view zoom.blade.php

<!DOCTYPE html>
<html lang="vi">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>{{ $data['meeting_name'] }}</title>
        <!-- import #zmmtg-root css -->
        <meta name="format-detection" content="telephone=no">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
        <link type="text/css" rel="stylesheet" href="https://source.zoom.us/1.9.0/css/bootstrap.css"/>
        <link type="text/css" rel="stylesheet" href="https://source.zoom.us/1.9.0/css/react-select.css"/>
    </head>
    <body>
    <script src="https://source.zoom.us/1.9.0/lib/vendor/react.min.js"></script>
    <script src="https://source.zoom.us/1.9.0/lib/vendor/react-dom.min.js"></script>
    <script src="https://source.zoom.us/1.9.0/lib/vendor/redux.min.js"></script>
    <script src="https://source.zoom.us/1.9.0/lib/vendor/redux-thunk.min.js"></script>
    <script src="https://source.zoom.us/1.9.0/lib/vendor/lodash.min.js"></script>
    <script src="https://source.zoom.us/zoom-meeting-1.9.0.min.js"></script>
<script>
    var routeList = "{{ $data['route_back_to_wait_room'] }}";
    var meetingNumber = "{{ $data['id_meeting_zoom'] }}";
    var passWord = "{{ $data['password'] }}";
    var userName = "{{ $data['name'] }}";
    var api_key = "{{ $data['api_key'] }}";
    var signature = "{{ $data['signature'] }}";
    var invite = "{{ $data['invite_zoom'] }}";

    console.log('checkSystemRequirements');
    console.log(JSON.stringify(ZoomMtg.checkSystemRequirements()));
    ZoomMtg.preLoadWasm();
    ZoomMtg.prepareJssdk();

    testTool = window.testTool;

    ZoomMtg.init({
        leaveUrl: routeList,
        isSupportAV: true,
        success: function () {
            ZoomMtg.i18n.load("vi-VN");
            ZoomMtg.i18n.reload("vi-VN");
            ZoomMtg.join(
                {
                    meetingNumber: meetingNumber,
                    userName: userName,
                    signature: signature,
                    apiKey: api_key,
                    passWord: passWord,
                    success: function(res){
                        $('#nav-tool').hide();
                        console.log('join meeting success');

                        // meeting set to record by default
                        ZoomMtg.record({
                            record: true
                        });

                        ZoomMtg.showInviteFunction({
                            show: invite
                        });

                        // or use a json file load language resource
                        // $.i18n.load("/js/zoom-lang/vi-VN.json", "vi-VN");

                    },
                    error: function(res) {
                        console.log(res);
                    }
                }
            );
        },
        error: function(res) {
            console.log(res);
        }
    });
    //event

    ZoomMtg.inMeetingServiceListener('onUserJoin', function (data) {
        console.log('onUserJoin');
        console.log(data);
    });

    ZoomMtg.inMeetingServiceListener('onUserLeave', function (data) {
        console.log('onUserLeave');
        console.log(data);
    });

    ZoomMtg.inMeetingServiceListener('onUserIsInWaitingRoom', function (data) {
        console.log('onUserIsInWaitingRoom');
        console.log(data);
    });

    ZoomMtg.inMeetingServiceListener('onMeetingStatus', function (data) {
        // {status: 1(connecting), 2(connected), 3(disconnected), 4(reconnecting)}
        console.log('onMeetingStatus');
        console.log(data);
    });
</script>
</body>
</html>

File route web

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ZoomController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/',[ZoomController::class,'index']);

Trước đó để có được ID meeting anh em đồng dev truy cập https://us05web.zoom.us/meeting/schedule để tạo 1 meeting, sau đó sẽ có ID meeting và mật khẩu (nếu có).

laravel zoom

Và sau đó chạy thử sẽ được kết quả như sau 

laravel zoom

OK, thế là cho Zoom chạy trên web ổn rồi đó anh em.

Tổng kết

Tích hợp zoom cho website rất có lợi cho việc nâng cao sản phẩm hoặc thương mại hóa. Bài viết trên tại hạ chỉ đưa ra ngắn gọn cách tích hợp để chạy zoom trên chính domain hay local website, để chi tiết hơn các chức năng từ sdk anh em truy cập https://marketplace.zoom.us/docs/sdk/sdk-reference/web-reference để tham khảo thêm nhé. Do zoom viết từ React nên anh em nào có vọc thêm chút Js từ view phía client cho màu mè hơn cũng được laugh. Ngoài ra, như phần đầu tại hạ bảo đăng ký JWT để phục vụ cho việc quản lý các meeting được tạo từ API, anh em có thể tạo ra 1 bảng meeting rồi sử dụng API CRUD Meeting của Zoom để tạo và lấy ID meeting lưu lại vào cơ sở dữ liệu thì tiện hơn, các đồng dev có thể tham khảo các API của zoom tại đây. Vì bài viết mang tính demo nên tại hạ không làm theo cách quản lý thông qua cơ sở dữ liệu =)) hehe. Nếu có thời gian, tại hạ sẽ làm tiếp phần sử dụng các API của Zoom cho các đồng dev. Cảm ơn anh em đồng dev đã đón đọc, nếu có sai sót gì mong anh em bỏ quá cho.