Amazon Alexa PHP Hello World Example

created December 13, 2016, last updated May 12, 2017.

.

This Christmas (2016) a lot of people in Europe will be unpacking a shiny new Amazon Echo device and enjoying meaningful discussions with Alexa about life, the universe and everything.

If you are a geek like me then you will probably want Alexa to do a bit more than tell you about the weather or play Last Christmas by Wham. I bought my Amazon Echo Dot primarily to use for extremely important Home Automation tasks such as ‘Alexa, switch on the Christmas Tree lights‘.

The developer documentation from Amazon is good but very biased towards node.js. I know absolutely nothing about node.js and some of the online examples seemed overly complex to me. Eventually I found some useable PHP code examples and set about creating my own flexible PHP server side app for handling Alexa requests.

The app I created uses Alexa to send home automation commands via an Internet server to a home based Raspberry Pi server that lets me control Lights and Audio equipment. This is a step by step Hello World example using the same script that shows how relatively simple it is to create an Amazon Alexa App using PHP on your server to handle requests.

Before we start, here is a shopping list of things you will need :

  1. Amazon developer account
  2. Internet accessible web server (project tested with Apache)
  3. SSL Certificate
  4. PHP
  5. Amazon Echo

 

1. Install and Test the PHP Application

  • Download my example PHP application and extract it to your web server
  • create a folder that is writeable by your www server user, i.e. www-admin
    • configure this folder path as amazonCacheFolder in config.php
      • const amazonCacheFolder=’/home/www/amazon/cache/’;
  • make the file PAJ/www/Amazon/alexa.php web accessible
    • Test that the application is working by browsing to
      • https://www.your.server/youralias/alexa.php?debug
    • Make sure you see
      • PAJ\Application\Amazon\AlexaRequest
      • logfolder is writeable
    • note the debug curl information as this will be helpful in testing access to your application.

2. Register a Developer Account

Register and login to Amazon Developer Services at https://developer.amazon.com. You should register with the Amazon account you used to setup your Amazon Echo device. Once you are registered and logged in, click on the Alexa tab, and then the Get Started button for the Alexa Skills Kit and click the Add a New Skill button.

Getting started with Alexa
Getting started with Alexa
Add a new skill
Add a new skill

 

3. Create and Test the Alexa Skill

Skill Information

Amazon calls the process used to interact with the Alexa Voice Service a Skill. We will create a new private skill called Hello World.

Alexa Skill Information
Alexa Skill Information

 

  • Skill Type
    • choose Custom Interaction Model
  • Language
    • Select from drop down
  • Name
    • The name of the skill
      • Hello World
  • Invocation Name
    • This is the name we will use to activate the skill when talking to Alexa
      • hello world
        • Alexa, ask hello world to say hello world
  • Click Next

 

Interaction Model

Alexa Skill Interaction Model
Alexa Skill Interaction Model

The interaction model describes how the user will interact with the voice service. In the context of Alexa, an intent represents an action that fulfills a user’s spoken request. Intents can optionally have arguments called slots. The intent schema is configured as an array in JavaScript Object Notation (JSON) format.

For Hello World use the following intent json schema:
Show interaction model json

{
  "intents": [
    {
      "name": "AMAZON.CancelIntent",
      "samples": []
    },
    {
      "name": "AMAZON.HelpIntent",
      "samples": []
    },
    {
      "name": "AMAZON.StopIntent",
      "samples": []
    },
    {
      "name": "HelloWorld",
      "samples": [
        "say {command}",
        "for {command}",
        "{prompt}"
      ],
      "slots": [
        {
          "name": "command",
          "type": "COMMANDOBJECTS",
          "samples": []
        },
        {
          "name": "prompt",
          "type": "PROMPTOBJECTS",
          "samples": []
        }
      ]
    }
  ],
  "types": [
    {
      "name": "COMMANDOBJECTS",
      "values": [
        {
          "name": {
            "value": "hello world"
          }
        },
        {
          "name": {
            "value": "clever quotes"
          }
        }
      ]
    },
    {
      "name": "PROMPTOBJECTS",
      "values": [
        {
          "name": {
            "value": "yes"
          }
        },
        {
          "name": {
            "value": "no"
          }
        }
      ]
    }
  ]
}
Here we define our intent name HelloWorld and associated slots. You can think of slots as variables to the intent, we have a slot (variable) named command with possible values of type OBJECT.

