見出し画像

WeChatシステムから送られて来るイベントへ応答する

WeChat公式アカウントの管理画面でイベント受信の設定をしておくと、フォロワーが公式アカウントに対して何かアクションを起こす度にイベントが飛んで来ます。このイベントに応答する事でフォロワーと会話したりフォローされた際のウェルカムメッセージを送る事が出来ます。
イベント受信の設定についてはこちらをご参照ください。

応答出来るイベントと主な用途

WeChatシステムからは色々なイベントが飛んで来ますが、応答出来るイベントは以下の4種類です。

  • フォローイベント
    このイベントに応答する事でフォローしてくれたユーザーに対してウェルカムメッセージを送る事が出来ます。公式アカウントで提供しているサービスの説明などを添えるとフォロワーのエンゲージメントアップに繋がるでしょう。
    なお、フォローしたユーザーがトラッキングコード付きのQRコードから流入していた場合、このイベントにトラッキングコードが付与されて来るので、流入元分析用にトラッキングコードを記録する事も出来ます。

  • 会話イベント
    このイベントにはフォロワーが公式アカウントに対して送信して来た「テキスト」「画像」「音声」「ビデオ」「ショートビデオ」「位置情報」「リンク」の内容が含まれています。
    キーワードに反応してテキストや画像を返信する簡単な自動応答から、AIでユーザーと会話するようなボットまで色々応用出来るイベントです。
    ちなみにWeChatオフィシャルアカウントプラットフォームの管理画面で「语音识别」(音声認識)機能を有効化している場合は「音声」のデータにはその音声をテンセントの音声認識エンジンでテキスト化したデータも含まれます。(音声認識を有効にする方法はこの記事の最後で紹介します)

  • QRコードスキャンイベント
    このイベントにはQRコードに埋め込まれたトラッキングコードが含まれています。ただし、このイベントは既にフォロワーとなっているユーザーがトラッキングコード付きのQRをスキャンして公式アカウントへ入って来た場合のみに発生する事に注意しましょう。
    まだフォローしていないユーザーがトラッキングコード付きのQRコードをスキャンしてもこのイベントは発生しません。フォローしていないユーザーがトラッキングコード付きのQRコードをスキャンして新たにフォローした場合は「フォローイベント」のみが発生し、トラッキングコードも「フォローイベント」の方に追加されます。
    各広告媒体に設定したトラッキングコードを既存のフォロワーがどれだけスキャンしているかを調べる事が主な用途だと思います。既にフォローしてくれている人にフォロワー獲得の為の広告を見てもらっても意味がありませんので、媒体ごとに新規フォロワー獲得数と既存フォロワーのスキャン数を比較する事でコンバージョンの効率を見る事が出来ます。
    ただこのイベントに公式アカウントから応答を返す事が出来る事を利用して、スタンプラリーのようなちょっとしたゲームに応用する事が出来ると思います。(実際に実装した事は今までありませんが…)
    例えば、各チェックポイントにトラッキングコード付きのQRコードを掲示し、スキャンされたらそのユーザーがスキャンしたチェックポイントを記録しておき、そのチェックポイントの周辺情報やまだスキャンしていないチェックポイントの情報を返信します。そうやってユーザーにイベント会場や観光地内を巡回させ、全部のチェックポイントでスキャンを完了したユーザーに記念品をプレゼントする、といった応用は出来ると思います。

  • メニュークリックイベント
    公式アカウントのメニューがクリックされた時に送られて来るイベントですが、APIを通じて公式アカウントのメニューを設定する際に指定する「type」の種類によって応答出来るものと出来ないものがあります。応答する事が許されている「type」は以下の2つのみです。

    • click
      このタイプのメニューがクリックされると「CLICK」イベントが送られて来ます。このイベントにはメニュー設定の際に指定しておいた「key」の値が含まれているので、イベントを処理するプログラムはこの値を見てどのメニューが押されたのかを判断します。カスタマーサポートのチャットボットを起動するトリガーとして利用したり、何かの案内図の画像を応答したりする利用方法が一般的です。

    • scancode_waitmsg
      このタイプのメニューがクリックされるとバーコードやQRコードをスキャンする為にWeChatクライアントがカメラを起動します。ユーザーがそのカメラでスキャン可能なコードをスキャンすると、スキャン結果がイベントとして送られて来ます。処理するプログラムはその結果に基づき処理をして、その処理結果を応答します。
      例えば小売店などでお客様に商品についているバーコードをスキャンしてもらい、JANコードから商品情報やキャンペーン情報を検索して返信したりする事が出来ます。ECサイトやECミニプログラムを運営している会社であれば、ユーザーの手元にある商品が自社のECサイトやECミニプログラム上で買えるかどうか、買えるとしたらいくらで買えるのかなどの情報を返信して、そのままECの商品ページへ遷移出来るリンクを返す事も出来るでしょう。

イベントへ応答する方法

イベントに対する応答で送信出来るコンテンツは「テキスト」「画像」「音声」「ビデオ」「音楽」「複合テキスト」の6種類です。このうち「テキスト」と「複合テキスト」以外のコンテンツは事前に登録したもの(メディアIDが割り当てられているもの)しか送信出来ません。
コンテンツは以下のような形式のXMLで応答します。

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[fromUser]]></FromUserName>
  <CreateTime>12345678</CreateTime>
  <MsgType><![CDATA[text]]></MsgType>
  <Content><![CDATA[フォローありがとうございます!]]></Content>
</xml>

XMLを構成する各要素の意味は以下の通りです。

  • ToUserName
    メッセージを送信する相手のOpenID。受信したイベントXMLにある「FromUserName」と一致している必要があります。

  • FromUserName
    メッセージ送信元のAppID。自分のAppIDだけが指定可能です。

  • CreateTime
    メッセージ生成時間。整数のUnix時間で指定します。

  • MsgType
    返信するコンテンツの種類。「テキスト」は「text」、「画像」は「image」、「音声」は「voice」、「ビデオ」は「video」、「音楽」は「music」、「複合テキスト」は「news」で固定です。

  • Content
    コンテンツの内容です。「テキスト」の場合は「Content」ですが、ほかの種類のコンテンツの場合はそれぞれ要素名が異なります。

ToUserName」と「FromUserName」がイベントデータのXMLとは正反対になるので注意しましょう。また、イベントデータを受信してから5秒以内に応答する必要があります。5秒を過ぎるとユーザーには「This Official Account is temporarily unavailable.Try again later.」というメッセージが表示されて応答は終了してしまいます。(5秒以上経過後にXMLデータを返送しても無視されます)
イベントへの応答の詳細についてはこちらの公式ドキュメントをご参照ください。
例えばフォローしてくれたユーザーに「フォローありがとうございます!」というメッセージを返す受信プログラムをPHPで書くならこうなります。
※「消息加解密方式」が「明文模式」か「兼容模式」の場合の例です

<?php
// 管理画面で設定したToken
$token = 'XXXXXXX';
if($_GET['echostr'] != ""){ // echostrがあるので確認リクエスト
   // シグネチャのチェック
   // GETで送られて来たtimestamp、nonceと管理画面で設定したTokenをアルファベット順に
   // 並び替えてから連結してSHA1でハッシュ化する
   $arr = array($_GET['timestamp'],$_GET['nonce'],$token);
   sort($arr, SORT_STRING);
   $sig_check = sha1($arr[0] . $arr[1] . $arr[2]);

   if($sig_check == $_GET['signature']){ // シグネチャが正しければ「echostr」を応答
      echo $_GET['echostr'];
   }
   // echostrがあるリクエストはイベント通知ではないので処理を終了
   exit();
}else{ // echostrがないのでイベント通知である
   // POSTされて来たデータを読み込んでXMLとして解釈する
   $postdata = file_get_contents("php://input");
   $xml = simplexml_load_string($postdata);

   if($xml !== false){ // POSTデータがXMLとして解釈出来た
      // XMLから応答に必要な情報を取得する
      $openid = $xml->FromUserName; // イベント送信者(ユーザーのOpenID)
      $appid = $xml->ToUserName; // イベント受信者(公式アカウントのAppID)
      $event = $xml->Event; // イベントの種類

      if($event == "subscribe"){ // イベントが「フォロー」だった
         $create_time = time();
         // 応答するメッセージをXML形式で生成(返信なので送信者と受信者が入れ替わっている事に注意)
         $message = <<<EOM
<xml>
  <ToUserName><![CDATA[{$openid}]]></ToUserName>
  <FromUserName><![CDATA[{$appid}]]></FromUserName>
  <CreateTime>{$create_time}</CreateTime>
  <MsgType><![CDATA[text]]></MsgType>
  <Content><![CDATA[フォローありがとうございます!]]></Content>
</xml>
EOM;
         // メッセージを送信
         echo $message;
      }else{ // フォロー以外のイベントだった
         // 応答しない場合は「success」を返しておく。必須ではないがWeChatシステムに
         // イベント受信プログラムが正常に稼働している事を知らせる為に送っておいた方が良い
         echo "success";
      }
   }
}

イベント受信のURLは1つしか設定出来ないので、初期設定時の確認リクエストを含めた全てのリクエストを1つのプログラムで受信する必要があります。その為、冒頭では必ず「echostr」の有無をチェックして確認リクエストであるかを確認しましょう。
このプログラムでは応答しない場合は「success」というテキストのみを出力しています。これは必須ではありませんが、テンセントの公式ドキュメントでは「success」を返す事を推奨しています。

1、直接回复success(推荐方式) 2、直接回复空串(指字节长度为0的空字符串,而不是XML结构体中content字段的内容为空)

テンセントの公式ドキュメント

XMLデータの暗号化

イベント受信の設定をした際に「消息加解密方式」を「安全模式」に設定している場合は応答を暗号化する必要があります。暗号化の手順は以下の通りです。

  1. 応答用のXMLデータを生成する

  2. 16文字の半角英数字で構成されるランダムな文字列を生成する

  3. 手順1で生成したXMLデータのデータサイズ(整数)を32 ビットのビッグエンディアンバイトオーダーでバイナリ文字列にpackする

  4. 手順2で生成したランダム文字列、手順3で生成したバイナリ文字列、手順1で生成したXML、自分のAppIDの順で連結した文字列を生成する

  5. 手順4で生成した文字列をブロックサイズ32バイトとしてPKCS#7でパディングする(16バイトではない理由はこちら

  6. 管理画面で設定したEncodingAESKeyの末尾に「=」を追加したうえでBase64でデコードして共通鍵を得る

  7. 16バイトの初期ベクトル(ランダムでOK)を用意し、手順6の共通鍵を使って手順5でパディング済みのデータをAES-256-CBCで暗号化する

  8. イベント通知で送られて来た「nonce」と「timestamp」、管理画面で設定した「Token」、そして手順7で生成した暗号化したデータをアルファベット順に並べ替えたうえで連結してSHA1でハッシュ化する

  9. 以下のXMLフォーマットに格納して出力する

<xml>
  <Encrypt><![CDATA[手順7で暗号化したデータ]]></Encrypt>
  <MsgSignature><![CDATA[手順8で生成したハッシュ]]></MsgSignature>
  <TimeStamp>イベント通知で送られて来たtimestamp</TimeStamp>
  <Nonce><![CDATA[イベント通知で送られて来たnonce]]></Nonce>
</xml>

(付録)音声認識機能を有効にする

会話イベントでユーザーが音声を送って来た場合にその音声を音声認識してテキスト化する機能があります。その機能を有効にするには、公式アカウントでWeChatオフィシャルアカウントプラットフォームにログインして、左にあるメニューで「接口权限」をクリックします。右側にAPIの一覧が表示され、今ログインしている公式アカウントで利用可能かどうかを調べる事が出来ます。
その中に「接收语音识别结果」がありますが、デフォルトでは無効(「已关闭」)になっていますので、右にある「开启」をクリックして有効化しましょう。

音声認識の設定

有効化すると、会話イベントでユーザーが音声を送って来た時のXMLデータに「Recognition」という要素が追加されます。これが音声認識をした結果のテキストです。なお、対応言語は中国語の普通話のみとなります。

この記事が気に入ったらサポートをしてみませんか?