呼叫文件,如果网络服务同意则取消呼叫

时间:2019-07-30 20:24:40

标签: php asterisk agi

我正在尝试开发一个提醒系统,该系统将自动拨打电话以提醒某人特定事件。为此,我使用Asterisk进行调用和PHP,以便为Asterisk创建调用文件。我希望调用文件在添加后30秒执行。为此,我在PHP脚本中设置了修改后的时间戳。 一切正常,除了我想再次运行一个Web服务检查以确定它是否仍然与致电用户有关。

这是我的PHP脚本

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $request = json_decode(file_get_contents("php://input"));

        $tmpcallfile = tempnam("/tmp", "call");
        $callfile = tempnam("/var/spool/asterisk/outgoing/", "call");

        $fh = fopen($tmpcallfile, "w");
        fwrite($fh, "Channel: SIP/voxbeam_outbound/" . $request->{'ToPhoneNumber'} . "\n");
        fwrite($fh, "CallerID: " . $request->{'FromPhoneNumber'} . "\n");
        fwrite($fh, "MaxRetries: 3\n");
        fwrite($fh, "RetryTime: 5\n");
        fwrite($fh, "Context: remind_event\n");
        fwrite($fh, "Extension: 111\n");
        fwrite($fh, "Priority: 1\n");
        fwrite($fh, "Archive: Yes\n");

        fclose($fh);

        touch($tmpcallfile, time()+30);

        rename($tmpcallfile, $callfile);
}
?>

我的想法是简单地使用extensions.conf中的curl调用Web服务。

[voxbeam_outbound]
exten => _X.,1,NoOp()
        same => n,Answer
        same => n,Dial(SIP/voxbeam_outbound/${EXTEN})

[remind_event]
exten => _X.,1,Answer
        same => n,Set(status=${CURL(http://localhost/ShouldRemindEvent)})
        same => n,GotoIf($["${status:0:1}" != "1"]?10)
        same => n,Dial(SIP/voxbeam_outbound/${EXTEN})
        same => n,Playback(remind_event)
        same => n,Hangup

        same => 10,Hangup

我以为如果我先检查Web服务,然后如果Web服务答复除1之外的任何其他内容,则转到10挂断,但是由于某种原因它仍然会调用。

为了完整起见,我还在sip.conf中添加了几行,尽管我认为这些实际上并不相关:

[voxbeam_outbound]
type=peer
insecure=invite,port
nat=no
canreinvite=no
username=<hidden>
secret=<hidden>
host=<hidden>
context=voxbeam_outbound

所以问题是,我可以像这样简单地完成它,还是需要编写一个AGI脚本来实现我想要的?

我意识到这是编程和配置之间的混合,我认为这最适合堆栈溢出而不是超级用户,因为它是我正在构建的应用程序,并且涉及编程。

编辑:根据@arheops的建议,我尝试用Local拨打电话

php脚本中的新行,也向我想要联系的最终电话号码添加了PHONE_NUMBER变量,尽管我随后可以在Dialplan脚本中使用它

fwrite($fh, "Channel: Local/0@remind_event\n");
...
fwrite($fh, "SetVar: PHONE_NUMBER=" . $request->{'ToPhoneNumber'} . "\n");

extensions.conf中拨号计划脚本中的新提醒事件

[remind_event]
exten => 0,1,NoOp()
       same => n,Dial(SIP/voxbeam_outbound/${PHONE_NUMBER})
       same => n,Playback(remind_event)
       same => n,Hangup

但是根据星号的详细记录来看,它似乎仍然失败

Connected to Asterisk 13.16.0 currently running on hostname (pid = 22261)
    -- Attempting call on Local/0@remind_event for 111@remind_event:1 (Retry 1)
    -- Called 0@remind_event
    -- Executing [0@remind_event:1] NoOp("Local/0@remind_event-00000000;2", "") in new stack
    -- Executing [0@remind_event:2] Dial("Local/0@remind_event-00000000;2", "SIP/voxbeam_outbound/+467<hidden>") in new stack
  == Using SIP RTP CoS mark 5
    -- Called SIP/voxbeam_outbound/+467<hidden>
    -- SIP/voxbeam_outbound-00000000 is making progress passing it to Local/0@remind_event-00000000;2
    -- Local/0@remind_event-00000000;1 is making progress
       > 0xffa3a0 -- Probation passed - setting RTP source address to <hidden ip>:15476
    -- SIP/voxbeam_outbound-00000000 requested media update control 26, passing it to Local/0@remind_event-00000000;2
    -- SIP/voxbeam_outbound-00000000 requested media update control 26, passing it to Local/0@remind_event-00000000;2
    -- SIP/voxbeam_outbound-00000000 is ringing
    -- Local/0@remind_event-00000000;1 is ringing
    -- SIP/voxbeam_outbound-00000000 answered Local/0@remind_event-00000000;2
    -- Local/0@remind_event-00000000;1 answered
[Aug  1 12:18:15] WARNING[22326][C-00000001]: pbx.c:4414 __ast_pbx_run: Channel 'Local/0@remind_event-00000000;1' sent to invalid extension but no invalid handler: context,exten,priority=remind_event,111,1
[Aug  1 12:18:15] NOTICE[22326][C-00000001]: pbx_spool.c:460 attempt_thread: Call completed to Local/0@remind_event
    -- Channel SIP/voxbeam_outbound-00000000 joined 'simple_bridge' basic-bridge <988269c4-fbe9-439f-b0a9-22af873d5118>
    -- Channel Local/0@remind_event-00000000;2 joined 'simple_bridge' basic-bridge <988269c4-fbe9-439f-b0a9-22af873d5118>
    -- Channel Local/0@remind_event-00000000;2 left 'simple_bridge' basic-bridge <988269c4-fbe9-439f-b0a9-22af873d5118>
  == Spawn extension (remind_event, 0, 2) exited non-zero on 'Local/0@remind_event-00000000;2'
    -- Channel SIP/voxbeam_outbound-00000000 left 'simple_bridge' basic-bridge <988269c4-fbe9-439f-b0a9-22af873d5118>

4 个答案:

答案 0 :(得分:1)

您的呼叫文件具有Retry参数,因此它认为呼叫失败并重试。

您在这里有3个选择

1)删除不需要的文件

2)挂断电话前接听电话。

3)删除重试。

