无法连接到房间:访问令牌颁发者/主题无效 - Twilio visio 房间问题

brn*_*brn 3 twilio symfony reactjs

我在本教程的帮助下使用 twilio、Symfony 5: https: //www.twilio.com/blog/create-group-video-chat-app-symfony-php-twilio-react 来创建视频聊天。

输入房间名称并启动 visio 后,我在浏览器控制台中收到以下错误:

Unable to connect to Room: Invalid Access Token issuer/subject
Run Code Online (Sandbox Code Playgroud)

我理解这是因为路由 access_token 生成的令牌一定不正确。

我创建了一个普通的 twilio 帐户,然后生成 API 密钥,在我的 .env 文件中保留帐户 sid、api 密钥 sid 和 api 秘密。

以防万一我重新创建了一个新的 api 密钥来查看它是否更改了某些内容,但没有更改。

我已经检查了文档中的错误(https://www.twilio.com/docs/api/errors/20103),但解决方案没有解决我的问题。

Chat.js文件:

import React, { useState } from "react";
import axios from "axios";
import Video from "twilio-video";

const Chat = () => {
    const [roomName, setRoomName] = useState('');
    const [hasJoinedRoom, setHasJoinedRoom] = useState(false);

    const joinChat = event => {
        event.preventDefault();
        if (roomName) {
            axios.post('/access_token', { roomName }, ).then((response) => {
                console.log('RESPONSE: ');
                console.log(response.data.token);
                connectToRoom(response.data.token);
                setHasJoinedRoom(true);
                setRoomName('');

            }).catch((error) => {
                console.log(error);
            })
        } else {
            alert("You need to enter a room name")
        }
    };

    const connectToRoom = (token) => {
        const { connect, createLocalVideoTrack } = Video;
        let connectOption = { name: roomName };

        connect(token, connectOption).then(room => {
            console.log(`Successfully joined a Room: ${room}`);
            const videoChatWindow = document.getElementById('video-chat-window');

            createLocalVideoTrack().then(track => {
                videoChatWindow.appendChild(track.attach());
            });
            room.on('participantConnected', participant => {
                console.log(`Participant "${participant.identity}" connected`);
                participant.tracks.forEach(publication => {
                    if (publication.isSubscribed) {
                        const track = publication.track;
                        videoChatWindow.appendChild(track.attach());
                    }
                });
                participant.on('trackSubscribed', track => {
                    videoChatWindow.appendChild(track.attach());
                });
            });
        }, error => {
            console.error(`Unable to connect to Room: ${error.message}`);
        });
    };

    return(
        <div className="container">
            <div className={"col-md-12"}>
                <h1 className="text-title">Symfony React Video Chat</h1>
            </div>

            <div className="col-md-6">
                <div className={"mb-5 mt-5"}>
                    {!hasJoinedRoom && (
                        <form className="form-inline" onSubmit={joinChat}>
                            <input type="text" name={'roomName'} className={"form-control"} id="roomName"
                                   placeholder="Enter a room name" value={roomName} onChange={event => setRoomName(event.target.value)}/>

                            <button type="submit" className="btn btn-primary">Join Room</button>

                        </form>
                    )}

                </div>



                <div id="video-chat-window"/>
            </div>
        </div>
    )
};

export default Chat;
Run Code Online (Sandbox Code Playgroud)

TokenController用于生成用户令牌的文件:

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Twilio\Jwt\AccessToken;
use Twilio\Jwt\Grants\VideoGrant;

class TokenController extends AbstractController
{

    /**
     * @Route("/token", name="token")
     */
    public function index()
    {
        return $this->render('token/index.html.twig', [
            'controller_name' => 'TokenController',
        ]);
    }

    /**
     * @param Request $req
     * @return \Symfony\Component\HttpFoundation\JsonResponse
     * @Route("access_token", name="access_token", methods={"POST"})
     */
    public function generateToken(Request $req) {

        $accountSid = getenv('ACCOUNT_SID');
        $apiKeySid = getenv('API_SID'); 
        $apiKeySecretSid = getenv('API_SECRET');

        $identity = uniqid();

        $roomName = json_decode($req->getContent());

        $token = new AccessToken(
            $accountSid,
            $apiKeySid,
            $apiKeySecretSid,
            3600,
            $identity
        );

        $grant = new VideoGrant();
        $grant->setRoom($roomName->roomName);
        $token->addGrant($grant);
        return $this->json(['token' => $token->toJWT()], 200);
    }
}

Run Code Online (Sandbox Code Playgroud)

这行在**app.js**

ReactDOM.render(<Chat/>, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)

通过适当的进口。

更新

找到解决方案了!谢谢您的帮助 !

getenv() 方法是问题所在。

我现在将 .env 信息作为参数注入控制器中,如下所示:

services.yaml

parameters:
    app.env.ACCOUNT_SID: '%env(resolve:ACCOUNT_SID)%'
    app.env.API_KEY: '%env(resolve:API_KEY)%'
    app.env.API_SECRET: '%env(resolve:API_SECRET)%'
Run Code Online (Sandbox Code Playgroud)

并在控制器中恢复它们

Controller to recover the data


public function somename() {
    
    $sid = $this->getParameter('app.env.ACCOUNT_SID');
    $apiKey = $this->getParameter('app.env.API_KEY');
    $apiSecret = $this->getParameter('app.env.API_SECRET');

    $identity = uniqid();

    $token = new AccessToken(
        $sid,
        $apiKey,
        $apiSecret,
        3600,
        $identity
    );
}
Run Code Online (Sandbox Code Playgroud)

就像魅力一样

小智 6

也许它可以帮助那些有这个问题的人。

我发现示例代码中使用的默认区域是“US1”,并且我已在区域“IE1”中创建了我的 API 密钥。创建并使用在 US1 地区制作的 API KEY 解决了我的问题,并使示例代码正常工作。

现在因为我在欧洲地区,所以我将尝试弄清楚如何在SDK中将默认区域设置为“IE1”。

  • 我从 Twilio 支持处得到了答复 - 视频不是可区域化的产品,因此为 US1 以外的区域生成的任何 API 密钥都不起作用。 (2认同)