🔰

Vonage SMS ガイド

2024/03/28に公開

こんにちは。KDDI ウェブコミュニケーションズの小原です。

Vonage(ボネージ)の SMS 送信は数行程度のコードで実現できます。このガイドでは、SMS 送信の概要、必要な準備、送信方法、トラブルシューティングなどについて説明します。

要約

  • SMS API ではなく Messages API を推奨
  • 電話番号の取得は不要
  • 最大文字数: 660 文字
  • 課金単位:70 文字単位
  • 秒間送信数: 30 通(30MPS)
  • 到達率: 業界標準
  • 日本の電話番号から受信不可

要件

Vonage の SMS

国際 SMS と国内直収 SMS を同一料金で提供します。

国際 SMS 国内直収 SMS
概要 海外経由で配信 国内キャリアに直接配信
発信料 11 円 11 円
利用方法 標準で利用可能 別途お申し込み
秒間送信数 (MPS) 30 30
最大文字数(日本語) 660 文字 660 文字
課金単位(日本語) 70 文字 70 文字
最大文字数(英数字のみ) 3800 文字 3800 文字
課金単位(英数字のみ) 160 文字 160 文字
電話番号の取得 不要 不要
到達率
From(デフォルト) Alphanumeric Sender ID
(電話番号は利用不可)
他社と共通番号
専用番号(オプション) ×
受信 × ×
双方向 SMS(オプション) ×

Messages API と SMS API の違い

Vonage には SMS を送信する方法として Messages API と SMS API があります。

弊社では Messages API の利用を推奨します。

Messages API は SMS API と同じ機能に加え、将来的に LINE や RCS 対応が予定されています。コードに互換性がないため、今から開発するのであれば Messages API を推奨します。

Messages API SMS API
最大文字数 660文字 660文字
MPS(秒間の送信数) 30 30
SMS
Facebook Messenger ×
MMS ×
Viber ×
WhatsApp ×
Proactive Connect ×
LINE 予定 ×
RCS 予定 ×

Messages API サンプルコード

import json
import os

import vonage

client = vonage.Client(
    application_id=os.environ.get("VONAGE_APPLICATION_ID"),
    private_key=os.environ.get("VONAGE_APPLICATION_PRIVATE_KEY_PATH"),
)

response = client.messages.send_message(
    {
        "channel": "sms",
        "message_type": "text",
        "to": os.environ.get("TO_NUMBER"),
        "from": os.environ.get("VONAGE_BRAND_NAME"),
        "text": "日本語のテスト",
    }
)

print(json.dumps(response, sort_keys=True, indent=4))

参考資料

SMS API サンプルコード

import json
import os

import vonage

client = vonage.Client(
    key=os.environ.get("VONAGE_API_KEY"),
    secret=os.environ.get("VONAGE_API_SECRET")
)

response = client.sms.send_message(
    {
        "type": "unicode",
        "to": os.environ.get("TO_NUMBER"),
        "from": os.environ.get("VONAGE_BRAND_NAME"),
        "text": "日本語のテスト",
    }
)

print(json.dumps(response, sort_keys=True, indent=4))

参考資料

Messages API の初期設定

Messages API を利用するには設定が必要です。

デフォルトの SMS 設定

この設定は Vonage 全体の設定になるため、一度設定すれば完了です。

  1. 左メニューの「API 設定」を選択
  2. 「デフォルトの SMS 設定」の「Messages API」を選択

デフォルトの SMS 設定

  1. 画面右下の「変更を保存」を選択
  2. 確認のダイアログが出るため「SWITCH」と入力し、「切り替えて保存」を選択

Messages API に SWITCH

Webhook の用意

Messages API の認証には次節で案内するアプリケーションの作成が必要です。

その際、Webhook の設定が必要になるため、ここでは ngrok と Web フレームワークに Flask を使った一時的な Webhook を用意します。実運用であれば Vonage からアクセス可能なサーバ(AWS や VPS、自社サーバなど)を用意する必要があります。

  1. flask のインストール
  2. webhook.py の用意
  3. webhook.py の起動
# Flask のインストール
pip install flask
webhook.py
import json

from flask import Flask, request

app = Flask(__name__)