Edit the object type by clicking the EDIT button.

Custom Object Type
Custom Object Type

The type name is the name we defined as the slot type – OBJECT. We can enter possible values for this object (up to 50,000), in this case we will use hello world.

Next we need to configure the sample utterances for the skill. These are what people can invoke the intents configured in the skill.

Sample Utterances
Sample Utterances

The sample utterance starts with the intent name HelloWorld, followed by any combination of words a user might use to interact with the skill, and then the slot name that corresponds with this interaction.

When a user interacts with our Alexa Skill

‘Alexa, ask hello world to say hello world’

The voice service try to determine the user intention by matching the spoken words to the configured utterances, invoking the configured intent and matching the slot values to the phrases provided to the slot. In this case it will match ‘hello world‘ to the value configured in the command slot of the HelloWorld intent. This data will be sent to our server for us to process.

Why use slots? By using the amazon voice service to process and match the users spoken words to a configured set of slot variables (object types) we do not have to process the spoken words ourselves, we simply match the slot type to the command or processes we want to execute making it easier to determine user intent.

As of early 2017 Alexa are offering an improved interaction model builder called the Skills Builder kit, the skills builder kit allows you to create your interaction model with a graphical interface allowing you to configure your intent, utterances and slots much easier and to implement the new dialog features.

Click Next to continue.

Configuration

Configuration
Configuration

Now we will configure how the Skill communicates with our PHP application.

  • Select HTTPS
  • Select the geographical location closest to your server
  • Enter the URL to the Alexa php script on your server
    • https://www.your.server/youralias/alexa.php

 

Click Next.

SSL Certificate

SSL Certificate
SSL Certificate

Assuming your web server has a valid SSL certificate select ‘My development endpoint has a certificate from a trusted certificate authority’.

Click Next.

TEST

We can now test the Skill and server PHP application by using the service simulator.

Testing Alexa Skill
Testing Alexa Skill

 

In the Enter Utterance text box we can type the phrase we would say to invoke the application using our Echo device

Alexa, ask hello world to say hello world

The application will fail with an exception error if you have not yet added your amazon credentials to the config file in PAJ/Application/Amazon/Alexa/config.php. You can see the application id and userid in the service request. Copy these and add them to config.php.

	// AMAZON ALEXA
	const amazonSkillId = 'amzn1.ask.skill.XXX';
	const amazonUserId = 'amzn1.ask.account.XXX';
	const amazonEchoServiceDomain = 'echo-api.amazon.com';
	const amazonCacheFolder='/home/www/amazon/cache';

