Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Prevent Cart Desync: Build a Next.js Mini App Shop with MainButton Checkout

2026年10月01日に「Dev.to」が公開したITニュース「Prevent Cart Desync: Build a Next.js Mini App Shop with MainButton Checkout」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

Telegram Mini AppでNext.jsのECショップ構築時、Reactとネイティブボタンの状態同期、iOS表示崩れ、決済セキュリティが課題となる。これらを解決するため、`initData`のサーバー検証やCSS変数利用、ネイティブ連携で安定したショップを作る技術を解説する。

ITニュース解説

Telegram Mini Appは、人気メッセージングアプリであるTelegramの中で動作する小さなWebアプリケーションを指す。これはユーザーにとって非常に統合された体験を提供する一方で、開発者にとっては標準的なWebアプリケーションを構築するのとは異なる独自の課題をもたらす。特に、カート機能を持つECショップのようなMini AppをNext.jsのApp Routerを使って構築しようとすると、いくつかの重要な問題に直面する。もしMini Appを通常のWebアプリケーションと同じように扱ってしまうと、データの状態がずれてしまったり、iOSデバイスで画面の表示が崩れたり、さらにはセキュリティ上の脆弱性が生じたりする危険性がある。この記事では、これらの課題を克服し、堅牢なMini AppショップをNext.jsで構築するための方法を具体的に解説する。

まず、Telegram Mini Appの仕組みを理解することが重要だ。一般的なWebアプリケーションでは、支払い処理はブラウザ内で完結するが、Telegram Mini Appでは、通常、Telegramの画面下部に常に表示されるネイティブの「MainButton」というボタンを使って決済をトリガーし、その後Telegramのネイティブの支払い画面を開くのが、ユーザーにとって最もスムーズな体験となる。しかし、このMainButtonとWebアプリケーションの状態を適切に連携させないと、主に三つの大きな問題が発生する。

一つ目は「状態不同期」、つまりReactで管理しているカート情報とTelegramのMainButtonの状態が一致しない問題だ。MainButtonは、window.Telegram.WebApp SDKを通じて制御されるグローバルなUI要素であり、Reactコンポーネントツリーとは独立して存在する。例えば、ユーザーが商品をカートに追加したり削除したりしてReactの状態が変化しても、MainButtonのクリックリスナーを適切に更新しないと、ユーザーは古いカート情報で決済を試みてしまったり、誤って二重に購入してしまったりする可能性がある。これを防ぐためには、useEffectというReactのフックを使って、カートの状態が変化するたびにMainButtonの表示、テキスト、活性状態を同期させる必要がある。また、不要になったクリックリスナーを確実に解除する「クリーンアップ処理」も非常に重要だ。

二つ目は「iOSのビューポートバグ」だ。iOSデバイスでTelegramのWebViewが動作する際、キーボードが表示されたりMainButtonの表示が切り替わったりすると、CSSの100vh(ビューポートの高さの100%)が正しく計算されず、画面内の要素がずれて表示が崩れてしまうことがある。これにより、チェックアウトボタンが画面外に出てしまったり、入力フィールドが隠れてしまったりする不具合が生じる。この問題の解決策として、CSSの100vhの代わりに、Telegramのスクリプトが提供するCSS変数--tg-viewport-stable-heightを使用する。これにより、デバイスの環境に左右されない安定した表示を実現できる。

三つ目は「安全でないチェックアウト」だ。クライアントサイド(ユーザーのブラウザ側)で決済に必要な情報を生成しようとすると、Telegramボットのトークンが公開されてしまい、悪意のある攻撃者に利用されるセキュリティ上の脆弱性となる。このリスクを回避するためには、決済処理をNext.jsのRoute Handler(サーバーサイドのAPIエンドポイント)を経由させる必要がある。ユーザーのMini Appから送られてくるinitDataという情報を、サーバー側でHMAC-SHA256署名チェックを使って厳密に検証する。initDataが正当なものであれば、サーバーはTelegram Bot APIのcreateInvoiceLinkメソッドを呼び出し、安全な支払いリンクを生成してクライアントに返す。この方法により、ボットトークンがクライアント側に一切露出することなく、安全な決済フローを確立できる。

これらの課題を解決するための具体的な実装として、Next.jsのApp Router環境でTelegram WebApp SDKを安全に利用するために、React Context Providerを作成する。これにより、window.Telegramオブジェクトがクライアント側でのみ利用可能であるというサーバーサイドレンダリング(SSR)の制約に対応し、SDKの読み込みと状態管理を一元的に行うことができる。また、TypeScriptを利用している場合、global.d.tsファイルにWebAppインターフェースを宣言することで、SDKオブジェクトの型情報をTypeScriptに認識させ、安全な開発を促進する。

レイアウトの調整も不可欠だ。Telegram Mini AppはiOS、Android、デスクトップなど様々な環境のWebViewで動作するため、見た目が崩れないようにCSSを記述する必要がある。前述のiOSのビューポートバグへの対応に加え、Mini AppがTelegramのネイティブアプリの一部であるかのように感じさせるためには、UIの色をTelegramのテーマ変数(例:--tg-theme-bg-color)に合わせるのが効果的である。Tailwind CSSなどのフレームワークを使用している場合でも、これらのCSS変数を活用してテーマを同期させることができる。さらに、Mini App内でのページ遷移時には、Telegramのネイティブな「BackButton」を活用することで、一貫したユーザー体験を提供できる。Next.jsのルーターと連携するカスタムフックを作成し、特定の条件下でBackButtonを表示させ、クリックされたらrouter.back()を呼び出すように設定するのだ。

最後に、これらのMini Appを実際に運用する上での考慮事項を挙げる。決済の信頼性を確保するために、「べき等性」と「注文追跡」は非常に重要だ。createInvoiceLinkメソッドで生成される請求書のpayloadフィールドには、注文を識別するための一意で暗号学的に安全なランダムなIDを含めるべきだ。そして、このIDを持つ注文を、支払いリンクをユーザーに送る前に「保留中」としてデータベースに保存しておく。また、注文が実際に支払われたことを確認するためには、クライアントサイドのopenInvoiceコールバックだけに依存せず、別途Telegram Bot APIのウェブフックを設定し、pre_checkout_queryやsuccessful_paymentの更新を受け取って処理する必要がある。これにより、決済の信頼性を高め、注文の不履行を防ぐことができる。アプリケーションの初期化においては、Telegram.WebApp.ready()メソッドはReactアプリケーションが完全にマウントされてから呼び出すようにすることで、未スタイルのコンテンツが一時的に表示されたり、速度の遅いモバイル環境で画面が真っ白になったりする問題を回避できる。これらの考慮事項は、ユーザーに安定したサービスを提供し、長期的にMini Appを成功させるために不可欠な要素である。

関連コンテンツ

関連IT用語

関連ITニュース