这个问题很难解决。在您发起呼叫时,Twilio 首先在对您的初始 INVITE 的 200 OK 响应中提供 CallSid。由于它只是一个响应,Asterisk 将不允许您通过 SIP_HEADER() 访问 SIP 标头。
没错,如果 Asterisk 发起呼叫,您可以安装一个挂断处理程序,该处理程序将在挂断呼叫时触发,并且如果 Twilio 发送 BYE,您将可以完全访问处理程序中的“X-Twilio”标头,但如果 Asterisk 用自己的 BYE 终止呼叫,则不会。但是,如果您可以在对话生命周期中的某个时间将 Twilio-CallSid 从 Asterisk 中哄出来,则可以在您的挂断处理程序中使用 cURL来获取有关基于 CallSid 记录的呼叫的更多信息。
Twilio 文档解释说,您可以将带有 CallSid 的 HTTP GET 请求发送到他们的 Recordings API 并获取有关录制的信息。
curl -X GET -https://video.twilio.com/v1/Recordings/RMXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' -u ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:your_auth_token
在您的 PHPAGI 代码中,您可以执行以下操作:
$recording_object = NULL;
$accountsid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
$auth_token = "xxxxxxxxxxxxxxxxxxx"; // Your API access auth token
$cidurl = "https://api.twilio.com/2010-04-01/Accounts/$accountsid/Calls/$CallSid/Recordings.json";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $cidurl);
curl_setopt($ch, CURLOPT_USERPWD, "$accountsid:$auth_token");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$retval = curl_exec($ch);
$obj = json_decode($retval);
curl_close($ch);
if ($obj) {
if (property_exists($obj, "recordings")) {
$recording_object = $obj->recordings;
}
}
您将能够通过以下方式访问 RecordingSid 和 RecordingDuration:
$recording_object->sid
和
$recording_object->duration
(如果 $recording_object 不为 NULL)
现在,在通话(SIP 对话)的早期实际获取 X-Twilio-CallSid 是更加棘手的地方。
我总是从源代码构建 Asterisk。这很容易。甚至还有一些脚本可以根据您的 Linux Distro 存储库为您安装依赖项。
这是 CentOS 的示例。
这是我为解决此问题所做的工作。如今,Asterisk 附带了两个 SIP 通道驱动程序“chan_sip”和“chan_pjsip”。我使用 chan_sip,较旧的(成熟的、经过验证的、真实的)通道驱动程序。它运作良好。
如果您下载了 Asterisk 的源代码,并且在按照上述指南中的步骤进行操作之前,请找到文件“chan_sip.c”。它通常在目录 /channels 中
编辑文件。
在文件中,有一个名为handle_response()的函数。
/*! \brief Handle SIP response in dialogue
\note only called by handle_incoming */
static void handle_response(struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
搜索该功能。
在该函数中,搜索第一个switch语句,然后按照代码找到“case 200:”条件。
它应该类似于以下内容:
case 200: /* 200 OK */
p->authtries = 0; /* Reset authentication counter */
if (sipmethod == SIP_INVITE) {
handle_response_invite(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_REGISTER) {
handle_response_register(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_SUBSCRIBE) {
ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
handle_response_subscribe(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_BYE) { /* Ok, we're ready to go */
pvt_set_needdestroy(p, "received 200 response");
ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
}
break;
将其更改为如下所示:
case 200: /* 200 OK */
p->authtries = 0; /* Reset authentication counter */
if (sipmethod == SIP_INVITE) {
const char *twilio_callsid = sip_get_header(req, "X-Twilio-CallSid");
if (twilio_callsid) {
ast_verb(1, "** Setting channel variable 'twiliocallsid' to '%s'\n", twilio_callsid);
pbx_builtin_setvar_helper(owner, "twiliocallsid", twilio_callsid);
}
handle_response_invite(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_REGISTER) {
handle_response_register(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_SUBSCRIBE) {
ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
handle_response_subscribe(p, resp, rest, req, seqno);
} else if (sipmethod == SIP_BYE) { /* Ok, we're ready to go */
pvt_set_needdestroy(p, "received 200 response");
ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
}
break;
保存文件。然后按照步骤构建和安装 Asterisk。
现在,只要 Twilio 回答您的邀请,并发送一个 200 OK ,其中将包含 X-Twilio-CallSid chan_sip 会将其设置为一个名为“twiliocallsid”的通道变量,并且可以从拨号计划或您的 PHPAGI 脚本访问它。您可以获取 CallSid,并在对 Twilio 的 cURL 查询中使用它来获取录制信息并根据需要保存它。
我对此并不完全确定,但如果您已经安装了 Asterisk,您可能仍然可以将其关闭,转到包含源代码的目录并运行“make install”。其他人可能对此有意见,但是当您从源代码构建和安装它时,这就是全部。您可以根据需要修改源代码并使用“make install”编译已修改的内容。
然后停止,重新启动 Asterisk,一切顺利!