LINEミニアプリ開発は、普通のWebアプリをLIFF SDKで包み、LINE Developersコンソールの「開発用・審査用・本番用」という3つの内部チャネルに載せ分ける作業です。この記事では2026年11月時点の公式ドキュメントにもとづき、チャネルの作成、環境ごとのLIFF IDの切り替え、サーバーでのトークン検証、サービスメッセージを送るコード、審査申請の準備までを順に示します。LIFF SDK旧版の利用制限など、2026年に入ってから変わった前提も解説の対象です。費用や導入の判断を先に知りたい場合は、LINEミニアプリの仕組みと審査・開発費用の解説から読むと全体像がつかめます。
まとめ:LINEミニアプリ開発は内部チャネル3つの切り替えと審査の準備で決まる
画面の作り方は通常のWebアプリと変わりません。差が出るのは、内部チャネルごとに別々のLIFF IDとチャネルアクセストークンを持つ点と、サービスメッセージや検索公開が認証審査の通過を前提にしている点です。
実装で押さえる順番は次のとおりです。まず環境変数でLIFF IDを切り替えるビルドを作り、サーバーはLIFFアクセストークンを検証してから15分有効のステートレスチャネルアクセストークンでAPIを呼びます。サービスメッセージは、送信のたびに返る新しい通知トークンを保存する設計が前提です。審査は通常1〜2週間かかるため、プロバイダー名とプライバシーポリシーの会社名をそろえ、テストシナリオを用意してから申請します。
LINEミニアプリ開発の全体像:チャネル作成から審査通過までの作業と期間
作業は「チャネルを作る」「開発用で作って試す」「審査に出す」「本番に反映する」の4段階です。最初の2段階は数日で動くものが作れますが、後半の2段階はLINEヤフーの審査待ちを含むため、リリース日から逆算して2〜3週間の余裕を見ておきます。
LINEミニアプリチャネルの作成:地域・プロバイダー・チャネル説明の決め方
チャネルはLINE Developersコンソールで、プロバイダーを選んで[新規チャネル作成]から[LINEミニアプリ]を選んで作ります。公式の「開発を始めよう」によると、サービス提供地域は日本・タイ・台湾から選び、複数の国で出すなら国ごとにチャネルを分けます。
後から直せない項目が2つあります。プロバイダーは作成後に別のプロバイダーへ移せず、ユーザーIDもプロバイダー単位で発行されます。受託で作る場合は、開発会社のプロバイダーではなくサービス事業主のプロバイダーで作るのが原則です。外部に開発を任せるときは、チャネル説明にサービス事業主名と開発担当企業名を書くようコンソールガイドが求めています。
開発用・審査用・本番用の内部チャネルとLIFF IDが3つに分かれる仕組み
コンソール上では1つのチャネルに見えますが、内部は3つに分かれています。設定の反映のされ方が違うため、表で整理します。
| 内部チャネル | ステータス | 見られる人 | 設定の反映 |
|---|---|---|---|
| 開発用 | 常に開発中 | 管理者・テスター | 設定した時点で即時 |
| 審査用 | 常に開発中 | 管理者・審査担当者 | 審査開始時に開発用からコピー |
| 本番用 | 常に公開中 | 管理者・利用者 | 公開時に開発用からコピー |
LIFF IDは内部チャネルごとに1つずつ発行され、LIFF URLは https://miniapp.line.me/{liffId} の形式です。liff.init() には、そのビルドを載せる内部チャネルのLIFF IDを渡すようコンソールガイドが指定しています。つまり同じソースから、LIFF IDだけを変えた3種類のビルドを作ることになります。
開発環境を作る:エンドポイントURLの設定とLIFF CLIでのローカル確認
コンソールの[ウェブアプリ設定]タブで、開発用と審査用それぞれのエンドポイントURLを指定します。LIFF SDKそのものの導入と初期化の基本はLIFFの仕組みと開発手順の記事で扱っているため、ここではミニアプリで追加になる作業に絞ります。
環境ごとにLIFF IDを切り替えるliff.initの書き方とビルドの設定例
LIFF IDはコードに直書きせず、ビルド時に差し込みます。次はViteを使う例で、.env.development・.env.review・.env.production の3ファイルに各内部チャネルのLIFF IDを書き、vite build --mode review のようにモードを指定してビルドし分けます。
// .env.review の中身(審査用の内部チャネルのLIFF ID)
// VITE_LIFF_ID=2000000000-AbCdEfGh
import liff from '@line/liff';
const liffId = import.meta.env.VITE_LIFF_ID;
export async function initMiniApp() {
await liff.init({ liffId });
// サーバーにはプロフィールではなくアクセストークンを渡す
const accessToken = liff.getAccessToken();
const res = await fetch('/api/reservations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + accessToken,
},
body: JSON.stringify({ slotId: 'slot-1030' }),
});
return res.json();
}
サーバー側も同じ考え方で、チャネルIDとチャネルシークレットを内部チャネルごとに環境変数で持ちます。フロントとサーバーで別々の内部チャネルを指していると、後述のトークン検証で必ず弾かれます。
ローカル開発をLIFFブラウザで確かめるLIFF CLIのserveとベーシック認証
手元のコードをLINEアプリ内で確かめるには、HTTPSで外からアクセスできるURLが必要です。LIFF CLI(npm install -g @line/liff-cli)の serve コマンドは、mkcertで作った証明書を使ってローカルサーバーをHTTPS化し、ngrokでの外部公開にも対応します。公式は「公開済みのLIFFアプリでは serve を実行しない」と注意しており、使用できる対象は開発用の内部チャネルだけです。ソースはGitHubのline/liff-cliで公開されています。
公開前の画面に関係者以外が入らないようにするには、エンドポイントURLにベーシック認証を掛けられます。ただし効くのはステータスが「審査前」「審査中」で、LIFFブラウザで開いたときだけです。「反映済み」になると使えないため、本番の会員限定画面はアプリ側の認証で守ります。
サーバー側を実装する:LIFFアクセストークン検証とステートレストークン発行
LINEミニアプリのサーバーは、フロントから届いたLIFFアクセストークンを信用する前に検証し、LINEのAPIを呼ぶときは内部チャネルのチャネルアクセストークンを使います。この2種類のトークンを取り違えないことが、サーバー実装の要点です。
liff.getAccessTokenのサーバー検証とclient_idの照合手順
LINEログインの v2.1 APIリファレンスにある GET https://api.line.me/oauth2/v2.1/verify にアクセストークンを渡すと、有効なら client_id・scope・expires_in が返り、期限切れや取り消し済みなら400が返ります。client_id は発行元のチャネルIDなので、自分の内部チャネルのIDと一致するかを照合し、他のチャネル向けに発行されたトークンを受け付けないようにします。
クライアントが送ってきたユーザーIDをそのまま使う実装が危ない理由と、IDトークンを使う検証の比較はLINEミニアプリの危険性を実装目線で整理した記事で扱っています。
15分有効のステートレスチャネルアクセストークンを送信のたびに発行する
チャネルアクセストークンの公式解説によると、ステートレスチャネルアクセストークンは15分だけ有効で、発行数に上限がなく、取り消しはできません。LINEミニアプリのサービスメッセージでは長期トークンとv2.1トークンが使えず、ステートレストークンが推奨です。
発行は Messaging APIリファレンスの POST https://api.line.me/oauth2/v3/token に、grant_type=client_credentials とチャネルID・チャネルシークレットをフォーム形式で送ります。応答の expires_in は900秒です。キャッシュして使い回すより、送信処理のたびに発行するほうが期限切れの分岐を書かずに済みます。
サービスメッセージを送る:通知トークンの発行・保存・後続送信のコード
サービスメッセージは、予約の完了や注文の受付など、利用者の操作に対する確認として送るメッセージです。使えるのは認証済ミニアプリだけで、未認証の間は開発用の内部チャネルでのテストに限られます。
テンプレートの追加と名前の付け方:最大20個・言語タグ付き30文字以内
コンソールの「サービスメッセージテンプレート」タブで、用意された型からテンプレートを選んで追加します。公式の「サービスメッセージを送信する」によると、追加できるのはチャネルごとに20個までで、使うにはLINEヤフーの審査を通す必要があります。値下げやクーポン、新商品の案内など、広告目的の送信は禁止です。
APIで指定する templateName は「テンプレート名_言語タグ」の形式で最大30文字、言語タグは ja・en・zh-TW・th・id・ko の6種類です。審査前のテンプレートは、AdminかTester権限を持つ開発者に開発用チャネルから送るときにだけ使えます。
通知トークンの発行から初回送信・後続送信までのNode.js実装例
流れはLINEミニアプリ APIリファレンスのとおり、LIFFアクセストークンからサービス通知トークンを発行し、そのトークンでメッセージを送ります。次はNode.js 20以降の組み込み fetch で書いた例です。
// 内部チャネルごとに値を切り替える
const CHANNEL_ID = process.env.MINIAPP_CHANNEL_ID;
const CHANNEL_SECRET = process.env.MINIAPP_CHANNEL_SECRET;
async function postJson(url, token, body) {
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + token },
body: JSON.stringify(body),
});
if (!res.ok) throw new Error(url + ' ' + res.status);
return res.json();
}
// 1. LIFFアクセストークンを検証し、自分のチャネル向けか確かめる
async function verifyLiffToken(liffAccessToken) {
const res = await fetch('https://api.line.me/oauth2/v2.1/verify?access_token='
+ encodeURIComponent(liffAccessToken));
const body = await res.json();
if (!res.ok || body.client_id !== CHANNEL_ID) throw new Error('invalid LIFF token');
}
// 2. ステートレスチャネルアクセストークン(15分有効)を発行する
async function issueChannelToken() {
const res = await fetch('https://api.line.me/oauth2/v3/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: CHANNEL_ID,
client_secret: CHANNEL_SECRET,
}),
});
if (!res.ok) throw new Error('token ' + res.status);
return (await res.json()).access_token;
}
// 3. 通知トークンを発行して初回のサービスメッセージを送る
export async function sendFirstMessage(liffAccessToken, params) {
await verifyLiffToken(liffAccessToken);
const channelToken = await issueChannelToken();
const issued = await postJson(
'https://api.line.me/message/v3/notifier/token',
channelToken, { liffAccessToken });
const sent = await postJson(
'https://api.line.me/message/v3/notifier/send?target=service',
channelToken, {
templateName: 'reservation_confirmation_ja', // 追加したテンプレート名+言語タグ
params, // 変数名はテンプレートの定義に合わせる
notificationToken: issued.notificationToken,
});
// 送信のたびに返る新しいトークンを保存し、後続の送信に使う
return {
sessionId: sent.sessionId,
notificationToken: sent.notificationToken,
remainingCount: sent.remainingCount,
};
}
後続の送信では、保存した notificationToken を使って同じ送信APIを呼び、応答の新しいトークンで保存値を上書きします。通知トークンは発行から1年有効で、1つの操作につき送れるのは最大5回です。応答の remainingCount と expiresIn が0なら、送信はされたもののトークンは更新されていないので、その操作の通知はそこで打ち止めとして扱います。
実装でよく踏むのは2点です。同じLIFFアクセストークンで短時間に通知トークンの発行を繰り返すと400が返り、利用者がLIFFアプリを閉じた後の発行は401になります。予約の確定ボタンを押した直後、画面が開いている間に発行まで済ませる設計にしてください。
審査申請の準備:差し戻しを避ける登録情報・テストシナリオ・性能基準
認証済ミニアプリになるまで、サービスメッセージもLINE内の検索公開も使えません。審査は技術より登録情報と説明の不足で止まりやすいため、申請前の確認に時間を割きます。
審査前の確認:プロバイダー名とプライバシーポリシーの会社名をそろえる
公式の「審査を依頼する」は、申請前の確認事項として、プロバイダー名がサービス提供者と同じであること、プライバシーポリシーで利用者情報を取得する会社がプロバイダー名と同じであること、審査用と本番用のLIFF URLが同じサービスを指していることを挙げています。
申請の操作を行う場所は[審査申請]タブです。ベーシック認証を掛けているならユーザー名とパスワードを、予約・支払・注文を含むサービスならテスト用のアカウントや店舗といったテストシナリオを「審査のための補足資料」に書きます。性能面ではパフォーマンスガイドラインがLighthouseのPerformance 50以上を推奨しており、LINEログインが走らない状態の本番環境で測るという指定です。共有ボタンを置く場合は、カスタムアクションボタンの実装ガイドにあるとおり、共有メッセージをFlex Messageのバブルで作ります。
審査期間1〜2週間と初回承認後30日以内に行う検索公開の操作手順
審査は通常1〜2週間で、却下されると再申請と再審査にさらに数日かかります。完了日は指定できません。複数のミニアプリを出す場合は、まず1つを通してから残りを申請するよう公式が勧めています。
初めての承認後はステータスが自動で「反映済み」になり、LINE内で検索できるようにするには[検索可能にする]を押します。押さずに30日が過ぎると、31日目の午前9時(日本時間)に自動で検索可能になります。公開中のミニアプリを更新したときは、承認後に[変更内容を公開する]を押すまで本番には反映されません。
開発でつまずく箇所:LIFF SDKの利用制限とトークン・ID・認証の取り違え
ここまでの手順どおりに作っても、公開後に動かなくなる原因は外から来ます。2026年秋の時点で確認しておきたいのは次の2点です。
2026年11月24日頃に始まるLIFF SDK旧版の利用制限と更新の手順
LIFFのリリースノートによると、v2.20.0〜v2.31.0は非推奨となり、2026年11月24日頃に利用制限が実施される予定です。最新は2026年10月7日公開のv2.31.2で、v2.31.1以降への更新が必要です。CDNのエッジパスで読み込んでいれば自動で更新されますが、npmパッケージやCDNの固定パスで固定している場合は手で上げる必要があります。
npmで入れているなら npm install @line/[email protected] で更新し、開発用→審査用→本番用の順に入れ替えます。影響の確かめ方はLIFF SDKの脆弱性と2.31.1への更新手順の記事にまとめています。
開発用のトークンを本番で使うなど内部チャネルの取り違えで起きる不具合
コンソールガイドは、審査用や本番用から送るサービスメッセージに開発用のチャネルアクセストークンを使わないよう明記しています。環境変数の設定漏れで開発用のチャネルIDとシークレットが本番に残ると、前出のコードでは client_id の照合で全件の検証が通らなくなる仕組みです。リリース手順に、内部チャネルごとの環境変数を突き合わせる確認を1行入れておくと防げます。
もう1つは同意画面です。日本の新規チャネルでは2026年1月から「チャネル同意の簡略化」が必須になり、未認証の間はこの設定が本番用に反映されません。認証の前後で同意の出方が変わる前提で、権限を断られたときの画面分岐を用意しておきます。
自社で開発するか外部に任せるかの判断:内製で進めてよい条件と見送る場面
LINEミニアプリはWebの技術で作れるため、内製の敷居は低く見えます。判断を分けるのは画面の難しさではなく、サーバー側のトークン管理と審査対応を誰が持つかです。
内製で進めてよい条件:Webアプリとサーバー実装を同じチームで持てる場合
既存のWebアプリをミニアプリ化する案件で、フロントとサーバーを同じチームが保守しているなら、内製で進めて構いません。追加で書くのは、本記事のLIFF IDの切り替え、トークン検証、サービスメッセージ送信の3か所で、既存の会員認証に手を入れない範囲に収まるからです。
この場合も、プロバイダーをサービス事業主の名義で作ることと、LIFF SDKのリリースノートを誰が追うかは先に決めておきます。
外部に任せるべき場面:既存会員基盤との統合と審査対応を同時に抱える場合
既存の会員IDとLINEのユーザーIDを統合する、POSや予約台帳と双方向に連携する、複数店舗やブランドでチャネルを分ける、といった要件が重なる場合は、内製を見送る判断を勧めます。プロバイダー構成を後から変えられない以上、最初の設計の誤りはチャネルの作り直しと利用者IDの移行になり、手戻りの規模が大きくなるためです。
この段階で相談先を探すなら、LINEミニアプリ開発会社の選び方で確認点を整理したうえで、一創のLINEミニアプリ開発のように審査対応と既存システム連携をまとめて引き受ける会社に見積もりを取ると比較しやすくなります。
よくある質問
LINEミニアプリの開発について、検索の多い質問に答えます。
LINEミニアプリの開発にはどの言語を使いますか?
画面はHTML・CSS・JavaScriptで作るWebアプリで、ReactやVueなどのフレームワークも使えます。LIFF SDKはnpmパッケージの @line/liff かCDNで読み込みます。サーバーはトークンの検証とLINEのAPI呼び出しができればよいので、Node.js・PHP・Python・Javaなど言語は問いません。ネイティブアプリのようにSwiftやKotlinを書く必要はなく、iOSとAndroidで同じコードが動きます。
LINEミニアプリは個人でも開発できますか?
公式の「開発を始めよう」には、LINEミニアプリポリシーで定める利用対象者であれば誰でもチャネルを作成できると書かれています。開発用の内部チャネルで動かして試すところまでは個人でも実施可能です。認証審査ではプロバイダー名とプライバシーポリシーの取得会社をそろえる必要があるため、事業として公開するなら事業者名義のプロバイダーで作り直さずに済むよう、最初から名義を決めておきます。
未認証のLINEミニアプリでもサービスメッセージを送れますか?
本番の利用者には送れません。未認証ミニアプリでサービスメッセージを試せるのは開発用の内部チャネルだけで、送信先もAdminかTester権限を持つ開発者に限られます。テンプレート自体にもLINEヤフーの審査があり、本番の利用者に送れるのは、認証審査とテンプレートの審査をどちらも通過した後です。
LINEミニアプリの開発費用はどのくらいかかりますか?
既存のWebアプリを包むだけか、会員基盤や予約・決済と連携するかで大きく変わります。パッケージを使う場合と委託開発する場合の目安、公開後にかかる配信料や保守費用の内訳は、LINEミニアプリの審査と開発費用の解説で整理しています。本記事の範囲では、審査期間の1〜2週間と、LIFF SDKの更新に追随する保守工数を見積もりに含めておくことが要点です。
審査中に開発用チャネルの設定を変えると公開中のアプリに影響しますか?
影響しません。審査用と本番用の内部チャネルには、審査開始時や公開時に開発用の内容がコピーされる仕組みです。公開中のミニアプリを更新するときも、再審査を通過して[変更内容を公開する]を押すまでは本番に反映されないため、開発用では次の版の作業を続けられます。審査が始まった後は申請の取り消しや情報の変更ができない点には注意してください。
関連記事
- LINE予約システムを自作する:LIFFとMessaging APIの構成・コード・料金【2026年10月】:LIFFで予約画面を作る具体例
- LINE Messaging APIとは?できること・2026年10月改定後の料金と実装手順:友だち向けのプッシュ配信と料金
- 予約管理システムのLINE連携|4つの実装方式と通知コストで決める選び方:ミニアプリ以外の連携方式との比較
- LINE Notify終了後の移行実装|Messaging APIへの置き換え手順と通知コスト試算:社内向け通知の実装