Facebook Messenger Botを作る

Fuel PHPでFacebook Messenger Botを作ろうと思ったら、ハマったところがあったのでまとめました。
他のサイトにも書いてあることははしょった部分もあります。
[公式リファレンス](https://developers.facebook.com/docs/messenger-platform/getting-started)の「Facebookアプリの設定」までとても参考になります。(こちらはNode.jsです)
コンソールのUI変わってたりするので、そこは雰囲気で…。



#準備
- Facebookアカウントを用意
 - 登録してすぐ開発を始めようと思ったらアカウント停止されたので注意
- ページというものが必要になるので作る 
- [Facebook for Developers](https://developers.facebook.com)に登録


#Webhookの設定

最初に、URLの認証がありますがこのような形で飛んで来ます。

```json
{
  "hub_mode":"subscribe"
  "hub_verify_token":<YOUR_VERIFY_TOKEN>,
  "hub_challenge":123456
}
```

それに対して、

- ステータスコード200
- bodyはhub_challenge

になるようなコードを書いてあげます。
(\<YOUR_VERIFY_TOKEN>は任意に決められます。)

```php:webhook.php
class Facebook extends Controller_Base
 {
  private $token = '<YOUR_VERIFY_TOKEN>'; //URL認証の際に必要
  protected $format = 'json';

  public function get_webhook()
  {
    $req = Input::get(); //jsonを取得

    if ($req['hub_verify_token'] == $token) { 
      //hub_verify_tokenと一致してたらhub_challengeを返す
      $res = $req['hub_challenge'];
    } else {
      $res = 'error';
      Log::error("verify_token is wrong.");
    }
    // 200を返す。
    return $this->response(json_decode($res),200);//json_decodeしないとはじかれた。
  }
```

ここでテスト

```
curl -X GET "your_url/webhook?hub.verify_token=<自分の認証トークン>&hub.challenge=CHALLENGE_ACCEPTED&hub.mode=subscribe"
```
これで"CHALLENGE_ACCEPTED"が返って来たら成功です。


#アプリの設定
ここで、Facebook for Developersコンソールに移動して、アプリを作成。
アプリが作成できたら左の「プロダクト」から「Messanger」を追加。

そこから「設定」を開き、Webhooksの項目に移動する。

コールバックURLに先ほどのプログラムをあげた場所のURL、(**httpsじゃないとはじかれるので注意**)
トークンにはプログラム中に書いた\<YOUR_VERIFY_TOKEN>を入れます。

「確認して保存」を押して、エラーが出なければOK!
<img width="724" alt="スクリーンショット 2019-09-19 16.01.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419023/30b99f5a-d437-3b41-3c65-7cfffd41f98d.png">


続いて、同じくWebhooksの項目の「ページを追加または削除」から、このアプリに紐付けるページを追加。
そのあと、ページが追加された右端の「サブスクリプションを追加」から、サブスクリプションを追加します。(とりあえずこの４つはマストらしい)
<img width="718" alt="スクリーンショット 2019-09-19 16.03.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419023/dd68e764-21d7-80a5-6f56-33cd0c34989a.png">


最後にアクセストークンの項目に行き、ページを追加して、アクセストークンはメモします。

これで設定は完了。


#botを動かしてみる

では先ほどのプログラムにpostでリクエストが来た場合のコードを足してあげる。
これはおうむ返しをするサンプルコード。

```php:webhook.php
public function post_webhook()
  {
    $req = Input::get();

    if(isset($req['object'])) {

      foreach ($req['entry'] as $entry) {
        $webhook_event = $entry['messaging'];
        foreach ($webhook_event as $messaging) {
          //受信内容
          $id = $messaging['sender']['id'];
          $text = $messaging['message']['text'];
          
          $curl = Request::forge('https://graph.facebook.com/v4.0/me/messages','curl');
          $curl->set_method('post');
          $curl->set_params(array(
                   'access_token' => '<YOUR_ACCESS_TOKEN>',//さっきメモしたもの
                   'recipient' => array("id" => $id),
                   'message' => array("text" => $text)));
          
          $curl->execute();      
　　　  }
     }
   }    
  }
```

これで、紐付けたページのMessanger(アカウントに直接送るのとは違う)に送れば動く！

…と思いきや動かない！！！

なぜかというと、今は開発モードになっているため役割を持つユーザーの情報しか取れないようになっている。(公開するには審査が必要)


#役割の設定
コンソールの左にある「役割」から、「役割」を選ぶ。
「テスターを追加」から、テストさせたいユーザーを追加します。(友達だと名前を途中まで打つと出てくる。）
そうすると、申請が送られるので、テストユーザーのDevelopersコンソールに入って、申請を承認(右上アイコンのところに通知がくるはず)

そのテスターが、ページにメッセージを送れば、動くはず。

##注意
Webhookが飛んで来たときサーバーが500エラーを返してしまうと、20分おきくらいで再度リクエストを送ってくる。
逆に言えば、20分後でないと、どんなにコードを変えて、メッセージを追加で送ってもbotが反応しなくなってしまう。
デバッグにはとても不便だったので、追記。
何かご存知の方がいたら教えてください。


#参考
https://developers.facebook.com/docs/messenger-platform
https://tech.bita.jp/article/16