👌

WhatsAppにメッセージを送るプログラムを書いてみた

2023/08/05に公開
1

はじめに

前回Telegramでやった内容のWhatsApp版です。

WhatsAppとは

いわゆるメッセンジャーアプリです。
メッセンジャーアプリといえば日本ではLINEが有名ですが、
世界的に見るとWhatsAppが一番使われていたりします。
他にはTelegramやWeChat、Facebook Messengerなども有名ですね。
ちなみにWhatsAppを提供している会社はMeta社

日本

全世界

ロシア

改めて見るとWhatsAppが圧倒的なのがわかると思います。
Wikipediaによると、全世界の月間アクティブユーザ数が2020年で20億人を超えているそうです。

https://www.whatsapp.com/?lang=ja_JP

WhatsAppにメッセージを送るためにはどうするか

WhatsAppのクラウドAPIを用いることでWhatsAppに対して様々な操作を送ることが可能です。
Telegramと比べて見つけやすいです。

トップページ上部のメニューからビジネス向けをクリック
https://business.whatsapp.com/
WhatsApp Businessのページが開くので、ページ上部のメニューからDevelopersにマウスカーソルを当てるとプルダウンが出るので、そこからGet Startedをクリック
https://developers.facebook.com/docs/whatsapp/cloud-api/get-started
このページ自体がチュートリアルになっているので、読み進めながら実際に作って行ってみましょう。

WhatsAppにメッセージを送るサンプル

1.開発者アセットとプラットフォームアクセスを設定する

クラウドAPIを使うためには、Meta開発者アカウントとMeta開発者アプリを設定する必要があります。

1.Meta開発者として登録する

https://developers.facebook.com/docs/development/register
リンクの文言はMeta開発者ですが、遷移した先のページタイトルはFacebook開発者だったりするのが若干気になりますが、手順通り進めます。
途中Facebookアカウントにログインが必要です。ない場合はおそらく新規作成が必要。
ログインしたら、特に入力に困るところはないので、割愛します。

2.使用アカウントの二段階認証を有効にする

こちらもリンク先を見て設定すれば特に問題ないかと思います。
https://www.facebook.com/help/148233965247823

このページで、二段階認証を使用がオンになっていれば大丈夫です。
https://www.facebook.com/settings?tab=security

すでに設定済みだったので、次へ。

3.Metaアプリを作成する

下記ページからアプリを作成します。
https://developers.facebook.com/apps/

その他を選びます。

ビジネスを選びます。

アプリ名とメールアドレスを入力します。

こんな名前は良くない、ということで名前変更

「メッセージ送信テスト」でOKでした。

アプリが作れました。

WhatsAppと連携するので、WhatsAppの設定ボタンをクリックします。

設定ボタンをクリックすると下記のような表示になります。

WhatsAppと連携するには、WhatsApp BusinessプラットフォームAPIを用いる必要があり、
そのためにはMetaビジネスアカウントの作成が必要ということらしいです。

Metaビジネスアカウントの作成については、本記事の最後に載せています。

Metaビジネスアカウントが作成できると、先ほどの画面に戻ってきます。

これでアプリとWhatsAppが連携できました。

テストメッセージを送る

ページ内でサンプルメッセージを送ることができるので試してみます。

ステップ1: 電話番号を選択
送り先の電話番号を選択します。
最初は番号が登録されていないため、新しく電話番号を追加します。

登録した電話番号を持っているスマホにWhatsAppをインストールしておきましょう。

ステップ2: APIでメッセージを送信
curlのコマンドがあるのでそちらを実行してもOKですが、メッセージを送るボタンがあるので、そちらで簡単に試すことができます。

メッセージの内容は事前にテンプレートを作成しておき、送信時にテンプレートを指定する方式のようです。

トークンの固定化

テスト送信で使用しているトークンは時間で無効になってしまうため、実際にアプリケーションでの使用はできません。
左のメニューで設定ページを開くと固定トークンというのがあるので、これを試してみます。

「固定トークン」にあるリンク先の内容を見ていくと、
APIで使用するのは、システムユーザーアクセストークンが良いようです。

システムユーザーアクセストークンを作るには以下の手順でできそうです。

システムユーザを作る

  1. Meta Business Suiteにサインインします。
  2. 左上のドロップダウンメニューでビジネスアカウントを見つけ、設定(歯車)アイコンをクリックします。
  3. [ビジネス設定]をクリックします。
  4. [ユーザー] > [システムユーザー]の順に移動します。
  5. [追加]ボタンをクリックして、[管理者]または[社員]システムユーザーを作成します。

システムユーザーアクセストークンを生成する

  1. Meta Business Suiteにサインインします。
  2. 左上のドロップダウンメニューでビジネスアカウントを見つけ、設定(歯車)アイコンをクリックします。
  3. [ビジネス設定]をクリックします。
  4. [ユーザー] > [システムユーザー]の順に移動します。
  5. システムユーザーのリストから該当するシステムユーザーを選択します。
  6. [新しいトークンを生成]ボタンをクリックします。
  7. トークンを使用するアプリを選択します。
  8. アプリが正しく機能するために必要なアクセス許可をすべて選択し、トークンを生成します。

