Contents
アプリ作成と必須権限の取得
| 手順 | 内容 |
|---|---|
| 1️⃣ | Meta for Developers にログイン → 左メニュー 「マイアプリ」 → Create App。 |
| 2️⃣ | アプリタイプは Business(Messenger ボットで必須)。名前・連絡先メールを入力し作成。 |
| 3️⃣ | ダッシュボードの 設定 › 基本 にある App ID / App Secret を控える(後述の環境変数で使用)。 |
| 4️⃣ | 左メニュー 権限と機能 → + 権限を追加。取得すべき主要権限は次の通りです。 |
必要な権限
| 権限 | 用途・備考 |
|---|---|
pages_messaging |
ページ側とのメッセージ送受信(必須)。 |
pages_manage_metadata |
Webhook のサブスクリプションやページ情報取得に必要。 |
pages_read_engagement |
ページの基本情報・インサイト取得用。 |
pages_show_list (オプション) |
複数ページを扱う場合に一覧取得が可能。 |
重要:権限申請画面では「利用シナリオ」と「データ保持期間」の記載が必須です(2025 年版 Meta Platform Policy 参照)。
参考: https://developers.facebook.com/docs/messenger-platform/app-review/
Facebook ページ側での接続設定
- ページ管理者 アカウントで対象ページにログイン。
- 左サイドメニュー → 設定 › 高度なメッセージング を選択。
- Connected Apps セクションで アプリを接続 ボタンをクリック。
- ポップアップに App ID(「設定 › 基本」から取得)を入力し 接続。
接続が成功すると、一覧に自アプリが表示され 権限付与状況 が “有効” になることを確認してください。
Page Access Token の取得・管理 (2024‑10 以降)
トークンの有効期限について
Meta の公式ドキュメント(2024年11月時点)では、Page Access Token は「長期トークン」=有効期間 60 日 と記載されています。
Reference: https://developers.facebook.com/docs/messenger-platform/reference/access-token/#long-lived
したがって 「60日 → 無期限」への変更は確認できていません。実装時には次の点を意識してください。
| 項目 | 推奨対応 |
|---|---|
| 有効期間 | 60 日(自動更新なし)→ 必要に応じて再取得スクリプトを用意。 |
| 保存場所 | .env、AWS Secrets Manager、GCP Secret Manager 等の 環境変数・シークレットストア に保管し、コード内にハードコーディングしない。 |
| デバッグ | debug_token エンドポイントで expires_at が null でなければ有効期限が残っていることを確認できる。 |
Python での取得サンプル
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# token_utils.py import os, requests, logging from urllib.parse import urlencode log = logging.getLogger(__name__) APP_ID = os.getenv("FB_APP_ID") APP_SECRET = os.getenv("FB_APP_SECRET") PAGE_ID = os.getenv("FB_PAGE_ID") def _app_access_token() -> str: """アプリアクセストークン(client_credentials)を取得""" params = { "client_id": APP_ID, "client_secret": APP_SECRET, "grant_type": "client_credentials", } r = requests.get( f"https://graph.facebook.com/oauth/access_token?{urlencode(params)}" ) r.raise_for_status() return r.json()["access_token"] def get_page_access_token() -> str: """Page Access Token(長期)を取得""" app_token = _app_access_token() url = f"https://graph.facebook.com/{PAGE_ID}" params = { "fields": "access_token", "access_token": app_token, } r = requests.get(url, params=params) r.raise_for_status() token = r.json()["access_token"] log.info("Page Access Token 取得成功") return token |
有効期限の確認(オプション)
|
1 2 |
curl -X GET "https://graph.facebook.com/debug_token?input_token={PAGE_ACCESS_TOKEN}&access_token={APP_ID}|{APP_SECRET}" |
data.expires_atがnull→ 無期限(現時点では存在しません)- 数値が返ってくる → UNIX タイムスタンプで 60 日以内か確認
Webhook エンドポイント実装と署名検証 (Flask)
基本構成
| 機能 | 実装ポイント |
|---|---|
| GET(Verification) | hub.mode=subscribe と hub.verify_token が一致すれば hub.challenge を返す。 |
| POST(イベント受信) | 受信した JSON をパースし、messaging 配列から送信者 ID とメッセージ本文を抽出。 |
| 署名検証 | 本番環境では必ず X-Hub-Signature-256(HMAC‑SHA256)または X-Hub-Signature(HMAC‑SHA1)を APP_SECRET と比較する。 |
完全実装例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# app.py import os, hmac, hashlib, logging from flask import Flask, request, abort, jsonify app = Flask(__name__) log = logging.getLogger(__name__) VERIFY_TOKEN = os.getenv("FB_VERIFY_TOKEN") # 任意の文字列(Meta に設定したもの) APP_SECRET = os.getenv("FB_APP_SECRET").encode() # バイト列に変換 def verify_signature(req) -> bool: """X-Hub-Signature-256 が正しいか検証""" signature = req.headers.get("X-Hub-Signature-256") if not signature: return False sha_name, sig_hash = signature.split("=") if sha_name != "sha256": return False mac = hmac.new(APP_SECRET, msg=req.data, digestmod=hashlib.sha256) return hmac.compare_digest(mac.hexdigest(), sig_hash) @app.route("/webhook", methods=["GET"]) def webhook_verify(): mode = request.args.get("hub.mode") token = request.args.get("hub.verify_token") challenge = request.args.get("hub.challenge") if mode == "subscribe" and token == VERIFY_TOKEN: return challenge, 200 abort(403) @app.route("/webhook", methods=["POST"]) def webhook_receive(): # ---- 署名検証(本番必須)---- if not verify_signature(request): log.warning("Invalid X-Hub-Signature") abort(403) payload = request.get_json() for entry in payload.get("entry", []): for event in entry.get("messaging", []): sender_id = event["sender"]["id"] # メッセージが送られてきた場合のみ処理 if "message" in event and (msg := event["message"].get("text")): handle_message(sender_id, msg) return "EVENT_RECEIVED", 200 # ----------------------------------------------------------------- def handle_message(sender_id: str, text: str): """シンプルなエコーボット""" reply = f"受信しました: {text}" send_message(sender_id, reply) def send_message(recipient_id: str, message: str): import requests access_token = os.getenv("FB_PAGE_ACCESS_TOKEN") url = "https://graph.facebook.com/v17.0/me/messages" params = {"access_token": access_token} headers = {"Content-Type": "application/json"} data = { "recipient": {"id": recipient_id}, "message": {"text": message}, } r = requests.post(url, params=params, headers=headers, json=data) if not r.ok: app.logger.error(f"Message send error: {r.text}") # ----------------------------------------------------------------- if __name__ == "__main__": # デバッグ時は ngrok 等で HTTPS 化し、Meta ダッシュボードに URL を登録 app.run(host="0.0.0.0", port=5000, debug=False) |
ポイント
verify_signatureは必ず本番環境で有効化してください。テスト時はコメントアウトしても構いませんが、コードレビューで除外しないように注意。
署名検証の詳細は公式ドキュメント(Signature Verification)を参照。
メッセージ送受信サンプル
| 手段 | コマンド例 |
|---|---|
| cURL (手軽にテスト) | bash<br>curl -X POST "https://graph.facebook.com/v17.0/me/messages?access_token=$PAGE_ACCESS_TOKEN" \<br>-H "Content-Type: application/json" \<br>-d '{"recipient":{"id":"USER_PSID"},"message":{"text":"Hello from Flask bot!"}}' |
Python SDK (facebook-sdk) |
python<br>from facebook import GraphAPI<br>import os<br>graph = GraphAPI(access_token=os.getenv("FB_PAGE_ACCESS_TOKEN"))<br>resp = graph.put_object(parent_object='me', connection_name='messages', recipient={'id':'USER_PSID'}, message={'text':'Hello from SDK!'})<br>print(resp) |
Node.js (facebook-nodejs-business-sdk) |
javascript<br>const bizSdk = require('facebook-nodejs-business-sdk');<br>const Page = bizSdk.Page;<br>bizSdk.FacebookAdsApi.init(process.env.FB_PAGE_ACCESS_TOKEN);<br>const page = new Page(process.env.FB_PAGE_ID);\npage.sendMessage({recipient:{id:'USER_PSID'},message:{text:'Hello from Node SDK!'}})\n .then(r=>console.log(r))\n .catch(e=>console.error(e)); |
テスト環境の構築手順
- テストユーザー作成
- Meta Business Manager → 設定 → 「テストアカウント」→ 新規作成。
- テストページ作成
- 同じく Business Manager → ページ → 「Create Test Page」。
- テストユーザーをテストページの管理者に追加し、Messenger アプリでログイン。
USER_PSID(PSID)は Webhook が受信したイベントから取得できます。
ベストプラクティス:テスト用トークン・PSID は本番環境のログやデータベースに永続保存しないこと。テストが終了したら速やかに削除してください。
エラーコードと対処法
| エラーコード | 代表的なシナリオ | 主な原因 | 推奨対策 |
|---|---|---|---|
| 100 | Invalid parameter |
必須パラメータが欠如、JSON 構造不正 | JSON Linter で事前検証。公式エラーフィールド error.user_msg をログに残す |
| 190 | Invalid OAuth access token |
トークン期限切れ・無効化 | 新しい Page Access Token を再取得し、シークレットストアを更新 |
| 10 | Permission denied |
必要権限が未承認、またはページに接続されていない | 権限ステータスを Dashboard → App Review で確認。Connected Apps に正しく接続されたか再チェック |
| 200 | Too many calls (レートリミット) |
短時間に多数 API 呼び出し | エクスポネンシャルバックオフ実装、またはバッチ処理へ切り替え |
2025 年版 Meta ガイドラインに沿ったプライバシー・データ保持要件
Meta Platform Policy(2025 年改訂版)は 「最小限のデータ収集」 と 「明示的な同意」 を強く求めています。以下は実装時に必ず満たすべき項目と、公式根拠です。
| 項目 | 具体要件 | 公式根拠 |
|---|---|---|
| プライバシーポリシーの公開 | アプリ内・Web 上に URL を掲載し、メッセンジャーデータの利用目的・保持期間を明示。 | https://developers.facebook.com/policy/#privacy |
| データ保持期間 | メッセージ本文は 90 日以内に自動削除 するか、ユーザーから削除要求があったら即時消去。 | 同上(Data Retention) |
| ユーザー同意取得 | 初回メッセージ送信前に「本ボットは ○○ 用にデータを利用します」旨のテキストと 同意ボタン を表示し、postback イベントで同意状態を保存。 |
https://developers.facebook.com/docs/messenger-platform/policy/ |
| 最小限データ収集 | 必要なフィールドは id(PSID) と message.text のみ。他のプロフィール情報は取得しない。 |
同上(Data Use) |
| データ削除リクエスト対応 | ユーザーから「メッセージを削除」依頼があったら、即座に DB もしくはキャッシュから該当レコードを削除し、成功レスポンスを返す。 | 同上(User Data Deletion) |
実装ヒント
- 環境変数FB_PRIVACY_POLICY_URLを用意し、審査時のコメント欄に自動埋め込みできるようにすると便利です。
- データ削除は非同期キュー(例: AWS SQS)で処理し、タイムアウトを防止。
審査申請のベストプラクティス
- App Review ページへ移動 →
pages_messaging権限の「Request」ボタンをクリック。 -
必要情報として以下を必ず添付:
-
スクリーンショット(Connected Apps 画面、Webhook 検証成功画面)
- フロー図(ユーザーがメッセージ送信 → 同意取得 → データ保存・削除 の流れ)
-
テスト用 Facebook アカウント(審査担当者が実際に操作できるよう、テスター権限を付与したアカウント)
-
コメント欄に プライバシーポリシー URL と データ保持ポリシー概要 を記載。
- 提出後は Meta のレビュー担当からの質問に 24 時間以内 で回答し、必要なら UI/UX を微調整。
合格率を上げるコツ
| コツ | 内容 |
|---|---|
| 画面遷移は 2〜3 ステップ に抑える | ユーザーが迷わないようにし、同意ボタンは目立つ色で配置。 |
| エラーログの可視化 | error.user_msg とスタックトレースを CloudWatch / Stackdriver に送信し、審査時に「エラー対策が実装済み」ことを示す。 |
| テストユーザー情報は削除 | PSID やアクセストークンを本番ログに残さない。 |
| レートリミット対策 | 1 分間あたりの呼び出し回数上限に達した場合はバックオフ実装を示すコード例を添付。 |
まとめ
- 権限取得 → 必要な
pages_*系権限を申請し、利用シナリオとデータ保持期間を明記 - ページ接続 → Connected Apps に自アプリを紐付けるだけで API 呼び出しが有効化
- トークン管理 → 現時点(2024‑11)では 60 日の長期トークン。無期限への変更は未確認なので、定期取得スクリプトを用意
- Webhook → GET 検証に加えて、必ず HMAC 署名検証を本番実装に組み込む
- プライバシー遵守 → 2025 年版ガイドラインに沿ったポリシー公開・データ保持・同意取得を徹底
- 審査対策 → スクリーンショット、フロー図、テストアカウントを忘れずに添付し、エラーログやレートリミット対策も示す
以上の手順とベストプラクティスに沿って実装すれば、Meta の審査通過率が向上し、安全かつスケーラブルな Messenger ボットを本番環境へデプロイできます。