Telegram Mini AppのStar課金について
Telegram Mini Appでは、Telegramのアプリ内通貨「Star」を使用してデジタルアイテムを販売できます。
この記事では、Star課金の実装方法について詳しく解説します。
事前準備
Starの購入
まず、Star課金で使用するStarを購入しましょう。Telegramのテスト環境と本番環境では購入方法が異なります。
テスト環境でStarを無料で入手する方法
Telegramのテスト環境では、テスト用のクレジットカードを使用する事でStarを無料で入手可能です。
テスト環境への切り替え方法
Telegramアプリでのテスト環境への切り替え方法はプラットフォームごとに異なります。一部のプラットフォーム(Android版、Web版など)ではテスト環境は利用できません。
-
Telegram iOSアプリ版
設定アイコンを10回タップ → アカウント → 別のアカウントにログイン → テスト
-
メニュー(☰) → [Settings] → [MyAccount] を開き、Shift + Alt + [アカウントの追加] を右クリック→ [テスト サーバー] を選択
-
設定アイコンを 10 回クリックしてデバッグ メニューを開き、⌘ キーを押しながら「アカウントの追加」をクリック → 電話番号でログイン
Starの購入方法
デスクトップ版またはmacOS版のTelegramアプリを使用してテスト環境に切り替え、設定画面の「My Stars」を開きます。クレジットカード情報を入力してStarを購入します。
詳しくは
クレジットカード番号はドキュメントに記載されている番号を入力して、カード番号以外の情報は任意で構いません。
(注意)iOS版TelegramではクレジットカードでのStar購入ができないため、無料での取得方法はありません
テスト環境でMini Appを作成する
テスト環境で購入したStarは、テスト環境で作成したMini Appでのみ利用できます。
以下のリンクからテスト環境のBotFatherにアクセスし、Mini Appを作成してください。
テスト環境のAPIエンドポイントについて
テスト環境では、Telegram APIのエンドポイントが以下のように変わります。
-
本番環境のAPIエンドポイント
https://api.telegram.org/bot<token>/METHOD_NAME
-
テスト環境のAPIエンドポイント
https://api.telegram.org/bot<token>/test/METHOD_NAME
例えば、pyTelegramBotAPIを使用する場合、以下のようにエンドポイントを変更します。
from telebot import apihelper
apihelper.API_URL = "https://api.telegram.org/bot{0}/test/{1}"
本番環境でStarを購入する方法
本番環境では、iOS/Android版のTelegramアプリからStarを購入できます。ただし、プラットフォーム手数料が上乗せされるため、割高になります。
Fragmentという外部サイトでは、Starを\$TON(Toncoin)で販売しており、より安価に購入可能です。
FragmentではStarのほか、Telegram Premium、ユーザー名、電話番号なども\$TONで販売しています。
\$TONとは?
TONは、Telegramが開発を始めたブロックチェーンで、プロジェクト開始当初は「Telegram Open Network」という名称で進められていましたが、現在は「The Open Network」と改称され、非営利団体であるTON Foundationによって開発・運営されています。
\$TON(Toncoin)は、TONのネイティブトークンです。
https://ton.org/
テスト環境、本番環境どちらで開発すべき?
テスト環境ではStarを無料で利用できるため初期コストを抑えられます。一方、本番環境での開発にはStarの購入費用がかかりますが、後述する返金処理でMiniAppに支払ったStarは回収可能です。どちらを選ぶかは、プロジェクトの要件に応じて判断してください。
Star課金の実装方法
Telegramからの課金イベント通知用Webhookの登録
Star課金では、Telegramサーバーからの課金イベント通知をWebhookで受け取る必要があります。そのため、まずWebhookの登録を行います。
以下は、FlaskとpyTelegramBotAPIを使ったサンプルコードです。
WebhookのURLの登録
WebhookのURLには、推測されにくいようにTOKENを含めることを推奨します。
# webhook urlを設定
webhook_url = f"https://your-domain.com/{telegram_token}/webhook"
bot.set_webhook(
url=webhook_url,
allowed_updates=['message', 'callback_query', 'pre_checkout_query'] # 受信するメッセージ
)
URLだけでは不安な場合は、シークレットトークンを設定することも可能です。シークレットトークンを設定すると、Webhookリクエストに「X-Telegram-Bot-Api-Secret-Token」ヘッダーが追加されます。
bot.set_webhook(
url=webhook_url,
allowed_updates=['message', 'callback_query', 'pre_checkout_query'],
secret_token="XXXXXXXXXXXX" # シークレットトークンを設定
)
Webhookの受信処理
Webhookに設定したURLの受信処理を以下のように実装します。
@app.route(f"/{telegram_token}/webhook", methods=['POST'])
def webhook():
update = telebot.types.Update.de_json(request.stream.read().decode("utf-8"))
self.bot.process_new_updates([update])
return "OK"
Star課金処理の流れ
①購入ボタン→請求画面表示
ユーザーが購入ボタンを押してから請求画面を表示するまでのフローを説明します。
1: ユーザーがアイテムの購入ボタンを押します。
2: ClientがServerAPIを呼び出して請求書URLを要求します。
3: Serverは、Telegram APIのcreate_invoice_link
関数を使用して請求書URLを生成します。
create_invoice_link
関数のパラメーターには販売するアイテム名や価格情報などを含めます。
payloadはユーザーには公開されないデータで、支払いプロセス中に参照できるデータなので、ここに販売するアイテム情報などを含めましょう。payloadは128バイトまでの容量制限があります。
発行した請求書URLをClientに渡します。
サンプルコード:請求書URLの生成
title = "ポーション"
description = "体力を10回復する"
provider_token = "" # Star支払いの場合は空文字
currency = "XTR" # Star支払いの場合はXTR
amount = 100 # 販売価格
prices = [telebot.types.LabeledPrice(label=title, amount=amount)]
# payloadに販売情報を含める
payload = urllib.parse.urlencode({'item_id': 5})
# 請求書URLを発行
bot = telebot.TeleBot(telegram_token)
invoice_link = bot.create_invoice_link(
title, description, payload, provider_token, currency, prices
)
# クライアントに請求書URLを渡す
return invoice_link
4: ClientはServerから受け取った請求書URLを使って請求画面を表示します。
twa-dev/sdkを使用している場合は、WebApp.openInvoice
メソッドを使用して、ユーザーに支払い確認画面を表示できます。
サンプルコード:請求画面の表示
WebApp.openInvoice(
invoice_link,
function (status) {
// 購入後のコールバック
switch (status) {
case "paid":
case "failed":
case "cancelled":
case "pending":
}
});
});
②ユーザーが請求書を確認して支払いを行う
請求書画面が表示された後、ユーザーが支払いを完了するまでのフローは以下の通りです。
1 ユーザーが請求書画面でStar支払いを行います。
2 Telegramが支払い直前イベント通知(PreCheckoutQuery)をAppServerに送信します。
このリクエストには購入者・請求情報・payloadなどの支払い内容が含まれます。
3 AppServer側で、受信した支払い内容を検証し、answerPreCheckoutQueryで支払いの承認もしくはキャンセルを行います。
サンプルコード:支払い直前イベント通知(PreCheckoutQuery)の受信処理
bot = telebot.TeleBot(telegram_token)
def pre_checkout_query_filter(query):
payment_info = dict(urllib.parse.parse_qsl(query.invoice_payload))
return True
@bot.pre_checkout_query_handler(func=pre_checkout_query_filter)
def handle_pre_checkout_query(query):
if is_valid(query):
# 支払い承認通知を送信
bot.answer_pre_checkout_query(query.id, ok=True)
else:
# 支払いキャンセル通知を送信
bot.answer_pre_checkout_query(query.id, ok=False, error_message="無効な商品情報です。")
4 支払いが完了するとTelegramが支払い完了イベント通知(SuccessfulPayment)をAppServerに送信します。
リクエストパラメーターには以下のような情報が含まれるので必要に応じてデータベースなどに保存します。
請求書URL発行時のpayloadには購入したアイテム情報が含めているので、購入者にアイテムの付与を行います。
telegram_payment_charge_idは返金処理で必要になるので必ず保存しておきましょう。
リクエストパラメーター
- 購入者情報
- 販売価格
- telegram_payment_charge_id
- 請求書URL発行時のpayload
サンプルコード:支払い完了イベント通知(successful_payment)の受信処理
@bot.message_handler(content_types=["successful_payment"])
def handle_successful_payment(message):
user_id = message.from_user.id
telegram_payment_charge_id = (
message.successful_payment.telegram_payment_charge_id
)
amount = message.successful_payment.total_amount
payment_info = dict(parse_qsl(message.successful_payment.invoice_payload))
# telegram_payment_charge_idをDBに保存
add_payment_info(user_id, telegram_payment_charge_id, amount)
# 購入者にアイテムを付与
add_item_to_user(user_id, payment_info.get("item_id"))
参考
返金処理の実装
アプリ側で返金処理を行う方法
- ユーザーから取引で発行されたTransactionIDを教えてもらいます。TransactionIDはTelegramの設定画面にあるスターの取引履歴から確認できます
- アイテム販売時の支払い完了イベント通知(SuccessfulPayment)で受け取った
telegram_payment_charge_id
と、1で取得したTransactionIDが一致するかを確認します - 返金は、refundStarPayment関数を使用して行います。この関数に返金対象の
user_id
と1で取得したTransactionIDをパラメータとして渡します - 必要に応じて、返金後にデジタルアイテムの没収などを行います
返金完了イベント通知
Telegram Bot APIの仕様によると、refunded_payment
というメッセージがWebhookで届くようですが、どのような操作を行った場合にこの通知が発生するのか、ドキュメントでは見つかりませんでした。
もし詳細をご存知の方がいれば、ぜひ教えてください。
参考
売上を受け取る方法
Starの売上は、Apple/Googleのプラットフォーム手数料(30%)およびTelegramの手数料を差し引いた額が、\$TONで受け取れます。現在、1スターあたり0.013米ドル相当の\$TONが支払われます。
受け取り方法は、Telegramアプリ(Web版以外)のMiniAppの詳細画面から「スター残高ページ」に遷移することで確認・操作が可能です。
ただし、1スター以上の売上がない場合、この「スター残高ページ」に遷移するためのボタンは表示されませんのでご注意ください。
参考
- Star Pricing
- Telegram Bot Developers - 6.2.4. Rewards for Stars
- https://coinmarketcap.com/currencies/toncoin/
サポート窓口
Telegram Mini Appでは、ユーザーからの支払いに関する問い合わせを受け付けるため、チャットコマンド /paysupport
を実装する必要があります。
サンプルコード:/paysupportの処理
@bot.message_handler(commands=["paysupport"])
def handle_paysupport(message):
bot.send_message(
message.chat.id,
"""
お支払いに関するお問い合わせは、以下のフォームよりご連絡ください。
http://example.com/paysupport/form
""".strip(),
)
参考
その他の注意事項
Star課金はTelegram側の審査を必要としませんが、Apple/Googleのアプリ内購入(IAP)のガイドラインに従う必要があります。
支払いに関するガイドラインの詳細については、以下のリンクをご参照ください:
Telegram Bot Developers - Payments
開発中にハマった事
当初vercel(Hobby Plan)を使って開発していましたが、Webhookの通知が届かない問題に悩まされていました。
おそらくvercelが共有サーバーのため?なのか、他のvercelユーザーの影響でTelegram側からアクセス制限がかかっている可能性が考えられます。
同様の問題が起こった場合は、aws等でインスタンスを用意する事をおすすめします。