Run the test again. If the application is working you will see the service response JSON data returned from our PHP application, and the text that would be spoken by the Echo device.

  "response": {
    "outputSpeech": {
      "type": "PlainText",
      "text": "OK, I will now say hello world"
    },

Publishing

The publishing information is used to define how the app will appear to users if it is made public. This includes the category, countries the app will be available in, description, sample phrases and images.

This information will also be displayed in the Alexa mobile app.

As this is a private development skill, we do not want to publish it to all users.

 

Privacy & Compliance

Complete the privacy and Compliance section and click Save to save the Skill.

 

4. Test with Amazon Echo device

To use your newly created Hello World skill with your Echo device make sure the skill is visible and enabled in the Alexa app, under Home -> Skills select Your Skills

 

Select your skill in Alexa App
Select your skill in Alexa App

Now say to Alexa

Alexa, ask hello world to say hello world

Your Echo device will respond with

OK, I will now say hello world

You can also say, ‘Alexa, open hello world‘, this initiates a Launch Request.

Ok, so this is a bit lame, change the output text response by modifying the response text in the HelloWorld.php intent return array.

	return array(
		'intent' => array(
			'response' => 'OK, I will now say something much more meaningful',
			'target' => $_target,
			'status' => false
		)
	);

How the PHP application works

The PHP server side process is relatively straightforward:

  • Amazon sends the Alexa request data as an HTTP POST request to alexa.php.
    • alexa.php initiates the AlexaRequest class which
      • loads config data
      • gets the Alexa POST json data
      • validates the Alexa Request as per the guidelines here. This includes :
        • Validating the amazon application id
        • Verifying that the Request was Sent by Alexa
          • determine whether the URL meets each of the following criteria:
            • The protocol is equal to https (case insensitive).
            • The hostname is equal to s3.amazonaws.com (case insensitive).
            • The path starts with /echo.api/ (case sensitive).
            • If a port is defined in the URL, the port is equal to 443.
        • Validate the Signature of the Request
        • Validate the Timestamp of the Request
      • renders the alexa JSON response by
        • rendering default intent responses
          • STOP, CANCEL, HELP
        • render LaunchRequest response
          • open hello world
        • initiating PAJ\Application\Amazon\Alexa\Intent\IntentName()
        • processing the Amazon intent data
          • formulating a text response based on the process data, in this case simply returning the response text for hello world
            • OK, I will now say hello world
          • managing session attribute data
        • wrapping the response text and card data into a JSON request and outputting it

If you look at HelloWorld.php in Alexa/Intent you will see how we are parsing the intent data from Amazon, looping through the slot data and performing an action on each slot. In this case looking for the ‘command’ slot, validating the spoken words and then acting on them to formulate a response.

 

Further customisation

Here you can also see how you can now further customise the application. For example suppose you want to ask alexa to turn the lounge lights on

‘Alexa, ask Home to switch the lounge lights on’

Here my Alexa Skill is called Home, my intent name is Command, and I have configures a slot called switch which contains object types (variables) such as ‘lounge lights on’ and ‘lounge lights off’.

In Alexa/Intent/Command.php I parse the intent data to find the switch slot, verify that the slot value contains either ‘lounge lights on’, or ‘lounge lights off’ and the send the appropriate commands to my home automation system, i.e. FHEM. When the command has been successfully executed I can return the appropriate response.

‘Ok, I have switched the lounge lights on’

Debugging

If the Application is not working as expected check out the logfiles in your cache folder, for each Amazon Alexa request you will see the request, intent and response data logged in a file called helloworld_yyyy-mm-dd.log.

Use the skills tester in the Amazon skill builder to test and debug your skill. To debug further use the example curl command from the debug page. Execute this from a bash terminal to run curl and simulate an alexa request to your application.

Amazon Default Intents

You will notice that Amazon includes some default intents in the interaction model : AMAZON.StopIntent, AMAZON.CancelIntent, AMAZON.HelpIntent. If you want to publish your skill you must also include responses for these default intents.

Prompt and Response Dialog

Having completed a basic Alex command skill I will extend this PHP example to allow for prompts and responses in part 2 of this blog post.

 

Comments

  1. Richard says:

    Dear Sir:
    This article is really helpful to me.
    I haved completed the steps above and can let Alexa say “hello world” to me.
    But, I have a question,
    I have a WIFI IoT plug too, I can turn it “ON” or “OFF” through API now.
    And, I would like to let Alexa to turn it “ON” or “OFF” (maybe use the API).
    For example, ‘Alexa, ask HomePlug to turn the plug on’.
    Would you please show me the steps or examples for reference?
    BTW, do you know any article/reference that can let Alexa to “find” my device (plug).
    I can modify the firmware if needed.

    Any hints appreciated.
    Thanks in advance.

    Best Regards
    Richard

  2. Peter Freimann says:

    Hey,

    thanks a lot for the great work! I set up the example project and extented it already.
    Currently I try to figure out, how one could ask questions back from Alexa.

    For instance, when I have an intend with two slotItem, and the first one is given, so Alexa could ask back: “Okay, I understand, you would like to do . Could you please tell me what is your ?”

  3. Hastaelnabo2000 says:

    Hi,
    nice explained. Trying to test it I always get following error:
    “Exception error, HTTP GET when POST was expected”
    Line 152 of AlexaRequest.php file

      • PAJ says:

        I have included some new debug information including a curl command that will simulate a post from the command line. You can see the debug info by browsing to alexa.php?debug

  4. Jens says:

    You probably should state somewhere in the begining of the article, that your demo project requires an apache webserver not an »internet accessible webserver« since it runs into a fatal error while using nginx+php-fpm.

  5. JK says:

    Thanks for sharing! That’s a nice starting point.

    There are two issues while testing on nginx + php 7.1:

    1)
    PAJ\Application\Amazon\Alexa\Intent\Data:

    Add “static” keyword to function cleverQuotes to prevent a php Warning:
    static function cleverQuotes()

    2)
    PAJ\Application\Amazon\AlexaRequest:

    I changed
    $_headers = apache_request_headers();
    to
    $_headers = $_REQUEST; // Or $_POST

    to make it working with nginx

    • PAJ says:

      Thanks for pointing that out, I will update the code with a non apache specific header request function.