Help us understand the problem. What is going on with this article?

AWS SDK for PHP を用いた Amazon SNS の操作

More than 3 years have passed since last update.

AWS Lambda, SQS, HTTP/S, Email, SMS, モバイルデバイスなどに対して PUSH 通知を送ることができる Amazon SNS を AWS SDK for PHP を用いて操作する方法についてざっくりと見ていきます。なお、雰囲気をつかんだのちに、実装する際にはドキュメントを見ることを強くお勧めします。

SNSクライアントのインスタンス化

Amazon SNS の操作をするためのクライアントクラスは、以下のように直感的にインスタンス化できます。

<?php
require_once('./vendor/autoload.php');
use Aws\Sns\SnsClient;

$client = new SnsClient([
    'version' => 'latest',
    'region' => 'us-east-1', # 各自の利用しているregionを指定
    'profile' => 'default',  # ~/.aws/credentials 下に credential を置く
]);

デバイストークンの登録

APNSやGCMなどから発行されたデバイストークンは SnsClient#createPlatformEndpoint を用いて対応するアプリケーションへエンドポイント登録ができます。戻り値の 'EndpointArn' にデバイスに紐づく EndpointArn が格納されているので、個別のデバイスへの通知が必要な場合は、これを永続化する必要があります。

try {
    $platformApplicationArn = '<applicationのarn>';
    $token = '<デバイスから受け取ったデバイストークン>'
    $params = [
        'PlatformApplicationArn' => $platformApplicationArn,
        'Token' => $token,
    ];
    $result = $client->createPlatformEndpoint($params);

    $endpointArn = $result['EndpointArn'];  // 必要に応じて永続化
} catch (Aws\Sns\Exception\SnsException $e) {
    // 例外処理
}

なお、すでに登録されているデバイストークンを何度登録しても、正常に動作します(べき等性がある)。ただし、すでに登録されているデバイストークンが、異なる attribute(具体的にはUser Data)を持っている場合は例外が発生するので注意が必要です。こういったことは、AWSコンソールとコード両方からデバッグテストなどをしているときに発生しやすいと思います。

また、エンドポイントの Enabled が false になっていることをチェックしたければ、以下のように Attributes を指定してあげれば例外のほうに流れてくれます。

$params = [
    'PlatformApplicationArn' => $platformApplicationArn,
    'Token' => $token,
    'Attributes' => ['Enabled' => 'true'],
];
try {
    $result = $client->createPlatformEndpoint($params);

    $endpointArn = $result['EndpointArn'];  // 必要に応じて永続化
} catch (SnsException $e) {
    // トークンが登録済みで Enabled が false のときに例外に流れるようになる
}

トピックの作成・購読

デバイストークンをアプリケーションに登録するとエンドポイントが発行されます。エンドポイントへ個別に通知を送るのも良いですが、一斉におなじ内容の通知を送りたいこともあると思います。そんなときにはトピックというものが便利です。トピックにエンドポイントを紐付けておけば、トピック宛に通知を送るだけで、紐付いているエンドポイントに一斉にメッセージを送ることができます。トピックを作る場合は SnsClient#createTopic を使います。

$params = ['Name' => '<Topic名>'];
$result = $client->createTopic($params);

$topicArn = $result['TopicArn'];

続いてエンドポイントが TopicArn を購読するように処理を走らせます。

$params = [
   'Endpoint' => $endpointArn,
    'Protocol' => 'Application',
    'TopicArn' => $topicArn,
];

$result = $client->subscribe($params);
$subscriptionArn = $result['SubscriptionArn'];

このようにして、エンドポイントにトピックを購読させることができます。すでに無効になっているエンドポイントについても購読処理は正常に行うことができます。

プッシュ通知の送信

Amazon SNSを利用すれば、トピックや各デバイスなど様々な粒度でPUSH通知を送ることができます。通知には SnsClient#publish を使います。

$msg = [
    'Message' => 'hogehoge',
    'TargetArn' => '<TopicArn | EndpointArn>',
];

無効なエンドポイントに通知を行った場合、例外が発生します。ただし、トピックへ送った場合で、サブスクライバーの中に無効なエンドポイントがあっても正常に処理が行われます。JSONでメッセージを送る際には MessageStructure => 'json' をパラメタに追加してください。

$msg = array(
    'MessageStructure' => 'json',
    'TargetArn' => $topicArn,
    'Message' => json_encode(array(
        'default' => '<string>...',
        'APNS_SANDBOX' => json_encode(array(
            'aps' => array(
                'key' => 'value'
            )
        ))
    ))
);
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした