https://a.storyblok.com/f/270183/264733/fcab058396/sms-cupcake.png

フェイルオーバーでPHPからSMSを送信する:カップケーキベーカリー

最終更新日 May 4, 2021

所要時間:1 分

顧客と連絡を取り合うことは、どのような組織にとっても重要です。この投稿では Vonage Messages APIを紹介し、ビジネスが顧客に適した方法でメッセージを届けるためにどのように使用できるかを説明します。ケーススタディは、顧客にメッセージを送信する機能を必要とする架空の "カップケーキベーカリー "ビジネスです。この投稿では、現代のコミュニケーションの要である SMS を PHP のウェブアプリケーションで使う方法を示します。また、最初の試みが失敗した場合に、Messages API が他の通信チャネルを使ってメッセージを送信し、顧客に届く可能性を最大限に高める方法も紹介します。

もしあなたがアプリケーションに最新のメッセージング機能を実装する準備ができているウェブ開発者なら、このチュートリアルはあなたのためのものです!

材料を準備する

始める前に、以下の材料を集める必要がある:

  • PHPを一般に公開されているウェブサーバー上で実行するか、開発プラットフォーム上のPHPを以下のようなツールで実行します。 ngrokのようなツールを使って開発プラットフォーム上で PHP を実行します。Vonageはレスポンスを ウェブフックで応答を送信するので、アプリケーションに到達できる必要がある。

  • Vonage CLIをまだお持ちでない場合は、こちらをご覧ください。

  • SMSを送れる電話番号が2つあるともっと楽しいよ :)

Meetings APIとの出会い

Vonageは長い間SMS機能で知られてきましたが、Messages APIは新しいものです(まだベータ版です)。Messages APIを使用すると、単一のインターフェイスを使用して、さまざまなチャネルにメッセージを送信することができます。SMSよりもFacebook MessengerやWhatsAppにメッセージを送った方が安い場合が多く、Messages APIを使えば1つのツールを統合するだけでこれらすべてをカバーできる。また、時間の経過とともにメッセージチャンネルは追加されていくので、新しいメッセージングプラットフォームが流行するたびに統合を追加する必要がなくなる投資でもある。

Messages APIを補完するものとして、Dispatch APIがあります。このAPIは、意図した受信者にメッセージを届けるというタスクにさらなる信頼性を与えるものです。Dispatch APIを使えば、特定の時間内にメッセージが届かなかった場合にどうするかというルールを設定することができます。そのため、そのユーザーに対して別の連絡方法、たとえば別の電話番号を持っていたり、Facebookで交流があったりする場合は、別の方法で2回目のメッセージを送ることができます。この投稿では、別の電話番号に送信する例を示しています。この機能は、私が旅行中に異なる国で異なる電話番号を使用する際によく望む機能です!

Webhookエンドポイントの設定

をご覧ください。 メッセージとディスパッチページでアプリケーションを作成し、このプロジェクトで使用するウェブフックを設定します:

  • ステータスのURLは [YOUR URL HERE]/status例えばngrokの場合、次のようになる。 https://abcdef1.ngrok.io/status.

  • インバウンドメッセージのURLは [YOUR URL HERE]/inbound例えばngrokの場合、次のようになる。 https://abcdef1.ngrok.io/inbound.

この2つのルートだ、 /status/inboundには好きな名前をつけられますが、ここでは GitHub のサンプルコードと同じものを使います。

ダッシュボード上で、作成したアプリケーションIDをメモし、秘密鍵ファイルも持っていることを確認してください(便利なclick-to-create-a-keyがあり、公開鍵と秘密鍵のペアを生成し、公開鍵をアプリケーションの設定に入れ、秘密鍵をダウンロードしてアプリケーションで使用します)。

コードを予熱する

(パン作りに喩えるのは行き過ぎだろうか? ごめん!)。

動作するアプリケーションのコードはGitHubで公開されている。アクセス https://github.com/nexmo-community/bakery-messaging-with-dispatchにアクセスし、リポジトリをクローンするか、コードをダウンロードしてください。