@app.route("/", methods=["GET", "POST"])
def show():
    requestData = request.get_data()
    requestJson = json.loads(requestData)
    print(json.dumps(requestJson, indent=2))
    return requestData


if __name__ == "__main__":
    app.run()
# webhook.py の起動
$ python webhook.py
 * Serving Flask app 'webhook'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit

Webhook は Vonage からアクセス可能である必要があるため、ローカルで動く webhook.py を ngrok でインターネット上に公開します。

ngrok のインストール方法は Mac や WSL などの OS によって異なるため ngrok 公式のインストール方法をご参照ください。Step 2: Connect your account まで進めてください。

インストールが終わったら ngrok を起動します。

# 5000 で動く webhook.py を ngrok で公開
$ ngrok http 5000
Session Status                online
Account                       kwcplus (Plan: Free)
Version                       3.13.0
Region                        Japan (jp)
Web Interface                 http://127.0.0.1:4040
Forwarding                    https://1234-56-789-0ab-cd.ngrok-free.app -> http://localhost:5000

Forwarding に各自ユニークな URL が発行されます(Ex. https://1234-56-789-0ab-cd.ngrok-free.app)。この URL が Vonage に設定する Webhook の URL になります。

http://localhost:4040/ にアクセスし、下記画面が表示されれば成功です。Vonage から Webhook にアクセスがあるとこの画面に内容が表示されます。

ngrok ready

Webhook に Basic 認証を使うことはできません。より安全な Signed Webhooks をご検討ください。

アプリケーションの作成

Messages API を認証して利用するには「アプリケーション ID」と「秘密鍵」を発行し、アプリケーションの「メッセージ」を有効化します。

  1. 左メニューの「アプリケーション」を選択
  2. 「新しいアプリケーションを作成する」を選択
  3. 「名前」にわかりやすい識別子(SMS 送信など)を指定
  4. 「認証」の「公開鍵と秘密鍵を生成」を選択し、ダウンロードした private.key(秘密鍵)を保存
  5. 「メッセージ」に「着信 URL」と「ステータス URL」に ngrok の URL を設定。どちらも同じ URL で構いません
  6. 画面右下の「新しいアプリケーションの生成」を選択

アプリケーションを作成する

  1. 発行された「アプリケーション ID」をメモ

アプリケーションを作成する

Messages API に利用する「アプリケーション ID」と「秘密鍵」は大切に保管ください。

なお、以上の作業は Vonage CLI もしくは Application API でも設定可能です。

SMS 送信

アプリケーション ID と秘密鍵が用意できたので SMS を送信する準備が整いました。

ここでは Python を使います。ほかの言語をご利用の方はタブから言語を選択して適宜読み替えてください。

送信サンプル

SDK のインストール

「Install dependencies」をクリックすると SDK のインストール方法が表示されます。

SDK のインストール

pip install vonage

SMS の送信

送信プログラムは send_sms.py とします。

send_sms.py
import os

import vonage

# クレデンシャル
VONAGE_APPLICATION_ID = os.environ.get("VONAGE_APPLICATION_ID")
VONAGE_APPLICATION_PRIVATE_KEY_PATH = os.environ.get(
    "VONAGE_APPLICATION_PRIVATE_KEY_PATH"
)

# From, To
VONAGE_BRAND_NAME = os.environ.get("VONAGE_BRAND_NAME")
TO_NUMBER = os.environ.get("TO_NUMBER")

# 本文
VONAGE_SMS_BODY = os.environ.get("VONAGE_SMS_BODY")

# 初期化
client = vonage.Client(
    application_id=VONAGE_APPLICATION_ID,
    private_key=VONAGE_APPLICATION_PRIVATE_KEY_PATH,
)

# SMS 送信
response = client.messages.send_message(
    {
        "channel": "sms",
        "message_type": "text",
        "to": TO_NUMBER,
        "from": VONAGE_BRAND_NAME,
        "text": VONAGE_SMS_BODY,
    }
)
print(response)

send_sms.py で利用する環境変数は下記です。

環境変数
VONAGE_APPLICATION_ID メモしたアプリケーション ID
VONAGE_APPLICATION_PRIVATE_KEY_PATH 保存した private.key
VONAGE_BRAND_NAME Alphanumeric Sender ID
TO_NUMBER 送信先電話番号(E.164)
VONAGE_SMS_BODY SMS 本文(UTF-8 + LF)

Alphanumeric Sender ID

Vonage の SMS は From にアメリカ番号を利用できないため、下記ルールの Alphanumeric Sender ID を利用します。

  • 3 ~ 11 文字
  • 利用可能な文字は a ~ z, A ~ Z, 0~9, スペース
    • 数字のみは不可

たとえば「KWC 2FA」や「KWCPlus」が利用可能です。

E.164/MSISDN

Vonage は世界中に SMS 送信できるため、電話番号に国番号を含めた E.164/MSISDN 形式で書く必要があります。

日本の国番号は 81 です。

電話番号の先頭の 0 を外し、先頭に国番号を追加します。

たとえば電話番号が 080-XXXX-YYYY であれば 8180XXXXYYYY になります。

E.164 は先頭に + を追加した +8180XXXXYYYY 形式もありますが、Vonage は + が不要です。

SMS の文字コードと課金単位

文字コード

Vonage は SMS 本文を UTF-8 で書きます。

Vonage は UTF-8 で受け取り、自動で SMS が利用する文字コードの GSM-7 もしくは UCS-2 に変換して送信します。

文字コード 最大送信数 課金単位 備考
GSM-7 3800 文字 160 文字単位
UCS-2 660 文字 70 文字単位 GSM-7 以外の文字が含まれる場合

GSM-7 は英数字や記号などです。

UCS-2 は GSM-7 以外の文字、つまり日本語などが含まれると自動で選ばれます。

最大送信数や課金単位は文字数単位となり、バイト数ではありません。UCS-2 であれば「あa」は 2 文字です。

例外があり、次の記号は SMS の制御に使われるためエスケープ処理されて 2 文字として換算されます。

| ^ € { } [ ] ~ \

分割にはさらに細かいルールがありますが、その説明と、簡単に何分割されるかは連結エンコード中ほどの Try it out が便利です。

「a」は 160 文字で分割されませんが、「[」は 81 文字で Part 1 と Part 2 で二分割されます。

Basic Character Set の分割

Basic Character Set Extension の分割

課金単位

課金は GSM-7 なら 160 文字単位、UCS-2 なら 70 文字単位になります。

API で指定した文字数が UCS-2 で 71 文字の場合、2 通の課金になります。

課金の単位は文字数単位であって、API 単位ではないことにご注意ください。文字数で課金されるため、改行コードが CRLF は 2 文字になり、LF なら 1 文字で済みます。

自動で 70 文字もしくは 160 文字に分割され、宛先のスマホには自動で連結されて届きます。そのため Concatenated SMS やコンカチ SMS と呼ばれることがあります。

SMS送信

ややこしい話が続きましたが、以上を踏まえて SMS を送信してみましょう。TO_NUMBER に書いた番号に届いたでしょうか?

$ VONAGE_APPLICATION_ID=アプリケーション ID \
  VONAGE_APPLICATION_PRIVATE_KEY_PATH=private.key \
  VONAGE_BRAND_NAME="AlphaNum 11"
  TO_NUMBER=8180XXXXYYYY \
  VONAGE_SMS_BODY=$'こんにちは\nテストです' \
  python send_sms.py
{'message_uuid': 'f1234ba5-de67-4157-bdfa-27e309f51627'}

Webhook

SMS を送信すると Vonage から Webhook に Delivery receipts が届きます。

Vonage がキャリアに送信を依頼すると submitted、送信先端末から到達の連絡があると delivered になります。

SMS は分割されることがあります。分割数は ["sms"]["count_total"] で確認が可能です。

ngrok の下記ページでリアルタイムに Webhook を見ることができます。

http://127.0.0.1:4040/

{
    "to": "8180XXXXYYYY",
    "from": "AlphaNum 11",
    "channel": "sms",
    "message_uuid": "7506c56b-a6ff-45e6-8c62-868fa34afc4d",
    "timestamp": "2024-03-07T04:35:56Z",
    "usage": {
        "price": "0.26668",
        "currency": "EUR"
    },
    "status": "submitted",
    "destination": {
        "network_code": "44020"
    },
    "sms": {
        "count_total": "4"
    }
}
{
    "to": "8180XXXXYYYY",
    "from": "AlphaNum 11",
    "channel": "sms",
    "message_uuid": "7506c56b-a6ff-45e6-8c62-868fa34afc4d",
    "timestamp": "2024-03-07T04:36:00Z",
    "status": "delivered",
    "destination": {
        "network_code": "44010"
    }
}

Messages API の Webhook の注意点

Messages API で一通の SMS が分割される場合に、分割された二番目以降の message_uuid と Webhook は取得できません。ダッシュボードのログで確認できます。

SMS API は分割された全件の Webhook を取得可能です。

ログ

ダッシュボードでは Messages ログと SMS ログで同じものが見えます。

SMS ログでは、Status の delivered などをクリックすると「SMS ライフサイクル」を見ることができます。

SMS ログ

「配信ステータス(DLR)」は詳細なステータスを確認できます。

送信に失敗した場合に、ネットワークエラーや、受信者不在など確認できます。

DLR のステータス詳細はこちらをご参照ください。

https://developer.vonage.com/ja/messaging/sms/guides/delivery-receipts

ダッシュボードで SMS の個別ログを確認できる期間は 30 日間です。30 日より前の個別ログを閲覧するには有料の Reports API をご利用いただくか、Webhook のログを独自保存する必要があります。

月ごとの件数や配信成功率であれば「SMS分析」と「配信と品質」から参照が可能です。

SMS 分析

SMS 分析 - 月別

SMS 分析 - 月別」の Successful が課金対象数です。

Reports API では価格のある項目が課金対象数です。

SMS 配信

SMS 配信

SMS 配信」はステータスごとの配信状況が確認できます。

トラブルシューティング

送信した SMS が届かない問題の切り分けには SMS 送信の仕組みを知る必要があります。

国際 SMSと国内直収 SMS について

図の「キャリア」が海外キャリアか、国内キャリア(au、docomo、Softbank、楽天モバイル)かの違いになります。

海外キャリアは複数の海外キャリアを経由して国内キャリアにたどり着きます。

国内キャリアの障害率は非常に低いのですが、海外キャリアは国内キャリアに比べ障害率が高くなります。そのため、国内直収に比べて到達率が下がります。

Vonage は日本も含めたキャリアの障害情報を Vonage API Status で公開しています。障害の多くは海外キャリアの障害になります。

国際 SMS の到達率は低くても、Webhook の status を確認して再送することで到達率を高めることができます。

到達率について

国内直収 SMS の到達率は 99% ですが、一般的に 10 ~ 30% の SMS が端末に届かないことがあります。

この 99% の到達率は「③ SMS 送信」した率になり、下記理由は除外されます。

  1. SMS に送信できない電話番号への送信
    • 03 や 06 などの地域番号
    • 070/080/090 でも SMS 機能のない SIM
  2. 秒間 30 通以上の送信(30MPS)
  3. E.164 形式ではない電話番号での送信
    • 8180XXXXYYYY 形式の必要があります。080XXXXYYYY は送信できません
  4. 存在しない電話番号への送信
    • 入力間違いなど。ユーザからの初回入力時には到達可能かご確認ください。SMS 送信して URL をクリックいただくなどです
  5. 受信拒否
    • 端末契約者が許否した場合
    • 端末によってはデフォルトで受信拒否設定の場合があります
  6. 圏外、電源オフ
  7. 端末契約者の料金未納
  8. キャリアによるフィルタリング

1.~3. は「① API」で発生します。SDK もしくは Vonage からエラーメッセージが返りますので、エラーメッセージをご確認ください。課金は発生しません。課金は「② SMS 送信依頼」された場合に発生します。

4.~5. は 100% 送信することができません。SMS ログの DLR をご確認ください。

6.~7. は再送することで到達する可能性があります。過去、送信できていた場合は本事象の可能性の可能性があります。

8.は 30MPS 以下や一般的な文面では発生しません。

その他の送信できない理由としては Vonage やキャリアの障害があります。
SMS Analytics で一部 Network(キャリア)の失敗が高い場合はその可能性があります。

KWCPLUS

Discussion