maxbeckers/amazon-alexa-php

Php library for amazon echo (alexa) skill development.

Installs: 46 077

Dependents: 3

Suggesters: 0

Security: 0

Stars: 113

Watchers: 13

Forks: 30

Open Issues: 1

pkg:composer/maxbeckers/amazon-alexa-php

2.1.0 2025-10-06 14:16 UTC

README

Build Status Scrutinizer Code Quality Coverage Status MIT Licence contributions welcome

Amazon Alexa PHP Library

A modern PHP library for building Amazon Alexa skills with clean, maintainable code. This library simplifies handling Alexa requests by providing a robust validation system, flexible request handlers, and helper utilities for common tasks.

🚀 Features

  • Request Validation: Automatic verification of Amazon request signatures
  • Flexible Handler System: Easy-to-extend request handler architecture
  • SSML Support: Built-in Speech Synthesis Markup Language generator
  • APL Support: Create and send Alexa Presentation Language documents, components, directives, gestures and commands
  • Device Address API: Helper for accessing user location data
  • PHP 8.2+ Ready: Leverages modern PHP features and type safety
  • Symfony Integration: Available bundle for Symfony applications

📋 Requirements

  • PHP 8.2 or higher
  • Composer

🔧 Installation

composer require maxbeckers/amazon-alexa-php

🚀 Quick Start

Basic Request Handling

<?php

use MaxBeckers\AmazonAlexa\Request\Request;
use MaxBeckers\AmazonAlexa\Validation\RequestValidator;
use MaxBeckers\AmazonAlexa\RequestHandler\RequestHandlerRegistry;

// 1. Parse incoming request
$requestBody = file_get_contents('php://input');
$alexaRequest = Request::fromAmazonRequest(
    $requestBody, 
    $_SERVER['HTTP_SIGNATURECERTCHAINURL'] ?? '', 
    $_SERVER['HTTP_SIGNATURE'] ?? ''
);

// 2. Validate request authenticity
$validator = new RequestValidator();
$validator->validate($alexaRequest);

// 3. Handle request
$registry = new RequestHandlerRegistry();
$registry->addHandler(new MyIntentHandler());

$handler = $registry->getSupportingHandler($alexaRequest);
$response = $handler->handleRequest($alexaRequest);

// 4. Send response
header('Content-Type: application/json');
echo json_encode($response);

🎯 Creating Request Handlers

Simple Intent Handler (PHP 8.2+)

<?php

use MaxBeckers\AmazonAlexa\Request\Request;
use MaxBeckers\AmazonAlexa\Response\Response;
use MaxBeckers\AmazonAlexa\RequestHandler\AbstractRequestHandler;
use MaxBeckers\AmazonAlexa\Request\Request\Standard\IntentRequest;

class WelcomeIntentHandler extends AbstractRequestHandler
{
    public function __construct(
        private readonly array $supportedApplicationIds = ['amzn1.ask.skill.your-skill-id']
    ) {
        parent::__construct();
    }

    public function supportsRequest(Request $request): bool
    {
        return $request->request instanceof IntentRequest &&
               $request->request->intent->name === 'WelcomeIntent';
    }

    public function handleRequest(Request $request): Response
    {
        return $this->responseHelper->respond(
            outputSpeech: 'Welcome to our amazing skill!',
            shouldEndSession: false
        );
    }
}

Advanced Handler with Slots

<?php

use MaxBeckers\AmazonAlexa\Request\Request;
use MaxBeckers\AmazonAlexa\Response\Response;
use MaxBeckers\AmazonAlexa\RequestHandler\AbstractRequestHandler;
use MaxBeckers\AmazonAlexa\Request\Request\Standard\IntentRequest;

class UserInfoHandler extends AbstractRequestHandler
{
    public function __construct(
        private readonly array $supportedApplicationIds = ['amzn1.ask.skill.your-skill-id']
    ) {
        parent::__construct();
    }

    public function supportsRequest(Request $request): bool
    {
        return $request->request instanceof IntentRequest &&
               $request->request->intent->name === 'GetUserInfoIntent';
    }

    public function handleRequest(Request $request): Response
    {
        $intentRequest = $request->request;
        $userName = $intentRequest->intent->slots['userName']->value ?? 'friend';
        
        $message = match($userName) {
            'admin' => 'Hello administrator! You have special privileges.',
            'guest' => 'Welcome, guest user. Limited features available.',
            default => "Nice to meet you, {$userName}!"
        };

        return $this->responseHelper->respond($message);
    }
}

🎤 SSML Generation

Create rich speech responses with the SSML generator:

<?php

use MaxBeckers\AmazonAlexa\Helper\SsmlGenerator;

