与Laravel和Nexmo的文本到语音通话

这是米迦勒Heap系列教程的第二部分,介绍了如何使用Laravel构建多通道帮助台系统。 在我们的上一篇文章中,我们介绍了使用Nexmo发送和接收SMS Laravel通知,我建议在完成这篇文章之前先完成这篇文章中的任务。或者,您可以在Github上查看预构建的版本。 今天,我们将进一步介绍,并添加在客户的记录单中添加新响应时向客户进行文本到语音通话的功能。先决条件 要完成此文章,您需要一个Nexmo帐户和Nexmo命令行工具安装和配置,以及您通常的Laravel先决条件。您还需要本系列第1部分中的Deskmo应用程序。 在我们开始之前,您需要再次将本地服务器暴露于internet。在一个终端运行php artisan serve,在另一个终端运行ngrok http 8000。如果您使用的是自动生成的ngrokURL,则需要在Nexmo仪表板上更新您的SMS webhook URL。选择我们的通知方法 首先要做的是配置票证响应的通知机制。我们希望帮助台代理在添加回复时能够选择反馈方法,而不是自动发送短信。 打开resources/views/ticket/create.blade.php并在recipient和submit表单组之间添加以下HTML以添加单选按钮来选择通知方法: 1 2 3 4 5SMS 6 7 8 91011Voice121314 以及添加HTML,我们需要更新TicketController以使用传入的值。打开app/Http/Controllers/TicketController.php并编辑store方法。我们需要在这个方法顶部的验证器中将notification_method标记为必填字段: 7]); 最后,在store方法的末尾,查找我们发送通知的位置,并将其包装在if语句中,为首选通知方法是语音呼叫和无效通知方法添加条件提供。 1if ($data[\"notification_method\"] === \"sms\") {2Notification::send($ticket->subscribedUsers()->get(), new TicketCreated($entry));3} elseif ($data[\"notification_method\"] === \"voice\") {4// Make a voice call here5} else {6throw new Exception(\"Invalid notification method provided\");7} 代理现在可以选择语音呼叫作为通知方法,但不会向客户发送通知。我们需要在应用程序中添加对语音呼叫的支持。 在处理语音呼叫时,Nexmo将以两种不同的方式与我们的应用程序进行交互–当呼叫被应答时和当呼叫状态发生变化时。应答呼叫 当呼叫被应答时,Nexmo将向answer_url发出GET请求。我们应用程序中的这个端点将返回一个JSON文档,该文档解释在调用中要做什么。这个响应被称为Nexmo Call Control Object(NCCO)。 要做的第一件事是创建一个WebhookController来处理这个传入的请求: 1php artisan make:controller WebhookController 要让呼叫向客户说出消息,我们需要使用一个talk操作。当用JSON表示时,它采用以下形式: 1[2{3\"action\": \"talk\",4\"text\": \"This is an example talk action\"5}6] 让我们采用这种格式并实现一个answer方法,该方法将返回一个NCCO。如果票证条目存在,我们的文本应该包含消息内容,如果票证条目不存在,则包含错误消息。在新的WebhookController中添加以下内容: 1public function answer(TicketEntry $ticket) { 2if (!$ticket->exists) { 3return response()->json([ 4[>> 7] 8]); 9}1011return response()->json([12[15]16]);17} 我们需要将use AppTicketEntry;添加到控制器的顶部,以便在我们的方法中用作类型提示。 在实现控制器的同时,我们需要告诉应用程序如何路由传入请求。打开routes/web.php并在底部添加以下路由: 1Route::get(\"/webhook/answer/{ticket?}\", \"WebhookController@answer\"); 您现在应该可以访问此webhook终结点并查看成功响应和错误响应。 注意:这将用于演示目的,但它非常不安全,因为攻击者可以在URL中放置任何ID以查看错误票证响应。如果在应用程序中实现此功能,则需要在应用程序和Nexmo之间设置一个共享机密。语音呼叫事件 除了在接听呼叫时向answer_url发出GET请求外,Nexmo还会将呼叫的状态更改发送给event_url。例如,Nexmo将向我们的event_url发出POST请求: - 打电话 - 来电接受者接听 - 通话中的所有方挂断 - 通话记录可用 由于这些事件中的信息在以后可能有用,我们将在每次的应用程序日志中添加一个条目我们收到一个事件。 我们需要导入WebhookController顶部的Log正面: 1use Log; 然后,我们需要实现event方法。当我们将在请求中接收到的所有内容作为上下文信息写入时,在这种方法中,我们只需要两行代码——一行记录数据,另一行告诉Nexmo接收到的数据没有任何问题: 1public function event(Request $request) {2Log::info(\"Call event\", $request->all());3return response(\"\", 204);4} 最后,我们需要添加一些路由,以便入站Nemxo请求将其发送到此控制器。再次打开routes/web.php和以下路线: 1Route::post(\"/webhook/event\", \"WebhookController@event\"); ust已添加并被提示通过语音添加响应。获取通话记录 通话结束后,Nexmo将向我们的***86***发送一个事件,其中包含通话的***87***,如下所示: ***88*** 此时,我们的应用程序将接收此事件并将其记录到磁盘。除了记录信息外,我们还想获取***89***,并使用转录服务获取文本。 再次打开***90***,更新***91***方法以检查是否设置了***92***。如果是,则调用***93***方法(我们将在下面实现): ***94*** 接下来,我们需要实现***95***方法。首先要做的是使用***96***并使用Nexmo库获取它: ***97*** 这将为调用提供原始音频,我们可以将原始音频输入到转录服务中以获取文本形式的语音。转录调用录制 要转录调用,我们将使用IBM的语音到文本API。如果您还没有帐户,则需要注册IBM Bluemix才能完成下一部分的工作。 重新登录后,请访问\"项目\"页面,然后单击右上角的\"创建项目\"。在模式中,单击\"获取Watson服务\",选择\"语音到文本\",然后单击右侧的\"添加服务\"。给你的项目起一个名字,然后创建一个项目。 在出现的页面底部会有一个凭证部分。点击右边的Show,注意你的***98***和***99***。IBM没有官方的PHP客户端库,所以我们将使用***100***并直接向他们的API发出HTTP请求。我们使用刚从Nexmo请求的音频数据发出***101***请求,并将得到一个JSON文档作为包含转录文本的响应。 将以下内容添加到***102***方法中以调用IBM转录API,用IBM凭据替换***103***和***104***: ***105*** IBM转录API返回一个JSON响应,其结构如下所示: ***106*** 我们需要循环这个响应,构建一个字符串并将其作为对票据的回复。在您的***107***方法的末尾添加以下内容: ***108*** 现在我们有了我们的转录文本,是时候将其添加到我们的票证中了。不幸的是,我们没有办法将传入的***109***链接到用户的电话号码,因此我们不知道音频响应的是哪个票证。 注意:为了简化本文的内容,我们将把此响应添加到最新创建的票证中,并将其归因于创建票证的用户。在现实世界中,当你打电话时,你需要跟踪电话的***110***,并用它来找到正确的用户(但我把它作为一个练习留给你)。 更新你的***111***方法,这样***112***语句检查是否有***113***也会创建一个新的***114***,并将它添加到最新的***中票证: ***115*** 除了更新***116***方法外,您还需要将***117***添加到***118***顶部的导入列表中。 现在添加新票证,当您接到电话时,请在按#键之前尝试说\"这是一个音频回复,太棒了\"。通话结束后,打开刚刚添加的票证并刷新,直到您的回复出现(不应超过几秒钟)。结论 恭喜,您完成了通话!我们采用了现有的可以处理双向短信的应用程序,并添加了使用IBM Watson transcription API进行语音呼叫和接受客户响应的功能。 在本系列的下一篇文章中,我们将添加对使用聊天应用程序(而不是短信或语音)向客户发送短信的支持,为他们提供一种与您的支持人员进行实时对话的方式。 如果您希望获得Nexmo的信用来完成此帖子并测试平台,请联系邮箱:devrel@nexmo.com如果您有任何想法或问题,请随时联系@mheap onTwitter或todevrel@nexmo.com。非常感谢Nexmo赞助本周的Laravel新闻

admin_action_{$_REQUEST[‘action’]}

do_action( "admin_action_{$_REQUEST[‘action’]}" )动作钩子::在发送“Action”请求变量时激发。Action Hook: Fires when an ‘action’ request variable is sent.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$_REQUEST['action']引用从GET或POST请求派生的操作。源码(Source)更新版本源码位置使用被使用2.6.0 wp-admin/admin.php:...

日期:2020-09-02 17:44:16 浏览:1155

admin_footer-{$GLOBALS[‘hook_suffix’]}

do_action( "admin_footer-{$GLOBALS[‘hook_suffix’]}", string $hook_suffix )操作挂钩:在默认页脚脚本之后打印脚本或数据。Action Hook: Print scripts or data after the default footer scripts.目录锚点:#说明#参数#源码说明(Description)钩子名的动态部分,$GLOBALS['hook_suffix']引用当前页的全局钩子后缀。参数(Parameters)参数类...

日期:2020-09-02 17:44:20 浏览:1054

customize_save_{$this->id_data[‘base’]}

do_action( "customize_save_{$this->id_data[‘base’]}", WP_Customize_Setting $this )动作钩子::在调用WP_Customize_Setting::save()方法时激发。Action Hook: Fires when the WP_Customize_Setting::save() method is called.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_data...

日期:2020-08-15 15:47:24 浏览:795

customize_value_{$this->id_data[‘base’]}

apply_filters( "customize_value_{$this->id_data[‘base’]}", mixed $default )过滤器::过滤未作为主题模式或选项处理的自定义设置值。Filter Hook: Filter a Customize setting value not handled as a theme_mod or option.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_date['base'],指的是设置...

日期:2020-08-15 15:47:24 浏览:882

get_comment_author_url

过滤钩子:过滤评论作者的URL。Filter Hook: Filters the comment author’s URL.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/comment-template.php:32610...

日期:2020-08-10 23:06:14 浏览:923

network_admin_edit_{$_GET[‘action’]}

do_action( "network_admin_edit_{$_GET[‘action’]}" )操作挂钩:启动请求的处理程序操作。Action Hook: Fires the requested handler action.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$u GET['action']引用请求的操作的名称。源码(Source)更新版本源码位置使用被使用3.1.0 wp-admin/network/edit.php:3600...

日期:2020-08-02 09:56:09 浏览:865

network_sites_updated_message_{$_GET[‘updated’]}

apply_filters( "network_sites_updated_message_{$_GET[‘updated’]}", string $msg )筛选器挂钩:在网络管理中筛选特定的非默认站点更新消息。Filter Hook: Filters a specific, non-default site-updated message in the Network admin.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分$_GET['updated']引用了非默认的...

日期:2020-08-02 09:56:03 浏览:852

pre_wp_is_site_initialized

过滤器::过滤在访问数据库之前是否初始化站点的检查。Filter Hook: Filters the check for whether a site is initialized before the database is accessed.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/ms-site.php:93910...

日期:2020-07-29 10:15:38 浏览:824

WordPress 的SEO 教学:如何在网站中加入关键字(Meta Keywords)与Meta 描述(Meta Description)?

你想在WordPress 中添加关键字和meta 描述吗?关键字和meta 描述使你能够提高网站的SEO。在本文中,我们将向你展示如何在WordPress 中正确添加关键字和meta 描述。为什么要在WordPress 中添加关键字和Meta 描述?关键字和说明让搜寻引擎更了解您的帖子和页面的内容。关键词是人们寻找您发布的内容时,可能会搜索的重要词语或片语。而Meta Description则是对你的页面和文章的简要描述。如果你想要了解更多关于中继标签的资讯,可以参考Google的说明。Meta 关键字和描...

日期:2020-10-03 21:18:25 浏览:1683

谷歌的SEO是什么

SEO (Search Engine Optimization)中文是搜寻引擎最佳化,意思近于「关键字自然排序」、「网站排名优化」。简言之,SEO是以搜索引擎(如Google、Bing)为曝光媒体的行销手法。例如搜寻「wordpress教学」,会看到本站的「WordPress教学:12个课程…」排行Google第一:关键字:wordpress教学、wordpress课程…若搜寻「网站架设」,则会看到另一个网页排名第1:关键字:网站架设、架站…以上两个网页,每月从搜寻引擎导入自然流量,达2万4千:每月「有机搜...

日期:2020-10-30 17:23:57 浏览:1292