Retrieve the location from an Amazon Alexa device

This tutorial assumes you have already set up your Amazon Developer account, have a externally accessible endpoint server able of running PHP, and have a skill with intents set up (If not start here first). It is designed to help you get started and therefore does not include error or session management.

The API docs for this feature can be found at https://developer.amazon.com/docs/custom-skills/device-address-api.html

First things first, lets let the JSON contents of the request sent from the Echo device and store it in a variable called $echoRequest

Here is an example of what Alexa received from your Echo device

{
   "version":"1.0",
   "session":{
      "new":true,
      "sessionId":"amzn1.echo-api.session.aa11bb22-cc33-dd44-ee55-abcdef123456",
      "application":{
         "applicationId":"amzn1.ask.skill.aa11bb22-cc33-dd44-ee55-abcdef123456"
      },
      "user":{
         "userId":"amzn1.ask.account.AAAAAABBBBBBCCCCCCDDDDDD",
         "permissions":{
            "consentToken":"Atza|123abc123abc123abc"
         }
      }
   },
   "context":{
      "AudioPlayer":{
         "playerActivity":"STOPPED"
      },
      "System":{
         "application":{
            "applicationId":"amzn1.ask.skill.123456-aaaa-bbbb-1234-1234adbc5678"
         },
         "user":{
            "userId":"amzn1.ask.account.AAAA1111BBBB2222",
            "permissions":{
               "consentToken":"Atza|123abc123abc123abc"
            }
         },
         "device":{
            "deviceId":"amzn1.ask.device.BBBB2222CCCC3333",
            "supportedInterfaces":{
               "AudioPlayer":{

               }
            }
         },
         "apiEndpoint":"https://api.eu.amazonalexa.com"
      }
   },
   "request":{
      "type":"IntentRequest",
      "requestId":"amzn1.echo-api.request.aa11bb22-cc33-dd44-ee55-abcdef123456",
      "timestamp":"2017-10-29T15:47:35Z",
      "locale":"en-GB",
      "intent":{
         "name":"bin",
         "confirmationStatus":"NONE"
      }
   }
}

And now lets wrap that into a variable for use

<?php
$echoRequest   = json_decode(file_get_contents('php://input'));
?>

Now we have our request we’re going to need to pull out 3 pieces of information initially to make our location call, these are the consentToken, deviceId and apiEndpoint. As we used json_decode to take our JSON encoded string request and convert it into a PHP variable we can cherry pick the bits we need easily.

<?php
$consentToken  = $echoRequest->context->System->user->permissions->consentToken;
$deviceID      = $echoRequest->context->System->device->deviceId;
$apiEndpoint   = $echoRequest->context->System->apiEndpoint;
?>

Next, lets create a cURL call to pass the information received in the original request to the address lookup endpoint (remember there are 2 types of lookup, Get Country And Postal Code and Get Address. You cannot mix and match so if your skill has only asked for permission for the full address you cannot ask for just the Country and PostalCode and vice versa.

Here we create the required headers including the content type and Authorisation token based on the consentToken (context->System->user->permissions->consentToken). We then create our stream context and using the file_get_contents call sent the header to the specific URL.

As you can see the URL we call is also dynamic and based on the device region endpoint (context->System->apiEndpoint) as well as the deviceId (context->System->device->deviceId)

<?php
$opts = array('http' =>
    array(
        'method'  => 'GET',
        'header'  => array("Authorization: Bearer $consentToken", "Content-Type: application/json")
      )
);

$context  = stream_context_create($opts);

$countryAndPostalCode = file_get_contents($apiEndpoint.'/v1/devices/'.$deviceID.'/settings/address/countryAndPostalCode', false, $context);
?>

Lets wrap that all together into a basic function for easy usage

<?php

// get the initial request from Alexa
$echoRequest = json_decode(file_get_contents('php://input'));

// make a call to the getDeviceLocation function and write the result to the screen
echo getDeviceLocation($echoRequest);

// the main getDeviceLocation function
function getDeviceLocation($echoRequest)
{
    // set some variables and assign some values to them
    $result               = '';
    $consentToken         = $echoRequest->context->System->user->permissions->consentToken;
    $deviceID             = $echoRequest->context->System->device->deviceId;
    $apiEndpoint          = $echoRequest->context->System->apiEndpoint;
    
    // set the header options
    $opts                 = array(
        'http' => array(
            'method' => 'GET',
            'header' => array(
                "Authorization: Bearer $consentToken",
                "Content-Type: application/json"
            )
        )
    );

    // create the header
    $context              = stream_context_create($opts);

    // send the header to the created URL
    $countryAndPostalCode = file_get_contents($apiEndpoint . '/v1/devices/' . $deviceID . '/settings/address/countryAndPostalCode', false, $context);
    
    // return the response
    return $countryAndPostalCode;
}
?>

if everything has gone ok, and the device has actually allowed you access to this info (check out my other posts for more on this) you should get a response similar to this.

{  
   "countryCode":"GB",
   "postalCode":"AB1 2DE"
}

If you want the entire address simply amend your skill to request the full address via the Alexa dashboard, then alter your API call removing the /countryAndPostalCode to

// send the header to the created URL
$countryAndPostalCode = file_get_contents($apiEndpoint . '/v1/devices/' . $deviceID . '/settings/address', false, $context);

This, once you allow (or re-allow if you’ve changed from postcode to cull address) should give you a JSON response similar to this:

{
  "addressLine1" : "10 High Street", 
  "addressLine2" : "Middle Ware", 
  "addressLine3" : "null",  
  "districtOrCounty" : "null", 
  "stateOrRegion" : "Kent", 
  "city" : "Hastings", 
  "countryCode" : "GB", 
  "postalCode" : "AB1 2DE"
}
0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *