vikashkrjha/alexa-app

一套类,使用Lumen(以及较少程度上Laravel)简化创建简单的亚马逊Echo Alexa应用程序

0.3.5 2017-11-10 13:20 UTC

This package is auto-updated.

Last update: 2024-09-21 23:27:56 UTC


README

Latest Version Total Downloads Software License StyleCI

一套类,使用Laravel和Lumen简化创建简单的亚马逊Echo Alexa应用程序(注意:5.2.x版本的Lumen存在一个需要解决的问题[5]

主要更新 - 0.2.0 - 可以称其为beta版

我最近重构了几乎所有的这个包,使其与Laravel兼容,并且尽量不替换默认的Lumen Application。我还做了一些我认为最好的改变,例如,我将Laravel/Lumen会话与Alexa AlexaSkillsKit特定的会话数据解耦,并创建了一个单接口,通过这个接口可以处理大多数Alexa交互。但这主要是关于重构的,还有很多新功能,其中最重要的是支持亚马逊的AlexaSkillsKit安全相关要求。

主要功能

  1. 允许Laravel/Lumen风格的意图、启动和会话结束请求的路由
  2. 处理亚马逊提出的所有安全要求,包括证书/签名验证、时间戳验证等
  3. 通过熟悉的Laravel风格界面提供对Alexa AlexaSkillsKit会话数据的访问
  4. 使用Laravel会话数据填充响应,以在Lumen和Alexa之间维护1:1的会话数据集
  5. 提供易于返回Alexa友好响应的类,包括SpeechCardRe-prompt响应
  6. 可选地提供一种轻松检索连接的Echo设备信息的方法($device = Alexa::device();

快速示例

AlexaRoute::intent('/alexa-end-point', 'GetAntiJoke', function(){
    Alexa::say("Why was the little boy crying? Because he had a frog stapled to his face!");
});

演示

我很快将录制一系列新的教程视频。

安装

先决条件

对于AlexaApp来说,唯一需要的是Laravel或Lumen(基于5.2版本的版本)框架。

通过composer安装后(例如,composer require develpr/alexa-app

1:自动加载框架的相应服务提供程序

需要将Develpr\AlexaApp\Provider\LaravelServiceProvider添加到自动加载的服务提供程序数组中

Laravel

config/app.php配置文件中添加

'providers' => [
    ...snip...
    \Develpr\AlexaApp\Provider\LaravelServiceProvider::class,
    ...snip...
],

Lumen

在你的应用程序的bootstrap/app.php文件中添加

$app->register(\Develpr\AlexaApp\Provider\LumenServiceProvider::class);

2:为AlexaAlexaRoute添加外观/别名(可选)

这不是必需的,但可能非常有用。你可以注入\Develpr\AlexaApp\Alexa\Develpr\AlexaApp\Routing\AlexaRouter类的实例,或者使用$app['alexa']或$app['alexa.router']分别获取它们。

Laravel

如果你想使用外观/别名,你需要在config/app.php文件中添加两个单独的别名配置。

    'aliases' => [
        ...
        'AlexaRoute' => \Develpr\AlexaApp\Facades\AlexaRouter::class,
        'Alexa' => \Develpr\AlexaApp\Facades\Alexa::class,
        ...
    ],

Lumen

实际上,我不确定是否有添加别名/外观的“官方”方法,我通常不使用Lumen的自定义外观,然而,如在StackExchange帖子中提到的那样,这应该可以工作

首先确保在bootstrap/app.php文件中启用了外观/别名,通过取消注释$app->withFacades();,然后添加以下内容

class_alias(\Develpr\AlexaApp\Facades\AlexaRouter::class, 'AlexaRoute');
class_alias(\Develpr\AlexaApp\Facades\Alexa::class, 'Alexa');

对于Lumen来说,使用$app['alexa.router']或者将上述类之一的实例注入到你的类中可能更容易。

3:注册证书中间件以验证请求来自亚马逊/AlexaSkillsKit(可选)

对于任何生产应用程序,保护应用程序是重要的,并且Amazon实际上要求您按照其文档中所述进行保护。然而,您无需注册此中间件,在特定测试中也可以选择不注册。

此软件包通过提供满足Amazon提供的所有必需安全参数的中间件来简化此操作。目前,如果您想启用此功能,则需要根据Laravel/Lumen文档注册Certificate中间件。

如果您想保护应用程序中的所有路由,可以简单地将Certificate中间件添加到全局中间件,如下所示,否则您可以选择保护某些端点(即仅在/alexa-api-endpoint处运行证书/安全检查)。

Laravel

要保护所有路由,在您的app/Http/Kernal.php文件中

protected $middleware = [
    ...
    \Develpr\AlexaApp\Http\Middleware\Certificate::class,
    ...
];

Lumen

要保护所有路由,在您的bootstrap/app.php文件中

$app->middleware([
    ...snip...
    \Develpr\AlexaApp\Http\Middleware\Certificate::class,
    ...snip...
]);

所有安装完成

到此为止,一切应该“工作”(有关更多信息,请参阅下面的使用说明),但有一些元素可能需要配置。

## 配置

根据您的应用程序,可以修改许多内容,或者甚至可能需要修改,最重要的是,您需要设置安全选项以匹配您的AppId等。如果使用Laravel或Lumen,这些修改大多以相同的方式进行,所有配置值都应在config/文件中定义,或者通过使用.env文件。

如果您使用Laravel,可以使用控制台Artisan命令通过artisan vendor:publish将AlexaApp配置文件发布到应用程序配置目录,或者如果您愿意(或使用Lumen)可以手动从vendor/develpr/alexa-app/config/alexa.php复制此文件。

alexa.php配置文件中有许多注释,因此请仔细阅读以获取有关特定选项的更多信息! - 我将仅介绍更重要、更广泛的选择。

证书/安全

需要设置一些简单的配置选项,以便AlexaApp能够成功验证请求是有效的/来自Amazon/AlexaSkillsKit。

Amazon / AlexaSkillsKit "applicationId"s

这是您的AlexaSkillsKit的应用程序ID,用于验证请求是否为您的应用程序。如果您不确定您的应用程序ID是什么,最简单的方法(对我来说至少)是查看您的应用程序从您的应用程序发送到Web服务器的示例请求。JSON主体的一部分将包括..."application":{"applicationId":"amzn1.echo-sdk-ams.app.9ec3744a-d1b2-48f2-8e08-3b2045c00616"},... - 您希望在配置中输入的应用程序ID是此applicationId

可以在.env文件中使用ALEXA__APPLICATION_IDS密钥设置applicationIds配置值,或者在配置文件中直接设置。请注意,配置文件接受一个数组中的应用程序ID,以防您计划从一个Laravel/Lumen应用程序中为多个应用程序提供服务。.env文件方法只允许指定单个应用程序ID。

请求时间戳容差

截至本文撰写时,Amazon指定请求不应超过150秒以防止重放攻击。这是默认配置中设置的值,但如果您想更改此值,可以在此处进行更改。此外,请注意,如果您将此值设置为0,则不会检查请求年龄 - 这在测试您想重复测试的示例请求时很有用。

可以在配置文件('timestampTolerance')中或在.env文件中设置ALEXA_TIMESTAMP_TOLERANCE进行更改。

证书提供者

默认情况下,AlexaApp将使用文件存储来本地缓存亚马逊的远程证书文件。其他提供商将很快得到支持,包括redis、数据库和eloquent。这些相关选项可以在配置文件中查看/配置。

Alexa 设备

如果您想使用设备功能(例如 Alexa::device()),您可能需要配置一些选项。

基本上,您需要告诉Alexa应用程序您的持久化位置以及如何访问设备信息——目前提供了两种提供商,分别是eloquentdatabase。如果您使用eloquent提供商,请确保在Lumen中使用eloquent时已启用。

设备提供商

目前仅支持databaseeloquent选项,但可以通过实现\Develpr\AlexaApp\Contracts\DeviceProvider接口轻松支持更多提供商。

默认设备提供商是Eloquent,并且/vendor/develpr/alexa-app/Device/Device.php中有一个示例设备,可以复制到您的app目录并修改以满足您的需求。这个模型可以看作是Laravel基础安装中提供的User模型的类似物。

示例迁移

与AlexaApp一起提供了一个示例迁移,可以复制到您的迁移文件夹(手动或使用Laravel控制台命令php artisan vendor:publish --tag="migrations")。迁移后,将随附的DeviceProvider一起“即插即用”。如果您不想使用此迁移,那完全可以,但您需要查看配置文件以确保您修改/了解您可能需要更新以适应您的存储架构的任何选项。

使用

在以下章节中,您可以了解如何使用此包。请注意,虽然我可能在下面的大多数示例中使用外观/别名,但您当然不必这么做!如果您想了解更多,请查看安装部分 -> facades/aliases

路由

从亚马逊AlexaApp中间件到您的应用程序将发出三种类型的请求。这些是

  1. LaunchRequest(当您的应用程序“打开”时发生)
  2. SessionEndedRequest(当应用程序关闭时发送到您的应用程序)
  3. IntentRequest(这些都是上述请求之外的请求——可能是您应用程序的“精髓”——最有意义的交互)

这三种类型的请求可以像正常的LaravelLumen请求一样在您的应用程序中进行路由!所有这些示例都可能位于您的app/Http/routes.php中。

LaunchRequest

AlexaRoute::launch('/your-app-uri', 'App\Http\Controllers\AnyController@anyMethod');

$app['alexa.router']->launch('/your-app-uri', 'App\Http\Controllers\AnyController@anyMethod');

SessionEndedRequest

AlexaRoute::sessionEnded('/your-app-uri', function() use ($app) {
    return '{"version":"1.0","response":{"shouldEndSession":true}}';
});

$app['alexa.router']->sessionEnded('/your-app-uri', function() use ($app) {
    return '{"version":"1.0","response":{"shouldEndSession":true}}';
});

IntentRequest

AlexaRoute::intent('/your-app-uri', 'GetZodiacHoroscopeIntent', 'App\Http\Controllers\AnyController@anyMethod');

$app['alexa.router']->intent('/your-app-uri', 'GetZodiacHoroscopeIntent', 'App\Http\Controllers\AnyController@anyMethod');

请注意,在这些示例中,都使用了闭包和控制器来处理请求,但根据请求类型,使用一个还是另一个没有具体要求。

请注意,其他getpostputpatchdelete等选项仍然可用且未更改。

会话

会话值通过亚马逊/AlexaSkillsKit的json有效载荷传递到您的应用程序中。这些值可以在AlexaRequest中访问,或使用Alexa外观/别名。

检索会话值

$previousChoice = Alexa::session('previousChoice');

检索所有会话值

Alexa::session();

设置会话值

Alexa::session('previousChoice', "Pizza");

Alexa::setSession('previousChoice', "Pizza");

删除会话值

Alexa::unsetSession('previousChoice');

会话值也会包含在响应json中,但**仅当您使用AlexaResponse类时**。

槽位

您可以检索槽位的值(目前仅适用于IntentRequests)

$usersChoice = Alexa::slot('choice');

如果槽位为空,将返回 null。您可以通过传递您喜欢的默认值作为第二个参数来更改此默认值。

$usersChoice = Alexa::slot('choice', 'foo');

响应

您可以使用此包和Alexa外观轻松地从您的应用程序创建有效响应,但了解外观背后的类也很重要。最重要的是要知道 Alexa::say("Hello"); 实际上只是返回一个新的 \Develpr\AlexaApp\Response\AlexaResponse 对象,其中包含一个 \Develpr\AlexaApp\Response\Speech 对象。

使用Alexa外观/别名

向Amazon/AlexaSkillsKit/最终用户发送有效响应的最简单方法是

return Alexa::say("Oh hi Denny");

如上所述,最终会生成并返回一个 AlexaResponse,因此您可以将其他方法链接起来以添加其他响应功能。例如...

return Alexa::say("Oh hi Denny")->withCard(new Card("Hello message"))->endSession();

...将返回一个语音消息("Oh hi Denny")、一个标题为"Hello message"的卡片,并且将结束会话。

AlexaResponse

有几个有用的类可用于生成符合亚马逊回声友好的JSON响应。这些类并没有什么特别复杂或神奇的地方,它们只是让创建有效响应变得更加容易。

主要类是 AlexaResponse - 我打算每次都将此类的实例返回给Echo。您可以做一些有用的事情。

您可以在不执行其他任何操作的情况下返回此类的一个实例,这将是一个有效的响应(尽管相当无用!)

return new AlexaResponse;

您可以告诉Echo应该结束会话

$alexaResponse = new AlexaResponse;
$alexaResponse->endSession();

return $alexaResponse;

或者,您可以为语音/卡片/Reprompt对象添加一个(或两个),以将语音文本或卡片发送回Echo的最终用户(请注意,您不需要返回两者!)。

$alexaResponse = new AlexaResponse;
$alexaResponse->withSpeech(new Speech("Hello!!"));

$alexaResponse->withCard(new Card("Hello Title", "Hello Subtitle", "Hello content here!"));

return $alexaResponse;

您总是可以单行返回此对象

return new AlexaResponse(new Speech("Hello!!"), new Card("Hello Title", "Hello Subtitle", "Hello content here!"), true);

在这里,当第三个参数设置为true时,将结束会话。

测试

 $ phpunit --configuration phpunit.xml

谢谢

感谢 @jasonlewis - 我从他ding/api包中借鉴了很多关于路由片段的想法。

感谢大家查看这个。我猜在未来几周/几个月/一年中,亚马逊Echo开发者社区、开发者API等很多东西都会快速变化,我会尽我所能跟上这些变化,并肯定会查看和感谢任何拉取请求、功能请求等。

##//todo

我认为这个目前还处于beta版本。随着我继续真正测试它,我确信会出现一些错误,我非常欢迎任何反馈、错误报告、功能请求或评论。还有一些方面我还不确定我不会做一点点改变(例如,如果您使用Alexa::外观,它执行了大量的不同操作,我认为最好是将一些功能拆分。

  1. 找到一种不需要替换默认Application的方法!
  2. 在不需要用户返回AlexaResponse实例的情况下将会话添加到响应中
  3. 测试!!!!
  4. 为基于userIds的Echo设备/用户添加一些简单的身份验证选项
  5. 找出验证请求是否来自亚马逊的最佳方法 - 不确定这是否可行或将会可行,但希望很快就会实现
  6. 为解析来自Alexa的语音添加基本辅助工具 - 并非“完成”,但我已经添加了一些选项来帮助。我非常期待您对如何实现这种帮助提出意见!