php - 需要帮助在出站调用中获取 Twilio X-Twilio-CallSid 或 X-Twilio-RecordingSid

标签 php twilio asterisk dialplan

我们正在将调用与 Twilio 的记录 Sids 一起记录到数据库中,并且由于 Asterisk 仅在请求时将 Twilio 的 sip header 公开给拨号计划(而不是响应),因此我们无法获取 header X-Twilio-CallSid 和 X-Twilio-远端 channel 上的 RecordingSid。

对于由 Twilio 的本地分机发起并由 BYE 消息来 self 们本地的始发分机挂断的调用,Asterisk 看到的所有内容都是 SIP 响应。

任何人都可以帮助通过 dialplan 或 PHP AGI 脚本访问 CallSid 或 RecordingSid 吗?

我们尝试在被叫 channel (远端)上放置一个 gosub 例程,这允许我们访问该 channel 上的变量,但可用的 SIP header 仅来自 Asterisk 的 INVITE。 Twilio 响应中的任何 header 都不会被公开。除非 Twilio 发送 BYE 请求,在这种情况下挂断处理程序将公开 CallSid 和 RecordingSid。但是,如果 Asterisk 挂断调用,则在 asterisk 收到所需的 Twilio SIP 响应 header 之前,Asterisk 生成的 BYE 消息会触发挂断处理程序。

带有 gosub 例程的 PHP AGI DialScript。

$agi->exec("Dial", "SIP/twilio-out/+1$call->dnid,180,rU(far-channel-hangup-hook,".$call->calllog_listid.")"); 

拨号计划设置 (extensions.conf)

[far-channel-hangup-hook]
exten => s,1,Set(calllog_listid=${ARG1})
exten => s,n,Set(CHANNEL(hangup_handler_push)=far-channel-hangup,s,1)
exten => s,n,Return()

[far-channel-hangup]
exten => _.!,1,AGI(log_sid.php)
exten => _.!,n,Return()

最佳答案

这个问题很难解决。对于您发起的调用,Twilio 首先在对您的初始 INVITE 的 200 OK 响应中提供 CallSid。由于它只是一个响应,Asterisk 不允许您通过 SIP_HEADER() 访问 SIP header 。

你是对的,如果 Asterisk 发起调用,你可以安装一个挂断处理程序,该处理程序将在调用挂断时触发,如果 Twilio 发送 BYE,你将拥有对“X-Twilio” header 的完全访问权限在你的处理程序中,但如果 Asterisk 用自己的 BYE 终止调用则不会。但是,如果您可以在对话生命周期中的某个时间将 Twilio-CallSid 从 Asterisk 中取出,则可以在 hangup-handler 中使用 cURL 来根据 CallSid 获取有关录制调用的更多信息。

Twilio documentation说明您可以将带有 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 发行版存储库为您安装依赖项。

Here is an example for CentOS .

这是我为解决此问题所做的工作。目前,Asterisk 附带了两个 SIP channel 驱动程序“chan_sip”和“chan_pjsip”。我使用 chan_sip,较旧的(成熟的、经过验证的) channel 驱动程序。效果很好。

如果您下载了 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 应答您的 INVITE,并发送 200 OK,其中将包含 X-Twilio-CallSid,chan_sip 就会将其设置为名为的 channel 变量 “twiliocallsid”,可以从拨号计划或 PHPAGI 脚本访问它。您可以获取 CallSid,并在 Twilio 的 cURL 查询中使用它来获取录音信息并根据需要保存它。

我对此不太确定,但如果您已经安装了 Asterisk,您可能仍然可以将其关闭,转到包含源代码的目录并运行“make install”。其他人可能对此有意见,但是当您从源代码构建并安装它时,这就是所需要的一切。您可以根据需要修改源代码并使用“make install”编译修改后的内容。

然后停止,重新启动 Asterisk,就可以开始了!

关于php - 需要帮助在出站调用中获取 Twilio X-Twilio-CallSid 或 X-Twilio-RecordingSid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54029060/

相关文章:

Asterisk sip.conf 呼出配置

php - 我应该避免在 foreach 循环中查询数据库吗?

php - 使用 PHP 导入 .xlsx 文件

javascript - 附加的输入字段元素在 angularjs 中不起作用

javascript - 我的 json 变量有问题吗?

php - 如何直接从url上传文件到S3 bucket

twilio - 出现错误 - 可编程语音中的 twilio 11200

asterisk - AGI脚本执行没有错误,但没有生成结果

xamarin - Xamarin 的 Twilio 可编程视频

linux - 使左/右音频 channel 静音