👻

LINEミニアプリのServiceMessageを試してみた(Nextjs)

に公開

LINEミニアプリでサービスメッセージを送信する方法を検証しましたので備忘録的に纏めています。

送信に成功すると「LINEミニアプリ お知らせ」アカウントからメッセージを受信できます。

LINEミニアプリの公式から送信方法が記載されておりますので、そちらを参考に作成していきます。
https://developers.line.biz/ja/docs/line-mini-app/develop/service-messages/

※基本は審査後の認証済みアプリからのみ使用可能な機能にですが、テストユーザーに限っては
テスト環境で使用できます。

大きな流れは以下となります。
※今回事前準備は割愛しますが、もしご要望があればコメントください。

■事前準備
① LINE Developers Consoleでサービスメッセージのテンプレートを作成する。
② チャンネルIDとチャンネルシークレットを確認しておく

■開発(処理の流れ)
① ユーザーのアクセストークンを取得する
② チャンネルトークンを取得する
③ ①と②を元にサービス通知トークンを取得する
④ ③を元にテンプレートを指定してサービスメッセージを送信する

検証のため開発は分かりやすく「index.js」のみで実装しました。
本来はバックエンドとフロンドエンドで分ける必要がありますのでご注意ください。

まずはLINEミニアプリのスターターアプリをクローンしておきます。

 git clone https://github.com/line/line-liff-v2-starter.git

nextjsのsrcフォルダに移動します。

cd .\line-liff-v2-starter\src\nextjs\

nextjsをインストールして、ローカルサーバを起動します。

npm install next@latest
yarn dev

ルートフォルダに「.env.local」を新規作成して環境変数を設定します。

LIFF_ID='XXXXXXXXXXXXX' //LIFF URL開発用のhttps://miniapp.line.me/ 以降の文字列
NEXT_PUBLIC_LINE_MINIAPP_CHANNEL_ID='XXXXXXXXXXXXX' //チャンネルID
NEXT_PUBLIC_LINE_MINIAPP_CHANNEL_SECRET='XXXXXXXXXXXXX' //チャンネルシークレット

ここまででLINEミニアプリのスターターアプリが起動したかと思います。

このままローカル環境で進めたい所ですが、ローカル環境だとLINEログイン後の遷移先としてエンドポイントURLを設定しますが、httpsのみ対応しておりましたのでpackage.jsonを下記のように修正します。

  "scripts": {
    "dev": "next dev -p 9000 --experimental-https",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },

これでhttps://localhost:9000でアクセスできるようになるかと思います。

また、DeveloperConsoleよりエンドポイントを設定しておきます。

続いて、まずは適当にボタンを設定します。
index.jsの適当なところにボタンを配置。

<button onClick = {()=> servicemsEventClick()}>ボタン</button>

さらにservicemsEventClick関数を定義

 const servicemsEventClick =  async () =>{
    alert("テスト")
  }

ここまででボタンの配置と、ボタンをクリックした時のイベントを定義することができました。

ここから本題のサービスメッセージの送信を作っていきます。
まずは
「① ユーザーのアクセストークンを取得する」からいきます。


 //LINEミニアプリ ログイン処理
    //ログイン後の遷移はエンドポイントURL
    if (!liff.isLoggedIn()) {
      liff.login();
      return;
    }
    //ログイン後にユーザーのアクセストークを取得
    const liffaccessToken = liff.getAccessToken();
    console.log("LIFF Access Token:", liffaccessToken); //デバック用アクセストークンを確認用ログ

次に「②チャンネルトークンを取得」を実装します。

    //チャンネルトークンを取得関数定義
    const issueChannelAccessToken = async () => {
      const headers = {
        "Content-Type": "application/x-www-form-urlencoded",
      };  
      const body = `grant_type=client_credentials&client_id=${process.env.NEXT_PUBLIC_LINE_MINIAPP_CHANNEL_ID}&client_secret=${process.env.NEXT_PUBLIC_LINE_MINIAPP_CHANNEL_SECRET}`;
      console.log(process.env.NEXT_PUBLIC_LINE_MINIAPP_CHANNEL_ID); //デバック用_チャンネルIDを確認用ログ
      console.log(process.env.NEXT_PUBLIC_LINE_MINIAPP_CHANNEL_SECRET); //デバック用_セキュリティIDを確認用ログ

      //APIをPOSTしてチャンネルトークンを取得
      const response = await fetch("https://api.line.me/oauth2/v3/token", {
        method: "POST",
        headers,
        body,
      });
      const json = await response.json();
      console.log("Channel Access Token:", json);//デバック用_チャンネルトークン確認用ログ
      return json.access_token; //レスポンスデータからトークンのみを取得
    };

    //チャンネルトークンを取得
    const channelAccessToken = await issueChannelAccessToken();
    console.log("typeof:", typeof channelAccessToken);//デバック用_チャンネルトークン確認用ログ

次に「③サービスメッセージ通知トークン」を取得します。

     //サービスメッセージ通知トークン取得関数定義
    const issueServiceMessageNotificationToken = async () => {
    const response = await fetch("https://api.line.me/message/v3/notifier/token", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${channelAccessToken}`,//ヘッダーにチャンネルトークンを設定
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          liffAccessToken: liffaccessToken, //ユーザーのアクセストークンを設定
        }),
      });
      const json = await response.json();
      console.log("Notification Token:", json);
      return json;
    };
    //サービスメッセージ通知トークンを取得
    const { notificationToken } = await issueServiceMessageNotificationToken();
    console.log(notificationToken);//デバック用_サービスメッセージ通知トークン確認用ログ

最後にサービスメッセージを送信します。

    //サービスメッセージ送信処理定義
    const sendServiceMessage = async ({ templateName, params, notificationToken}) => {
      const response = await fetch("https://api.line.me/message/v3/notifier/send?target=service", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${channelAccessToken}`,//ヘッダーにチャンネルトークンを設定
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          templateName,
          parameters: params,
          notificationToken, //サービスメッセージ通知トークンを設定
        }),
      });
      const result = await response.json();
      console.log("Service Message Send Result:", result);
      return result;
    };
  
     //サービスメッセージを送信 
      await sendServiceMessage({
      templateName: 'restock_d_ja', //テンプレート名
      params: { 
        "price": "400円",
        "number": "1357",
        "address": "東京都新宿区新宿4-1-6",
        "btn1_url": "https://line.me",
        "btn2_url": "https://line.me",
        "btn3_url": "https://line.me",
        "btn4_url": "https://line.me",
        "reg_date": "2033/8/22 0:00",
        "shop_name": "ブラウン新宿店",
        "instock_date": "2033/8/22 0:00",
        "product_name": "Tシャツ"
      },
      notificationToken,
    });

これで画面上からボタンをクリックするとサービスメッセージが送信されるはずです。
送信されない場合はデバック用のログを確認してみてください。

少しでも参考になれば幸いです。

Discussion