それを手に入れたら、インストールしなければならない依存関係がいくつかある。できるだけシンプルにするため、このプロジェクトでは スリムマイクロフレームワーク.API 呼び出し (Messaging API と Dispatch API はまだベータ版であるため、私たちの PHP ライブラリではまだサポートされていません)、このプロジェクトでは GuzzleHTTP.

依存関係をインストールするには コンポーザー:

composer install

Messages APIとDispatch APIは、以下のものを使用します。 JSON ウェブトークン (JWT)を使います。ダッシュボードで作成したアプリケーションIDをVonage CLIで使用し、以下のようなコマンドを実行します。 private.key):

vonage jwt --application_id=VONAGE_APPLICATION_ID

このコマンドの出力は、このアプリケーションでのアクセスに使用するJWTです。このJWTは24時間ごとに失効するので、完璧に動作していたアプリケーションが突然 "Invalid token "エラーを返すようになったら、このプロセスを繰り返す必要があるかもしれないので注意してください。

アプリケーションは、JWT、アプリケーションID、そして送信するメッセージの連絡先情報を必要とする。に設定テンプレートがあります。 config.php.sampleこのファイルをコピーして config.phpそして、あなたのプラットフォームに合わせて値を編集してください。必要なのは

  • 再びアプリケーションID。

  • 先ほど生成したJWT。

  • メッセージを送信する電話番号 から.

  • メッセージを送るための2つの電話番号 への.

この後、材料が揃い、素晴らしいものを作り始めることができる!

優れた顧客コミュニケーションを調理する

この時点で準備は完了し、アプリケーションを使用する準備ができました。ウェブルートとして public/ディレクトリをウェブルートとして設定します。私はngrokを使ったローカル開発プラットフォームを使っているので、セットアップコマンドは1つのターミナルで php -S localhost:8080 public/index.phpngrok http 8080にあります。

もしNgrokが新しいURLを教えてくれたら(無料アカウントではURLを予約することはできません)、ダッシュボードに戻ってウェブフックのURLを更新することを忘れないでください。

では、プロジェクトのホームページをロードしてみよう。メッセージを送るためのとてもシンプルなフォームが表示されるはずだ。その前に、このフォームがどのように機能するかを少し見てみましょう。

Messages APIプロセスを理解する

Messages APIを使ったメッセージ送信の流れは次のようになる:

  1. メッセージを書きます!これはホームページにある入力フォームに入ります。

  2. メッセージの発信元電話番号の詳細を送信します。 から送信元の電話番号 宛先そしてメッセージそのものをJSON形式で送信します。詳細は APIドキュメントを参照してください。

  3. 成功したメッセージの応答は、ステータスコード202(「Accepted」)であり、応答のJSONボディの message_uuidフィールドである。

  4. Nexmoからの通信はすべて POSTリクエスト・ウェブフックから /statusを経由します。すべての受信リクエストには、ステータスに関連するメッセージIDとタイムスタンプが含まれます。これはJSON形式です。

  5. ステータスのウェブフックは、メッセージが送信されたことを示します。メッセージのステータスについては メッセージのステータスについてはを参照してください。

  6. もう1つのステータスウェブフックは、メッセージが配信されたこと(配信された場合)とその金額を示す。

ステータスの更新を読むことができることは非常に重要であることは明らかだ。

ステータス・アップデートの処理

メッセージのステータスに関して何か面白いことが起こると、最初にダッシュボードで設定したウェブフックにウェブフックが送られます。このアプリケーションでは /status.以下はそのルートのコードです:

$app->post('/status', function (Request $request, Response $response) {
    error_log($request->getBody());
    print_r($request->getParsedBody());
});

このアプリケーションの例では、多くのことをするわけではありませんが、すべてのレスポンスをキャプチャし、サーバーのログに記録します。また、それらを出力することもできます。これは後で、より高度な機能をデバッグする際に役立ちます。

お客様にメッセージを送る

Screenshot showing a custom message to be sentCupcake Bakery Custom Message