では、やっていきます。

システムユーザを作る

  1. Meta Business Suiteにサインインします。

  2. 左上のドロップダウンメニューでビジネスアカウントを見つけ、設定(歯車)アイコンをクリックします。

  3. [ビジネス設定]をクリックします。

  4. [ユーザー] > [システムユーザー]の順に移動します。

  5. [追加]ボタンをクリックして、[管理者]または[社員]システムユーザーを作成します。

アセットの追加

続けて作成したシステムユーザが利用できるアプリを紐づけるため、
アセットの追加を行います。

システムユーザーアクセストークンを生成する

  1. Meta Business Suiteにサインインします。

  2. 左上のドロップダウンメニューでビジネスアカウントを見つけ、設定(歯車)アイコンをクリックします。

  3. [ビジネス設定]をクリックします。

  4. [ユーザー] > [システムユーザー]の順に移動します。
    ここまでは、システムユーザを作るのと同じなので飛ばします。

  5. システムユーザーのリストから該当するシステムユーザーを選択します。

  6. [新しいトークンを生成]ボタンをクリックします。

  7. トークンを使用するアプリを選択します。

[新しいトークンを生成]ボタンをクリックした段階では小さいポップアップなのですが、
アプリを選択すると、縦にめっちゃ伸びます。
見切れているので、スクロールするとアクセス許可のチェック項目が表示されます。

  1. アプリが正しく機能するために必要なアクセス許可をすべて選択し、トークンを生成します。
    [新しいトークンを生成]ボタン

現状選択できるのは以下のようです。

利用可能なアクセス許可名 内容
instagram_manage_comments Instagramのコメントを管理する
instagram_basic Instagramの基本情報を読み取る
business_management ビジネスアカウントを管理する
read_insights インサイト(統計情報)を読み取る
pages_show_list ページの一覧を表示する
ads_read 広告情報を読み取る
instagram_manage_insights Instagramのインサイト(統計情報)を管理する
catalog_management カタログを管理する
pages_messaging ページのメッセージングを行う
page_events ページのイベントを管理する
publish_video 動画を公開する
leads_retrieval リード情報を取得する
pages_read_engagement ページのエンゲージメントを読み取る
pages_manage_metadata ページのメタデータを管理する
pages_manage_ads ページの広告を管理する
pages_manage_cta ページのCTA(コール・トゥ・アクション)を管理する
whatsapp_business_messaging WhatsAppビジネスメッセージングを行う
ads_management 広告を管理する
pages_read_user_content ユーザーコンテンツを読み取る
pages_manage_posts ページの投稿を管理する
whatsapp_business_management WhatsAppビジネスを管理する
instagram_manage_messages Instagramのメッセージを管理する
pages_manage_instant_articles インスタント記事を管理する
read_page_mailboxes ページのメールボックスを読み取る
instagram_content_publish Instagramのコンテンツを公開する
pages_manage_engagement ページのエンゲージメントを管理する

メッセージ送るだけであれば、whatsapp_business_messagingだけでよさそうです。
アセットでアプリを追加した段階で、whatsapp_business_managementwhatsapp_business_messagingの2つはすでにチェックされており、外すこともできないので、
この設定でトークン生成してみます。

利用可能なアクセス許可の詳細は下記にまとまっています。
https://developers.facebook.com/docs/permissions/reference

固定化したトークンでテストメッセージを送る

生成したトークンで、テストメッセージを送ってみます。
ブラウザ上ではトークンの変更が出来ないので、一緒に表示されていたcurlのコマンドをコピーし、
トークンを差し替えてcurlを実行してみます。

curl -X POST \
  https://graph.facebook.com/v17.0/108680348972887/messages \
  -H 'Authorization: Bearer <固定化したトークン>' \
  -H 'Content-Type: application/json' \
  -d '{ "messaging_product": "whatsapp", "to": "<電話番号>", "type": "template", "template": { "name": "hello_world", "language": { "code": "en_US" } } }'

トークンを差し替えてもメッセージが送られましたー。

サンプルプログラムからメッセージを送る

コードはChatGPTにチャチャっと書いてもらいます。

main.go

package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"strings"

	"github.com/joho/godotenv"
)

