I'm Max Beckers, Solution Architect at PAYONE a Worldline company.
- php / symfony (Certified Developer)
- java / spring boot
- kubernetes & helm
- software architecture
Php library for amazon echo (alexa) skill development.
License: MIT License
$backgroundImage = new Image();
$backgroundImage->sources = [['url' => $this->liveUrl.'/assets/start_bg.png']];
There is a api to get address informations for the device : https://developer.amazon.com/de/docs/custom-skills/device-address-api.html
The RequestValidator
in not complete under unit tests. It's not that easy because of openssl
connects.
It will be helpful to create some default handlers for the base intents. For the most base intents is only a response text needed, so this can be created very abstract.
Should be created for the following base alexa intents:
Hi,
I am trying to add a background image to a Display Interface body template.
I tried the following code:
$backgroundImage = new Image();
$backgroundImage->contentDescription = "Some Background";
$imageSource = new ImageSource();
$imageSource->url = 'https://example.com/some/image.jpg';
$backgroundImage->sources = [$imageSource];
$template->backgroundImage = $backgroundImage;
This code produces the following JSON response:
"sources": [
{
"url": "https://example.com/some/image.jpg",
"size": null,
"widthPixels": null,
"heightPixels": null
}
]
The Amazon API seems to have a problem with the empty values (for size, widthPixels and heightPixels)
This code works fine:
$backgroundImage = new Image();
$backgroundImage->contentDescription = "Some Background";
$backgroundImage->sources = [['url' => 'https://example.com/some/image.jpg']];
The properties for for size, widthPixels and heightPixels should therefore be omited in the response.
Cheers,
Fabian
Since April 2018 AudioItem also accepts metadata to output information on the screen of Echo devices.
This possability is currently missing.
Hi,
I wrote following code with you library:
$Stream = Stream::create('https://foo.com/bar.mp3',0815,null,0);
$AlbumImage = Image::create('description','https://foo.com/bar.jpg');
$Metadata = Metadata::create('Tracktitle','Albumname',$AlbumImage);
$AudioItem = AudioItem::create($Stream,$Metadata);
And it genereates the following JSON:
{
"version": "1.0",
"sessionAttributes": [
]
,
"response": {
"directives": [
{
"playBehavior": "REPLACE_ALL",
"audioItem": {
"stream": {
"url": "https:\/\/foo.com\/bar.mp3",
"token": "0815",
"offsetInMilliseconds": 0 }
,
"metadata": {
"title": "Tracktitle",
"subtitle": "Albumname",
"art": {
"contentDescription": "description",
"sources": "https:\/\/foo.com\/bar.jpg" }
}
}
,
"type": "AudioPlayer.Play" }
]
}
}
`Acording to https://developer.amazon.com/de/docs/custom-skills/audioplayer-interface-reference.html#play it should genereate:`
{
"type": "AudioPlayer.Play",
"playBehavior": "valid playBehavior value such as ENQUEUE",
"audioItem": {
"stream": {
"url": "https://cdn.example.com/url-of-the-stream-to-play",
"token": "opaque token representing this stream",
"expectedPreviousToken": "opaque token representing the previous stream",
"offsetInMilliseconds": 0
},
"metadata": {
"title": "title of the track to display",
"subtitle": "subtitle of the track to display",
"art": {
"sources": [
{
"url": "https://cdn.example.com/url-of-the-album-art-image.png"
}
]
},
"backgroundImage": {
"sources": [
{
"url": "https://cdn.example.com/url-of-the-background-image.png"
}
]
}
}
}
}
Notice the "art" part:
Your library:
"art": {
"contentDescription": "description",
"sources": "https:\/\/foo.com\/bar.jpg" }
Amazon:
"art": {
"sources": [
{
"url": "https://cdn.example.com/url-of-the-album-art-image.png"
}
]
},
(sorry for wrong styling)
This is a huge issue.
But would be very nice: Implement the full Smart Home API.
For more Details see https://developer.amazon.com/de/docs/device-apis/alexa-brightnesscontroller.html.
Here we don't have a type to find the request type class. So we should use the values directive.header.namespace
and directive.header.name
to detect the request type.
The lang
-Tag is not implemented now, but very useful. So the SSMLGenerator needs a funtion to support this tag.
https://developer.amazon.com/de/docs/custom-skills/speech-synthesis-markup-language-ssml-reference.html#lang
The audio tag in ssml currently only allows .mp3
files. But the Amazon internal sounds don't have this extension. See https://developer.amazon.com/de/docs/custom-skills/transportation-sounds.html. In code see https://github.com/maxbeckers/amazon-alexa-php/blob/master/src/Helper/SsmlGenerator.php#L53
The gadgets api is still in beta, but can be implemented now: https://developer.amazon.com/de/docs/custom-skills/gadget-controller-interface-reference.html
Downloading certificate in RequestValidator->validateSignature
uses file_get_contents
and thus depends on allow_url_fopen
to be enabled. For security reasons this is not the case on many servers. In these cases file_get_contents
will fail and simply return an empty string. The validation will fail as well of course.
Can be fixed by using curl
instead or as fallback:
if (ini_get('allow_url_fopen')) {
$certData = @file_get_contents($request->signatureCertChainUrl);
} else {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $request->signatureCertChainUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$certData = curl_exec($ch);
curl_close($ch);
}
Create a example with a user.
Hi,
first of all, thank you for you work!
I think i have found some issues / got some questions.
-> by this, isnt it impossible to use the "supportsRequest"-Methot like described in the manual as following:
return $request->request instanceOf Request\Standard\IntentRequest &&
'MyTestIntent' === $request->request->intent->name;
?
########
########
There seems to be an Error on nginx, maybe you should implement this: http://php.net/manual/en/function.getallheaders.php#84262
########
Using this, with an letsEncrypt Certificate i get the following error:
[proxy_fcgi:error] AH01071: Got error 'PHP message: PHP Fatal error: Uncaught MaxBeckers\AmazonAlexa\Exception\RequestInvalidSignatureException: Cert ssl verification failed. in .../src/Validation/RequestValidator.php:81\n
Stack trace:\n#0 ...src/Validation/RequestValidator.php(24): MaxBeckers\AmazonAlexa\Validation\RequestValidator->validateSignature(Object(MaxBeckers\AmazonAlexa\Request\Request))\n#1 ...alexa/amazon-alexa-php/examples/simple-intent-request.php(78): MaxBeckers\AmazonAlexa\Validation\RequestValidator->validate(Object(MaxBeckers\AmazonAlexa\Request\Request))\n#2 {main}\n thrown in ...alexa/amazon-alexa-php/src/Validation/RequestValidator.php on line 81\n'
Any suggestions / hints / updated ?! :)
Thank you!
To remove the toJson workaround to create the response for amazon i would prefer to use https://github.com/schmittjoh/serializer . Then it can be handled via annotation.
It would be useful if there was the ability to handle alexa skill events such as AlexaSkillEvent.SkillDisabled and AlexaSkillEvent.SkillPermissionAccepted which are just different request types.
According to the Amazon documentation, a SessionEndedRequest may not get a response.
In this library however, a RequestHandler must return a Response Object (see AbstractRequestHandler::handleRequest).
Should we allow AbstractRequestHandler::handleRequest to return null or create an EmptyResponse class that returns NULL when it is serialized to JSON?
Or do you have another idea?
Implement handling for Dialog Interface: https://developer.amazon.com/de/docs/custom-skills/dialog-interface-reference.html
Create an Example with a Card in Response.
The sources /src/Response/Directives/Dialog/*
do not have any unit tests atm. With this issue some tests should be written.
Following any of your example I getting:
[error][MaxBeckers\AmazonAlexa\Exception\MissingRequestHandlerException] MaxBeckers\AmazonAlexa\Exception\MissingRequestHandlerException in /home/alexa/www/vendor/maxbeckers/amazon-alexa-php/src/RequestHandler/RequestHandlerRegistry.php:41
Stack trace:
#0 /home/alexa/www/controllers/AlexaController.php(54): MaxBeckers\AmazonAlexa\RequestHandler\RequestHandlerRegistry->getSupportingHandler(Object(MaxBeckers\AmazonAlexa\Request\Request))
#1 [internal function]: app\controllers\AlexaController->actionIndex()
In my dev environment, I would like to override the validateSignature()
& validationTimestamp
methods in the MaxBeckers\AmazonAlexa\Request\Request\AbstractRequest
for obvious reasons.
Unfortunately, I cannot override these methods as the Request classes are hardcoded in the MaxBeckers\AmazonAlexa\Request\Request
class (line 31 - 50) which prevents me from creating my own classes to override the methods I have mentioned.
Ideally, having a setter to override the values returned from the 2 methods I have mentioned.
Hello,
can you help with an Example for Delegate with User-Dialog? Alexa return my question, but i can´t fill value of slot.
$DelegateDirective = DelegateDirective::create();
$this->responseHelper->directive($DelegateDirective);
return $this->responseHelper->respond("Wie groß bist du?");
On Echo Console it will returned:
[reason] => ERROR
[error] => MaxBeckers\AmazonAlexa\Request\Request\Error Object
(
[type] => INVALID_RESPONSE
[message] => The following directives are not supported: DelegateDirective
)
Thanks for help!
Hi, I'm building my first PHP endpoint for an Alexa Skill. I see that Alexa when I run the invocation, sends a request JSON with the type LaunchRequest, how can I handle the first LaunchRequest?
Thank you!
Hi, and thanks for your lib. We use it since 2 or 3 years now.
Actually I have a problem when I try to send a skill for certification - the prechecks fail with
"The skill end-point is not accepting valid signed requests.
and on server side - an nginx webserver with valid ssl certificate I get this error in log file:
2021/11/18 08:20:55 [error] 7286#7286: *295852312 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught MaxBeckers\AmazonAlexa\Exception\RequestInvalidSignatureException: Cert ssl verification failed. in /home/data/.../backend/vendor/maxbeckers/amazon-alexa-php/src/Validation/RequestValidator.php:166 Stack trace: #0 /home/data/.../backend/vendor/maxbeckers/amazon-alexa-php/src/Validation/RequestValidator.php(110): MaxBeckers\AmazonAlexa\Validation\RequestValidator->verifyCert(Object(MaxBeckers\AmazonAlexa\Request\Request), '-----BEGIN CERT...') #1 /home/data/.../backend/vendor/maxbeckers/amazon-alexa-php/src/Validation/RequestValidator.php(56): MaxBeckers\AmazonAlexa\Validation\RequestValidator->validateSignature(Object(MaxBeckers\AmazonAlexa\Request\Request)) #2 /home/data/.../backend/interface/index.php(43): MaxBeckers\AmazonAlexa\Validation\RequestValidator->validate(Object(MaxBeckers\AmazonAlexa\Request\Request)) #3 {main} thrown in /home/data/" while reading response header from upstream, client: 72.21.217.106, server: ---.com, request: "POST /backend/interface/ HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.2-fpm.sock:", host: "---.com"
The skill still works in the test simulator and it worked also the last year. Nothing was changed on the code the last year and the prececks were running without problems the whole time. Something changed now with the signature check. I already removed the downloaded certificate from /tmp but without success.
Does anyone has an idea what may be wrong? Again, it is strange because the checks worked weeks before and only store meta data changed.
Best regards and thanks
Hi,
Permission request for address creates an 403 HTTP Status Code but can be fixed by delivering a dynamically created permission card.
Amazon provides this new Permission Card https://developer.amazon.com/de/docs/custom-skills/device-address-api.html#permissions-card.
Could you provide this card and create an example eventually?
Thanks
Using this package with one app id means $supportedApplicationIds
has to be set for every handler.
Maybe AbstractRequestHandler
should implement a new interface RequestHandler
for more flexibility?
Since AbstractRequestHandler
only contains one "real" method which checks if an app id is supported. Would PR if desired.
Update load certificate from file_get_contents
to https://github.com/guzzle/guzzle or at least to curl
$backgroundImage = new Image();
$backgroundImage->sources = [['url' => $this->liveUrl.'/assets/start_bg.png']];
Hi,
I am using a FOSRestController
to return the result of the RequestHandler
to Amazon as JSON. The problem is, that the underlying JMSSerializer
uses underscore naming while the Amazon API expects camel case:
class AlexaController extends AbstractFOSRestController {
public function alexaAction(Request $request) {
...
$responseData = $transformer->transformRequest(
$request,
$request->headers->get('SIGNATURECERTCHAINURL'),
$request->headers->get('SIGNATURE')
);
// The registered handler returns a simple text/speech response
// return $this->responseHelper->respond('Hello World!');
$view = $this->view($responseData, 200);
return $this->handleView($view);
}
}
// Response:
{
"version" : "1.0",
"session_attributes" : [],
"response" : {
"output_speech": ... <= Amazon expects "outputSpeech" instead
}
}
I know that I could change the naming strategy used by JMSSerializer
in the projects parameters.yml
file. However, this would change the behavior globally all over the project and thus affect existing APIs.
Is there any way to define which naming strategy (camel case) has to be used when serializing the response data?
At the end of my demo, if at question "do you want continue?" I respond "no", I would like send a last message "bye" then send a Stop directive.
my code in handleRequest method is
case 'AMAZON.NoIntent':
$directive = new StopDirective();
$this->responseHelper->directive($directive);
return $this->responseHelper->respond("See you next time!");
the in othe block
if ($request->request instanceof \MaxBeckers\AmazonAlexa\Request\Request\Standard\SessionEndedRequest) {
return $this->responseHelper->respond("Bye");
}
but the response is
{
"body": {
"version": "1.0",
"response": {
"directives": [
{
"type": "null"
}
],
"type": "_DEFAULT_RESPONSE"
},
"sessionAttributes": {}
}
}
and Alexa send a Error...
How can I solve?
The tests do not follow the psr-4 standard namespaces. This should be fixed.
As tile, this repository missed this file. Consider the following file:
Contributions are welcome and will be fully credited.
Please read and understand the contribution guide before creating an issue or pull request.
This project is open source, and as such, the maintainers give their free time to build and maintain the source code
held within. They make the code freely available in the hope that it will be of use to other developers. It would be
extremely unfair for them to suffer abuse or anger for their hard work.
Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the
world that developers are civilized and selfless people.
It's the duty of the maintainer to ensure that all submissions to the project are of sufficient
quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used.
When requesting or submitting new features, first consider whether it might be useful to others. Open
source projects are used by many developers, who may have entirely different needs to your own. Think about
whether or not your feature is likely to be used by other users of the project.
Before filing an issue:
Before submitting a pull request:
If the project maintainer has any additional requirements, you will find them listed here.
PSR-2 Coding Standard - The easiest way to apply the conventions is to install PHP-CS-Fixer.
Add tests! - Your patch won't be accepted if it doesn't have tests.
Document any change in behaviour - Make sure the README.md
and any other relevant documentation are kept up-to-date.
Consider our release cycle - We try to follow SemVer v2.0.0. Randomly breaking public APIs is not an option.
One pull request per feature - If you want to do more than one thing, send multiple pull requests.
Send coherent history - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
Happy coding!
Generate helpers to create SSML output. For more details what the helper should represent methods for, see https://developer.amazon.com/de/docs/custom-skills/speech-synthesis-markup-language-ssml-reference.html
Amazon Polly is a text-to-speech tool from amazon (https://aws.amazon.com/de/polly/). With Polly you can use different Voices for your skill.
Amazon now supports the voice
tag for amazon polly integration. https://developer.amazon.com/de/docs/custom-skills/speech-synthesis-markup-language-ssml-reference.html#voice
Hi,
I am trying to receive the address from a device via the DeviceAddressInformationHelper class. Calling the getAddress function only returns a Permission Error. Already tried the new Permission Card function but even when allowing the location, the exception stays.
$helper = new DeviceAddressInformationHelper();
try {
$fullAddress = $helper->getAddress($request);
} catch (\Exception $exception) {
$fullAddress = null;
}
Hope you can help us through this
Thanks
Implement the CanFulfillIntentRequest, for more details about the request see https://developer.amazon.com/de/docs/custom-skills/understand-name-free-interaction-for-custom-skills.html#implement-canfulfillintent
For the Response in there an example: https://developer.amazon.com/de/docs/custom-skills/understand-name-free-interaction-for-custom-skills.html#canfulfillintent-sample-response
Hey,
first of all - thanks for your library! I encountered an issue during the use of SSMLGenerator
. By doing something like:
$generator = new SsmlGenerator();
$generator->say ("This & That");
print $generator->getSsml(), "\n";
An invalid SSML document is generated (and refused by Alexa), as it contains the "&" XML control character unescaped.
This reference should be useful. I think that using htmlspecialchars
on the input provided to say()
should be sufficient, I'll investigate.
Thanks,
Roberto
Any support for Alexa Presentation Language?
thank you very much for this great job,
Roberto
Hi, I appreciate your effort in making this.
is it possible to get this working with php 5.6? I see that you have set the minimum php version to 7.
Regards
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.