Telegram ボットで暗号資産の支払いを受け付ける方法
自作 Telegram ボットの物理商品の注文を Cryptanio のインボイスに紐付け、支払いリンクを送り、入金を確認する方法。Telegram Stars と Mini Apps の制限も説明します。
更新日:
自作 Telegram ボットの注文に暗号資産の支払いを紐付けることができます。サーバーが Cryptanio のインボイスを作成し、ボットが購入者にリンクを送り、支払いを確認してから注文の受け付けを通知します。ここでは、印刷したポスターなどの物理商品を販売するショップを例に説明します。ボットと注文処理は、ご自身で開発する必要があります。
最初に Telegram のルールを確認する
Telegram 内で販売するデジタル商品やサービスには、XTR と表記される Telegram Stars の使用が必須です。ボット内のコンテンツへの有料アクセスなどが該当します。外部サイトへのリンクを用意しても例外にはなりません。このような購入について、Stars の代わりに暗号資産での支払いを案内することはできません。これらの制限は Telegram Stars のドキュメントに明記されています。
本ガイドの対象は、Mini App を持たない通常のボットと、物理商品の注文です。Mini Apps と関連ボットには、TON の利用を含め、ブロックチェーン連携に関する追加の制限があります。Mini App を持たない通常のボットは、Telegram の Blockchain Guidelinesでこれらのルールの適用対象から明示的に除外されています。そのため、追加の確認なしに本ガイドを Mini App に転用することはできません。Telegram のルールは 2026 年 11 月 13 日に確認しました。
必要なもの
自作ボット、ボットを動かすサーバー、Cryptanio アカウント、Payments サービスが有効なプロジェクトを準備します。そのプロジェクトの Payments に接続された受取アドレスと、インボイスおよび必要なサービスの権限を持つ有効な API キーも必要です。
Telegram ボットのトークン、Cryptanio の API キー、webhook の署名検証用シークレットはサーバーに保管してください。購入者に渡すのは、その人の支払いリンクだけです。本ガイドは、ショップの作成から注文処理まで自動で行う完成済みの連携機能を前提としていません。
1. 決済用プロジェクトを準備する
管理画面で Payments を有効にし、そのサービスのプールに受取アドレスを追加します。アドレス帳に登録するだけでは不十分です。必要なネットワークと資産をプロジェクトで利用できることを確認し、支払いページに表示されない選択肢を購入者に案内しないでください。
USDT とネットワークの違いがまだ明確でなければ、先に「ネットワークとトークン」をお読みください。インボイスは、個別の支払い請求とその状態を結び付けます。
2. 注文と購入者を紐付ける
ユーザーがポスターを選んで注文を確定したら、サーバーで内部の注文番号を作成します。注文、Telegram の購入者、これから作成するインボイスの ID の対応関係を保存してください。連絡先や配送先住所はご自身のシステムに保管し、技術的なリンクや公開メッセージに含める必要はありません。
保存したインボイス ID から、対応する注文を一意に特定できるようにします。これにより、ボットを再起動した後でも支払いを処理できます。
3. 個別のインボイスを作成する
サーバーから API v1 のインボイス作成操作を呼び出します。ネットワークと資産を購入者が選ぶ場合は、invoice_currency と invoice_amount で注文の見積額を指定します。たとえば USD 12.50 は見積もりの単位を表し、実際の支払いには対応する暗号資産を使います。米ドルの受け付けや資金の自動交換を意味するものではありません。
以下は、ドキュメントのカタログにある、サポート対象の注文作成サンプルへの参照です。
#!/usr/bin/env bash
set -euo pipefail
: "${CRYPTANIO_API_KEY:?Set CRYPTANIO_API_KEY}"
: "${CRYPTANIO_OPERATION_ID:?Set CRYPTANIO_OPERATION_ID}"
: "${CRYPTANIO_PROJECT_ID:?Set CRYPTANIO_PROJECT_ID}"
json_string() {
local text="$1" char code index output='"'
for ((index=0; index<${#text}; index++)); do
char="${text:index:1}"
case "$char" in
'"'|'\') output+="\\$char" ;;
*) printf -v code '%d' "'$char"
if ((code < 32)); then printf -v char '\\u%04x' "$code"; fi
output+="$char" ;;
esac
done
printf '%s"' "$output"
}
response_file="$(mktemp)"
trap 'rm -f "$response_file"' EXIT
transfer_status=0
http_status="$(curl \
--silent --show-error --max-time 30 --request POST \
--header "Authorization: Bearer $CRYPTANIO_API_KEY" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header "Idempotency-Key: $CRYPTANIO_OPERATION_ID" \
--data-binary '{"project":'"$(json_string "$CRYPTANIO_PROJECT_ID")"',"invoice_currency":"USD","invoice_amount":"12.50","reference":"order-42"}' \
"https://api.cryptanio.com/v1/invoices" \
--output "$response_file" --write-out '%{http_code}')" || transfer_status=$?
if [[ "$http_status" == 2?? ]]; then
cat "$response_file"
exit "$transfer_status"
fi
printf 'HTTP %s\n' "$http_status" >&2
cat "$response_file" >&2
exit 1
ご自身の注文パラメーターを渡してください。新しい操作には一意の Idempotency-Key が必要です。障害後に同じリクエストを再試行する場合は、元のキーを維持します。これにより、ボタンの連続クリックで別の請求が作られることを防ぎます。詳細は注文確認ガイドをご覧ください。
4. 購入者にリンクを送る
作成レスポンスの checkout_url を保存し、個別チャットでリンク付きボタンとして送信します。Bot API は URL ボタンに対応しています。詳しくは InlineKeyboardButtonをご覧ください。購入者は Cryptanio のページを開き、利用可能な支払い方法を選びます。
受け取った URL をそのまま渡してください。ID からリンクを組み立てないでください。インボイスの読み取り時に返されるリンクは、閲覧用です。対話式の支払いを続けるには、保存した作成レスポンスのリンクが必要です。
5. サーバーで支払いを確認する
プロジェクトの webhook をご自身のハンドラーに向けて設定し、リクエストの元の本文で署名を検証します。イベントを保存済みのインボイスと照合し、その後 API で現在の状態を確認してください。
注文を履行処理に進めるのは、成功状態の paid になった場合だけです。取引の検出、購入者のチャットへの復帰、「支払いました」というメッセージは、この確認にはなりません。一部入金、入金不足、過払い、期限後の入金は、個別の判断が必要になる場合があります。そのような注文を自動で確定しないでください。webhook が重複して届いても、注文を二重に履行してはいけません。
確認方法とエラーの調べ方
ご自身の注文で、作成、リンクの表示、支払い、状態の変更、ボットのメッセージまで、一連の流れを確認します。ネットワーク手数料も考慮してください。この方法で作成するインボイスでは実際のデータを扱います。ボタンの重複クリックとイベントの再配信も、別途確認してください。
送金済みなのに注文が確定しない場合は、ネットワーク、資産、支払い情報、取引の承認を照合します。すでに paid なら、注文とインボイスの紐付け、およびボットのハンドラーを調べてください。オーナー向けの Telegram 通知は別のガイドで設定できますが、それ自体がサーバーによる注文の確認を代替するものではありません。