func main() {
	// .envファイルから環境変数を読み込む
	err := godotenv.Load()
	if err != nil {
		log.Fatalf("Error loading .env file: %s", err)
	}

	phoneId := os.Getenv("PHONE_ID")
	phoneNumber := os.Getenv("PHONE_NUMBER")
	accessToken := os.Getenv("TOKEN")

	// APIエンドポイントURL
	baseURL := "https://graph.facebook.com"
	version := "v17.0"
	url := fmt.Sprintf("%s/%s/%s/messages", baseURL, version, phoneId)

	// JSONデータを定義
	jsonData := `{
		"messaging_product": "whatsapp",
		"recipient_type": "individual",
		"to": "` + phoneNumber + `",
		"type": "template",
		"template": {
			"name": "hello_world",
			"language": {
				"code": "en_US"
			}
		}
	}`

	// POSTリクエストを作成
	req, err := http.NewRequest("POST", url, strings.NewReader(jsonData))
	if err != nil {
		log.Fatalf("Error creating request: %s", err)
	}

	// ヘッダーを設定
	req.Header.Set("Authorization", "Bearer "+accessToken)
	req.Header.Set("Content-Type", "application/json")

	// HTTPクライアントを作成
	client := &http.Client{}

	// リクエストを送信してレスポンスを取得
	resp, err := client.Do(req)
	if err != nil {
		log.Fatalf("Error sending request: %s", err)
	}
	defer resp.Body.Close()

	// レスポンスを表示
	fmt.Println("Status Code:", resp.StatusCode)
	fmt.Println("Response Body:")
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("Error reading response body: %s", err)
	}
	fmt.Println(string(body))
}

.env

同じ階層に.envファイルを置いて下記のように定義します。

PHONE_ID=your-phone-id
TOKEN=your-bot-token
PHONE_NUMBER=your-phone-number

PHONE_ID・・・URLの一部になります。メッセージの差出人となる電話番号IDを指定します。
TOKEN・・・先ほど生成したトークンを指定します。
PHONE_NUMBER・・・メッセージの送信先となる電話番号を指定します。

実行

go run main.go

と言うことで、無事メッセージを送る事ができました。

最後に

開発用のアカウントだけでなく、ビジネスアカウントも必要であり、試すまでのハードルがまぁまぁ高い印象でした。
そして、メッセージを送るために電話番号が必要なのがSMS感があって手間に感じました。

今回作成したサンプルプログラムは下記ですので、参考になれば幸いです。
https://github.com/KaT0819/whatsapp-sample

また、テンプレートではなく任意のメッセージを送ることが出来ませんでした。
テンプレートのメッセージ送信と同様正常にコマンドの実行は完了するのですが、肝心のメッセージが送られないいという謎事象に見舞われ解決しきれませんでした。
curlのコマンドだけでも残しておき、未来の自分に託したいと思います。

curl -X  POST \
 https://graph.facebook.com/v17.0/108680348972887/messages \
 -H "Authorization: Bearer <固定化したトークン>" \
 -H "Content-Type: application/json" \
 -d @- <<EOS 
{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "<電話番号>",
  "type": "text",
  "text": {
    "preview_url": false,
    "body": "Hello WhatsApp"
  }
}
EOS

おまけ

APIドキュメント

Message
https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages
メッセージの送信のガイド
https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-messages

エラーコード一覧
https://developers.facebook.com/docs/whatsapp/cloud-api/support/error-codes

Metaビジネスアカウントの登録

「アカウントの作成」

ビジネスの名前、氏名、メアドを入力します。

ビジネス名は「テスト」でもOKでした。実際にビジネスで利用する際はちゃんとした名前をつけるようにしましょう。
氏名も実際の名前でなくても良さそう。
氏と名の間は半角スペースで開けてあげる必要があります。

Metaビジネスアカウントの本人確認

ビジネスアカウントを作成しただけでは、
アプリとWhatsAppの連携を行おうとしてもエラーが発生し進めません。

Onboarding Failure
Your business is prohibited from advertising, including app sharing.

翻訳:あなたのビジネスは、アプリの共有を含む広告を禁止されています。

ビジネスアカウントを作成すると、いくつかメールが届いています。
「広告の利用が制限されています」というタイトルのメールが来ていました。
どうやら本人確認が必要そうなのでやっていきましょう。

基本、案内に従って進めていけばOKです。
途中、以下を求められるので、事前に準備しておくとスムーズです。

  • 顔写真をアップロード
  • 運転免許証など顔写真付きの証明書のコピーをアップロード

Discussion

tk42tk42

詳細な記事ありがとうございます.
日本語での解説記事が少なかったため大変助かりました.

「最後に」にある

任意のメッセージを送ることが出来ませんでした。
テンプレートのメッセージ送信と同様正常にコマンドの実行は完了するのですが、肝心のメッセージが送られないいという謎事象に見舞われ解決しきれませんでした。

こちらの件ですが同じ問題で悩んでいたところ,こちらのstackoverflowにて解決しました.

Message templates are the only type of message that can be sent to customers who have yet to message you, or have not messaged you in the last 24 hours. Thus, message templates are primarily used to initiate conversations with customers.
メッセージ テンプレートは、まだメッセージを送信していない、または過去 24 時間以内にメッセージを送信していない顧客に送信できる唯一のメッセージ タイプです。したがって、メッセージ テンプレートは主に顧客との会話を開始するために使用されます。

It means the business can send other types of messages only if the user replies to the business in 24 hours window.
つまり、ユーザーが 24 時間以内に返信した場合にのみ、企業は他の種類のメッセージを送信できるということです。(抄訳)

とある通り「ユーザーからメッセージを送信する」ことが必要でした.
一度ユーザーからメッセージを送ってからは,curlからテンプレート以外のメッセージ送信が可能になりました.

ご参考になれば幸いです.