AWS Developer Tools Blog

Receiving Amazon SNS Messages in PHP

A little over a year ago, we announced a new feature in the AWS SDK for PHP that allowed customers to validate inbound SNS messages. In the latest version of the SDK, this functionality is now available in its own package, one that does not depend on the SDK, so it’s simpler to listen to SNS topics with lightweight web services. In this blog post, I’ll show you how to use the Amazon SNS message validator for PHP to parse messages in a single-file web application.

About SNS

Amazon Simple Notification Service (Amazon SNS) is a fast and fully managed push messaging service that can deliver messages over email, SMS, mobile push, and HTTP/HTTPS endpoints.

With Amazon SNS, you can set up topics to publish custom messages to subscribed endpoints. SNS messages are used by many of the other AWS services to communicate information asynchronously about your AWS resources. Some examples include:

  • Configuring Amazon Glacier to notify you when a retrieval job is complete.
  • Configuring AWS CloudTrail to notify you when a new log file has been written.
  • Configuring Amazon Elastic Transcoder to notify you when a transcoding job changes status (e.g., from “Progressing” to “Complete”)

Receiving SNS Messages and Verifying Their Signature

Using the SNS Message Validator’s Message class, you can easily parse raw POST data from SNS:

<?php

require 'path/to/vendor/autoload.php';

$message = AwsSnsMessage::fromRawPostData();
echo $message->get('Message');

Amazon SNS sends different types of messages, including SubscriptionConfirmation, Notification, and UnsubscribeConfirmation. The formats of these messages are described in the Appendix: Message and JSON Formats section of the Amazon SNS Developer Guide.

Messages from Amazon SNS are signed. As a best practice, you should use the MessageValidator class to verify the signature and ensure a message was sent from Amazon SNS.

<?php

use AwsSnsMessage;
use AwsSnsMessageValidator;

$message = Message::fromRawPostData();

// Validate the message
$validator = new MessageValidator();
$validator->validate($message);

Instances of AwsSnsMessageValidator have two methods for validating messages, both of which take an instance of AwsSnsMessage as their only argument. validate (shown above) will throw an AwsSnsExceptionInvalidSnsMessageException. isValid will return a Boolean — true for valid messages and false for invalid ones.

Confirming a Subscription to a Topic

In order for an HTTP(S) endpoint to receive messages, it must first be subscribed to an SNS topic. Subscriptions are confirmed over HTTP(S), so you’ll need to create and deploy an endpoint before you set up a subscription. SubscriptionConfirmation messages provide a URL you can use to confirm the subscription.

$message = AwsSnsMessage::fromRawPostData();

// Validate the message
$validator = new MessageValidator();
if ($validator->isValid($message)) {
    file_get_contents($message->get('SubscribeURL'));
}

Handling Notifications

Let’s put it all together and add some extra code for handling both notifications and subscription control messages.

<?php

if ('POST' !== $_SERVER['REQUEST_METHOD']) {
    http_response_code(405);
    die;
}

require 'path/to/vendor/autoload.php';

try {
    $message = AwsSnsMessage::fromRawPostData();
    $validator = new AwsSnsMessageValidator();
    $validator->validate($message);

    if (in_array($message['Type'], ['SubscriptionConfirmation', 'UnsubscribeConfirmation']) {
        file_get_contents($message['SubscribeURL']);
    }

    $log = new SplFileObject('../messages.log', 'a');
    $log->fwrite($message['Message'] . "n");
} catch (Exception $e) {
    http_response_code(404);
    die;
}

Conclusion

As you can see, receiving, verifying, and handling Amazon SNS messages is simple. Setting up your application to receive SNS messages will allow you to create applications that can handle asynchronous communication from AWS services and other parts of your application.