$ssmlGenerator = new SsmlGenerator();
$ssmlGenerator
    ->say('Welcome to our cooking skill!')
    ->pauseStrength(SsmlGenerator::BREAK_STRENGTH_MEDIUM)
    ->say('Today we will learn about')
    ->emphasis('amazing', SsmlGenerator::EMPHASIS_STRONG)
    ->say('pasta recipes.')
    ->pauseTime('2s')
    ->say('Let\'s get started!');

$ssml = $ssmlGenerator->getSsml();
// Result: <speak>Welcome to our cooking skill! <break strength="medium" /> Today we will learn about <emphasis level="strong">amazing</emphasis> pasta recipes. <break time="2s" /> Let's get started!</speak>

🖼 APL (Alexa Presentation Language)

Build multimodal experiences with the included APL directive, component, command, and gesture classes:

<?php

use MaxBeckers\AmazonAlexa\Response\Directives\APL\RenderDocumentDirective;
use MaxBeckers\AmazonAlexa\Response\Response;
use MaxBeckers\AmazonAlexa\ResponseHelper;

// Inside a request handler:
$document = [
    'type' => 'APL',
    'version' => '1.8',
    'mainTemplate' => [
        'items' => [
            [
                'type' => 'Text',
                'text' => '${payload.data.message}',
                'style' => 'textStylePrimary1'
            ]
        ]
    ],
];

$dataSources = [
    'data' => [
        'message' => 'Hello from APL!'
    ],
];

$aplDirective = new RenderDocumentDirective(
    token: 'mainScreen',
    document: $document,
    datasources: $dataSources
);

// Using the response helper (if available in your handler base)
$response = $this->responseHelper->respond(
    outputSpeech: 'Showing a visual response.',
    directives: [$aplDirective],
    shouldEndSession: false
);

// Or manually:
$alexaResponse = new Response();
$alexaResponse->response->directives[] = $aplDirective;

You can also leverage the rich PHP class model (components, commands, gestures, layouts) instead of raw arrays for stronger typing when building complex documents.

📍 Device Address Information

Access user location data with proper permissions:

<?php

use MaxBeckers\AmazonAlexa\Helper\DeviceAddressInformationHelper;

$addressHelper = new DeviceAddressInformationHelper();

try {
    // Get full address (requires "read::alexa:device:all:address" permission)
    $fullAddress = $addressHelper->getAddress($request);
    
    // Get country and postal code only (requires "read::alexa:device:all:address:country_and_postal_code" permission)
    $countryAndPostalCode = $addressHelper->getCountryAndPostalCode($request);
    
    $response = $this->responseHelper->respond(
        "I found your location in {$fullAddress->city}, {$fullAddress->stateOrRegion}"
    );
} catch (Exception $e) {
    $response = $this->responseHelper->respond(
        'I need permission to access your address. Please check your Alexa app.'
    );
}

🛡️ Error Handling

Implement robust error handling:

<?php

use MaxBeckers\AmazonAlexa\Exception\ValidationException;

try {
    $validator = new RequestValidator();
    $validator->validate($alexaRequest);
} catch (ValidationException $e) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid request signature']);
    exit;
} catch (Exception $e) {
    http_response_code(500);
    error_log('Alexa skill error: ' . $e->getMessage());
    echo json_encode(['error' => 'Internal server error']);
    exit;
}

🔗 Advanced Usage

Custom Response Builder

<?php

use MaxBeckers\AmazonAlexa\Response\Response;
use MaxBeckers\AmazonAlexa\Response\OutputSpeech;
use MaxBeckers\AmazonAlexa\Response\Card;

public function handleRequest(Request $request): Response
{
    $outputSpeech = new OutputSpeech();
    $outputSpeech->type = OutputSpeech::TYPE_SSML;
    $outputSpeech->ssml = '<speak>Custom SSML response</speak>';
    
    $card = new Card();
    $card->type = Card::TYPE_SIMPLE;
    $card->title = 'Skill Response';
    $card->content = 'This appears in the Alexa app';
    
    $response = new Response();
    $response->outputSpeech = $outputSpeech;
    $response->card = $card;
    $response->shouldEndSession = false;
    
    return $response;
}

Registry with Multiple Handlers

<?php

$registry = new RequestHandlerRegistry();
$registry->addHandler(new LaunchRequestHandler());
$registry->addHandler(new WelcomeIntentHandler());
$registry->addHandler(new HelpIntentHandler());
$registry->addHandler(new StopIntentHandler());
$registry->addHandler(new SessionEndedRequestHandler());

🎛️ Symfony Integration

For Symfony applications, use the dedicated bundle:

composer require maxbeckers/amazon-alexa-bundle

Visit maxbeckers/amazon-alexa-bundle for detailed integration instructions.

📚 Documentation

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.