我正在构建一个由 Twilio API 驱动的 Laravel 应用程序。 Laravel 应用程序基本上应该是 Twilio API 的 UI,从而使用户更容易使用。我正在为其构建此应用程序的人希望用户仅提供他们的 accountSid 和 authToken,以及登录所需的电子邮件和密码。 这是 UI 的外观(未完成):
这里我已经面临一个问题:据我所知,ClientToken应该不再使用了吧? https://www.twilio.com/docs/voice/sdks/deprecated-pages/client/tutorials/capability-tokens
使用客户端令牌,我只需要 accountSid 和 authToken 以及一个 clientName。 但是,现在应该使用 AccessToken,而不是使用 ClientToken,或者? https://www.twilio.com/docs/iam/access-tokens 这里需要提供accountSid、apiKeySid和apiKeySecret。据我所知,当目标是执行浏览器 VOIP 调用时,甚至需要提供 twimlAppSid https://www.twilio.com/docs/iam/access-tokens#create-an-access-token-for-voice。这些令牌将存储在每个用户的 Laravel 数据库中。难道不能只提供指向 Laravel 端点的 VoiceUrl 参数而不是创建 TwimlApp,只是为了获取 twimlAppSid?
所以现在我的问题是 accountSid 和 authToken 是否足以满足我的客户的要求,我是否能够基于这两个令牌获取/生成其他所有内容,或者我真的需要 accountSid、apiKeySid、apiKeySecret 以及twimlAppSid?如果需要所有这些令牌,这对用户体验来说会非常糟糕,因为即使是用户也需要创建一个 twimlApp 并放置我正在构建的应用程序的正确 Laravel 端点,以便 Twilio 可以向该端点发出请求获取 TwiML 说明。
我将向您展示一些代码,但您可能不需要这些代码来回答我的问题。只是一些额外的信息,也许有用。
为了向您提供更多背景信息,这就是我目前拥有的。如果我是对的,我什至可能还需要将 twimlAppSid 存储在数据库中?它目前在 .env 文件中被硬编码为字符串。后端代币生成:
public function getToken(Request $request)
{
$accessToken = new AccessToken(
auth()->user()->account_sid,
auth()->user()->api_key_sid,
auth()->user()->api_key_secret,
3600,
auth()->user()->id
);
$voiceGrant = new VoiceGrant();
$voiceGrant->setOutgoingApplicationSid(config('twilio.twilio.connections.twilio.twimlAppSid'));
$accessToken->addGrant($voiceGrant);
$token = $accessToken->toJWT();
return response()->json([
'token' => $token,
]);
}
在前端,我通过以下方式使用 AlpineJS 获取令牌:
startUp: function () {
fetch('dialer/token').then(response => {
return response.json()
}).then(data => {
this.token = data.token
this.clientName = data.clientName
this.initializeDevice()
})
},
initializeDevice: function () {
device = new Twilio.Device(this.token, {
debug: true,
codecPreferences: ['opus', 'pcmu'],
})
this.addDeviceListeners(device)
device.register()
},
最后,Twilio 将调用提供此功能的 Laravel 端点:
public function voiceViaTwilio(Request $request)
{
$response = new VoiceResponse();
$conferenceName = $request['ConferenceName'];
$from = $request['From'];
$to = $request['To'];
$user = TwilioNumber::where('phone_number', $from)->first()->user;
$twilio = new Client($user->account_sid, $user->auth_token);
$twilio->conferences($conferenceName)
->participants
->create(
$from,
$to,
);
$dial = $response->dial();
$dial->conference($conferenceName, [
'startConferenceOnEnter' => true,
'endConferenceOnExit' => true,
]);
$dial = $response->dial();
$dial->conference($conferenceName);
return response($response)->header('Content-Type', 'text/xml');
}
这将使我(呼叫者)进入一个即时创建的会议。 为了向您展示单击模态中的呼叫按钮时会发生什么,请看一下前端:
makeBrowserCall: async function () {
// generate unique conference name
const conferenceName = 'conference-' + Math.random().toString(36)
if (device) {
if (this.call && this.call.status() === 'open') {
console.log('OPEN')
fetch("/dialer/twilio/voice/conference/add", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-TOKEN": "{{ csrf_token() }}"
},
body: JSON.stringify(
{
To: this.to,
From: this.dialFrom,
ConferenceName: conferenceName,
}
),
success: function (data) {
console.log('success', data)
}
})
return
}
console.log('showBrowserCallModal', this.dialFrom, this.to, this.callerId, conferenceName, this.clientName)
this.call = await device.connect({ params: { To: this.to, From: this.dialFrom, CallerId: this.callerId, ConferenceName: conferenceName, ClientName: this.clientName } })
this.call.on("accept", this.updateUIAcceptedOutgoingCall.bind(this))
this.call.on("disconnect", this.updateUIDisconnectedOutgoingCall.bind(this))
this.call.on("cancel", this.updateUIDisconnectedOutgoingCall.bind(this))
}
},
一旦我拨打了第一个号码并且会议已经即时创建,因此
call.status()==='open'
,可以通过点击另一个端点来添加更多参与者"/dialer/twilio/voice/conference/add"
这基本上是相同的:
public function addParticipant(Request $request)
{
$response = new VoiceResponse();
// create conference and add subsequent callers to the conference, and end the conference when the last caller leaves, and use $request['To] as the caller to the conference
$conferenceName = $request['ConferenceName'];
$from = $request['From'];
$to = $request['To'];
$user = TwilioNumber::where('phone_number', $from)->first()->user;
$twilio = new Client($user->account_sid, $user->auth_token);
$twilio->conferences($conferenceName)
->participants
->create(
$from,
$to,
);
$dial = $response->dial();
$dial->conference($conferenceName, [
'startConferenceOnEnter' => true,
'endConferenceOnExit' => true,
]);
$dial = $response->dial();
$dial->conference($conferenceName);
return response($response)->header('Content-Type', 'text/xml');
}
非常感谢你:)