この時点で、どうぞご自由にメッセージを入力してください。私のは "Your cupcakes are ready for collection "と書いてある。送信を押すと、メッセージはすぐに携帯電話に届くはずだ。魔法だったのだろうか?いや、コードを見てみよう。

$app->map(['GET', 'POST'], '/', function (Request $request, Response $response, array $args) {
    $config = $this->get('config');
    $information = [];
    $title = "Cupcake Bakery Customer Messaging";

    if($data = $request->getParsedBody()) {
        $message = $data['message'];
        $client = new \GuzzleHttp\Client(['base_uri' => "https://api.nexmo.com/v0.1/messages"]);

        try {
            $apiResponse = $client->request('POST', '/v0.1/messages', [
                'headers' => [
                    'Authorization' => 'Bearer ' . $config['jwt'],
                    'Content-Type' => 'application/json',
                    'Accept' => 'application/json'
                ],
                'json' => [
                    'from' => $config['from'],
                    'to' => $config['customer1'][0],
                    'message' => [
                        'content' => [
                            'type' => 'text',
                            'text' => $message
                        ]
                    ]
                ]
            ]);

            $information['statusCode'] = $apiResponse->getStatusCode();
            $information['body'] = $apiResponse->getBody();
        } catch (Exception $e) {
            $response = $e->getResponse();
            $responseBodyAsString = $response->getBody()->getContents();
            echo $responseBodyAsString;
            error_log($responseBodyAsString);
        }

    }

    $response = $this->view->render($response, 'index.html', ['information' => $information, 'title' => $title]);
    return $response;
});

このルートは GETPOSTの両方で使用できます。 GETで読み込まれ、フォームが送信されるときに POST.もし POSTデータがある場合、APIリクエストを構築するために以前に設定したコンフィギュレーションとともにメッセージデータが使用されます。レスポンスのステータスコードとボディはキャプチャされ、ページに出力されます。このデバッグ出力を使って、送信したメッセージの message_uuidを取得できます。

この例では Slim フレームワークを使用していますが、コードの大半は Slim 固有のものではなく、どの PHP アプリケーションでも動作します。Slim の詳細については、以下をご覧ください。 https://www.slimframework.com/- 特にお勧めするのは 「最初のアプリケーション」チュートリアル.

メッセージの進捗状況

エンドポイントはすでに /statusエンドポイントはすでにウェブフックを受信するように設定されているので、そこにアクセスして何が起きているかを確認することができます。複数のメッセージを送信した場合、メッセージIDはさらに重要になりますが、この段階では、ステータスの更新がどのメッセージに関連するかは明らかでしょう。

成功したメッセージには、2つのステータスアップデートが表示されます。最初のものは、メッセージが送信されたことを確認するものです:

{
    "message_uuid": "a5587e33-c304-4bf9-85a3-823e379e8a68",
    "to": {
        "number": "447700900001",
        "type": "sms"
    },
    "from": {
        "number": "	447700900000",
        "type": "sms"
    },
    "timestamp": "2018-10-17T10:17:02.889Z",
    "status": "submitted"
}

メッセージが私の携帯電話に届いた後、メッセージ配信に関する情報を示す2回目のステータスアップデートが表示される:

{
    "message_uuid": "a5587e33-c304-4bf9-85a3-823e379e8a68",
    "to": {
        "number": "447700900001",
        "type": "sms"
    },
    "from": {
        "number": "	447700900000",
        "type": "sms"
    },
    "timestamp": "2018-10-17T10:17:05.480Z",
    "status": "delivered",
    "usage": {
        "price": "0.0333",
        "currency": "EUR"
    }
}

Facebook Messengerのような他のメッセージング・チャンネルも、ユーザーが実際にメッセージを見たことを知らせるために「既読」ステータスを返すことができる。

また、メッセージにエラーがある場合は、ステータスの更新を受け取ります。この場合、JSONデータの最上位に errorsフィールドが表示されます。 エラーの詳細コードとエラーの理由を含みます。メッセージ /statusエンドポイントに注目して、Messages API を使ってみてください。