答案 1 :(得分:1)

呼叫文件非常适合安排时间,但是我会使用PHP AGI代替Dialplan来进行网络侧操作。

您将使呼叫文件拨打带有目标电话号码的本地电话,以及查询网络服务所需的任何参数(用户ID,电子邮件等)。然后,AGI执行curl请求,您可以继续从AGI内拨号。我想这对您来说会比Dialplan更舒适。因为您可以直接在PHP中控制调用,并且可以从AGI脚本中登录文件,所以它将消除您的“由于某种原因X造成的混乱”部分。

您还可以进行更高级的API查询,例如需要身份验证令牌的外部API,处理更复杂的输出等。

以下是一些帮助您入门的有用链接:

AGI library links(我个人更喜欢PHPAGI)

PHP cURL docs

答案 2 :(得分:0)

从Asterisk社区获得了很大的帮助。主要问题是需要两个上下文,呼叫的每个分支都需要一个上下文。

  • 通过拨号拨打电话的上下文(以下message_dial)
  • 播放声音文件的另一个上下文。 (以下消息)

这是有效的extensions.conf文件。只需在Dial命令之前在message_dial中的拨号计划中添加任何条件:

[message_dial]
exten => s,1,NoOp()
        same => n,Dial(SIP/voxbeam_outbound/${PHONE_NUMBER})

[message]
exten => s,1,NoOp()
        same => n,Playback(message)
        same => n,Hangup

呼叫文件可能看起来像这样

Channel: Local/s@message_dial
CallerID: +46<hidden>
MaxRetries: 3
RetryTime: 15
Context: message
Extension: s
Priority: 1
Archive: Yes
SetVar: PHONE_NUMBER=+46<hidden>

因此,考虑最终解决方案,对于Asterisk熟练的技术人员来说,实现它确实是直接的。

答案 3 :(得分:0)

为此,我宁愿将原始AMI操作与本地渠道和AGI一起使用。另一个很棒的选择是ARI,您可以使用星号进行任何操作。

我正在使用AJAM或phpAMI或PAMI。您必须考虑到这一点。