メッセージが届かない場合は、別の連絡先をご利用ください。

メッセージがユーザーに届かなかった場合は、それを検知して、そのユーザーのために保持している他の連絡先情報を試してみてください。この利点は、ユーザーがWhatsAppやFacebookメッセンジャーのアプローチを好むことが多い一方で(そして、これらの方が安価に送信できる)、SMSの方が、データ通信量が不足していたり、電波の届きにくい場所にいたりしても、確実にユーザーに届くということです。開発者としては、メッセージのステータスを検出したり、再試行ロジックを追加したり、多くの異なるメッセージングプラットフォームを扱えるコードを構築したりすることに一生懸命になる必要はない。Dispatch API がすべてやってくれるので、とても簡単なのだ。

ディスパッチ API ドキュメント Dispatch API ドキュメントをご覧ください。を参照してください。

このアプリケーションの例では、別のSMS番号を使用しています(旅行中、ある電話パッケージが別の場所よりもうまく機能する場合に便利だと感じることがよくあります)が、ここに示したtry-another-SMS-exampleとまったく同じ方法で、複数の「from」詳細を設定し、ユーザーに対して任意の数の異なる連絡方法をサポートすることができます。

Dispatch APIをコントロールする

このレベルを追加するには、Messages APIの上にDispatch APIを使います。サンプル・アプリケーションのウェブ・インターフェイスにある "Send message with fallback "リンクの後ろにある /message-with-dispatchこのアクションは、サンプル・アプリケーションのウェブ・インターフェイスにある "Send message with fallback" リンクの後ろにあります。コードはあまり変わりませんが、送信するリクエストに若干の違いがあります:

    $apiResponse = $client->request('POST', '/v0.1/dispatch', [
        'headers' => [
            'Authorization' => 'Bearer ' . $config['jwt'],
            'Content-Type' => 'application/json',
            'Accept' => 'application/json'
        ],
        'json' => [
            'template' => 'failover',
            'workflow' => [
                [
                    'from' => $config['from'],
                    'to' => $config['customer1'][0],
                    'message' => [
                        'content' => [
                            'type' => 'text',
                            'text' => $message
                        ]
                    ],
                    'failover' => [
                        'expiry_time' => 15, // in seconds, 15 is the minimum
                        'condition_status' => 'delivered'
                    ]
                ],
                [
                    'from' => $config['from'],
                    'to' => $config['customer1'][1],
                    'message' => [
                        'content' => [
                            'type' => 'text',
                            'text' => 'Message retry. ' . $message
                        ]
                    ]
                ]
            ]
        ]
    ]);

構造が変わり templateを指定します。 workflowを指定するようになりました。この例では failoverテンプレート(現在唯一のオプション)を使って、SMSが15秒以内に届かなかった場合(あくまでデモです。どのくらい待ちますか?)、その顧客用に持っている別の番号に別のメッセージを送るようにしています。

派遣状況アップデートをフォローする

Messages APIとまったく同じように、Dispatch APIは単にステータスコード 202 Accepteddispatch_uuidを返すだけなので、このAPIリクエストに関連するイベントを結びつけることができる。

先のMessages APIを使った例のように、メッセージが送信されたときだけでなく、メッセージが配送/既読になったときや、Dispatchの状態が変化したときにも更新を受け取ります。以下は、Dispatch API が最初の電話番号に配信できず、2番目の電話番号にフォールバックしたときの一連のデータです。

まず第一に、最初の番号に最初のメッセージを送る。

{
    "message_uuid": "afb5f546-97e7-44ba-97cd-bb7706a93f4e",
    "to": {
        "number": "447700900001",
        "type": "sms"
    },
    "from": {
        "number": "	447700900000",
        "type": "sms"
    },
    "timestamp": "2018-10-19T11:33:07.118Z",
    "status": "submitted",
    "_links": {
        "dispatch": {
            "href": "v0.1/dispatch/de8d9eaf-8d10-407f-840b-53473f26c173",
            "dispatch_uuid": "de8d9eaf-8d10-407f-840b-53473f26c173"
        }
    }
}

1台目」の電話を機内モードにしてテストする)配信できない場合、まったく同じステータスが再び届くが、データには「2台目」の電話番号が含まれている:

{
    "message_uuid": "e083fc2e-dffc-42c9-a7b3-446ee5fe67ba",
    "to": {
        "number": "447700900002",
        "type": "sms"
    },
    "from": {
        "number": "	447700900000",
        "type": "sms"
    },
    "timestamp": "2018-10-19T11:33:25.071Z",
    "status": "submitted",
    "_links": {
        "dispatch": {
            "href": "v0.1/dispatch/de8d9eaf-8d10-407f-840b-53473f26c173",
            "dispatch_uuid": "de8d9eaf-8d10-407f-840b-53473f26c173"
        }
    }
}

つ目のメッセージは届いた!

{
    "message_uuid": "e083fc2e-dffc-42c9-a7b3-446ee5fe67ba",
    "to": {
        "number": "447700900002",
        "type": "sms"
    },
    "from": {
        "number": "	447700900000",
        "type": "sms"
    },
    "timestamp": "2018-10-19T11:33:27.385Z",
    "status": "delivered",
    "usage": {
        "price": "0.0333",
        "currency": "EUR"
    },
    "_links": {
        "dispatch": {
            "href": "v0.1/dispatch/de8d9eaf-8d10-407f-840b-53473f26c173",
            "dispatch_uuid": "de8d9eaf-8d10-407f-840b-53473f26c173"
        }
    }
}

最初のメッセージも後の時点で配信された場合、非常に似たようなステータスアップデートが表示されるので、それも貼り付けません。いつもは10分後くらいに携帯が機内モードになっていることに気づいたときに届くんだけど.

SMSの配信がDispatchリクエストの正常終了を意味するこのようなステータスの場合、受信するWebhookはどちらかの順番で到着する可能性があるので、どちらが先に到着するかに注意しましょう。

2つ目のメッセージの配達に成功すれば、Dispatchが成功したことになるので、そのための "completed "ステータスの更新もある:

{
    "template": "failover",
    "status": "completed",
    "timestamp": "2018-10-19T11:33:27.450Z",
    "usage": {
        "price": "0.0353",
        "currency": "EUR"
    },
    "dispatch_uuid": "de8d9eaf-8d10-407f-840b-53473f26c173",
    "_links": {
        "messages": [
            {
                "message_uuid": "afb5f546-97e7-44ba-97cd-bb7706a93f4e",
                "href": "v0.1/messages/afb5f546-97e7-44ba-97cd-bb7706a93f4e",
                "channel": "sms",
                "status": "submitted"
            },
            {
                "message_uuid": "e083fc2e-dffc-42c9-a7b3-446ee5fe67ba",
                "href": "v0.1/messages/e083fc2e-dffc-42c9-a7b3-446ee5fe67ba",
                "channel": "sms",
                "usage": {
                    "price": "0.0333",
                    "currency": "EUR"
                },
                "status": "delivered"
            }
        ]
    }
}

メッセージの配信には時間がかかることがあるので、これらの非同期更新はAPIとやりとりするための重要な方法である。この例では /statusこれは、これらのAPIを扱うすべての開発者にお勧めしたいことだ。

マルチチャネル、弾力性のあるメッセージング

このチュートリアルでは、単純な SMS API を使って顧客にメッセージを送信するアプリケーションを扱いました。 fromtoデータを送信するだけです)。また、メッセージが顧客に届かなかったことを検出し、別のチャネルを使って顧客に連絡することで、弾力性を持たせる方法も見てきました。

次はどこだ?

これらのAPIをもっと活用したいとお考えなら、次に訪れてみたい場所をいくつかご紹介しよう:

シェア:

https://a.storyblok.com/f/270183/250x250/e3d3b71060/lornajane.png
Lorna Mitchellヴォネージの卒業生

ローナはブログ癖のあるソフトウェア・エンジニアだ。彼女は言葉とコードを同等に扱おうとしている。