BLOG
ブログ

ブログ

LINE Message APIとNext.jsで遊んでみた!

社員の日常

こんにちは!システム部の西田です!

今回で3度目のブログ執筆になるのですが、過去私が書いたブログ記事はどれも撮影に関する内容でした。
ドローン空撮のメリット・飛行許可申請・注意点についてまとめました!
ドクターインタビューに行ってきました!

しかし今回はシステム部らしい記事を書いていくことにしました…!!

といっても、そんな大袈裟なことはできないので…
今回はLINE Message API を使ってちょっと遊んでみたっていう内容の記事です。
私自身初めて触りますし、色々と調べながらやっていきますのであんまり参考にはならないかも。
場合によってはシリーズ化もあるかもなので、よろしくお願いします!

ではいきます!

何を作るか

まずざっくりと完成系をイメージします…

システム上で管理者とユーザーがメッセージのやり取りをするようなシチュエーションで、管理者側はwebの管理画面から、ユーザーはLINEで公式アカウントとやり取りをするような、そんな感じです。

弊社が開発した病院採用管理システムをイメージしてそこに当てはめますと、、

・管理者側

→ 病院の採用担当者
PCでwebシステムに入って、応募者の様々なステータスや履歴を見ながらメッセージを送ります。そのため、管理画面上から。

・ユーザー

→ 応募者
応募者は管理画面からメッセージ送信以外そんなにやることがないので、毎回ログインしなくても済むようにLINEからメッセージを送る。

って感じですね。

そんな仕様が本当に必要な時が来るかなんてそんなことは関係ないんです!

ただの思いつきですが、やっていきます。

LINE Message APIとは

その名の通り、LINEのメッセージに関するAPIたちのことですね。
公式アカウントと絡めたりして色々できるようです。

公式サイトから引用しますと、「Messaging APIは、あなたのサービスとLINEユーザーの双方向コミュニケーションを可能にする機能です。」とのこと。
なんかよくわからないですね。

まずはLINE message APIでできることを公式サイトを見ながら確認していきたいと思います。
LINEに関する様々なAPIが用意されているようです。

ここで問題発生です。

ドキュメントを読んでいて気づいたのですが、該当ユーザーにメッセージを送信するAPIは用意されているが、メッセージ履歴を取得するAPIはなさそうなのです。
それもそうか、、LINEの履歴ってすごく長いからデータ量とかもすごそうですもんね、、

私の理想は早くも砕け散ったのでした、、

と思ったのですが、色々ネットで調べたりchat-gpt大先生に泣きついてみたところ、公式LINEにメッセージが送信されるたびに呼ばれるwebhookを使うことで、メッセージをデータベースなどに保存しておけば同様のことができそうな予感…!

なるほど!大変そうだ!!

ということで今回は手始めにメッセージを送るところだけやっていこうと思います!!

使用する技術スタック的な紹介

  • next.js
  • LINE message API
  • react-chat-elements
  • vercel ?

フロントは慣れているNext.jsを使用します。
というか他に私が触れるものがないです。笑

チャットの見た目は1からcssで作ってもいいのですが、なんかいい感じのuiライブラリないかなと思って探したところ、react-chat-elements というのがよさそうだったので、これを使います。
王道uiライブラリのマテリアルUIとかaunt designとかにもありそうだったけど、なんかいい感じのがなかったですね…

vercelはまぁ、もしデプロイすることがあったらということで…

ではnext.jsのプロジェクト作成からやっていきます。
–ts をつけてtypescriptで作成していきます。

npx create-next-app@latest --ts
見た目作成

まずはreact-chat-elementsで見た目を適当に作ります。

参考は公式github公式ドキュメント参照です。

公式の手筈通りに、インストールします。

npm install react-chat-elements --save

LINE風メッセージのやり取りには MessageList コンポーネントが使えそうですね。

ただ、公式の使い方を見てコピペしてもタイプエラーが大量に、、、

エラー文章と公式ドキュメントを見比べつつ、必要な値を適当に設定していきます。

<MessageList
    className='message-list'
    lockable={true}
    toBottomHeight={'100%'}
    referance={{
      test: ""
    }}
    dataSource={[
    {
      id: "1",
      title: "たなか たけし",
      position: 'left',
      type: 'text',
      text: 'こんにちは 私はたなかです',
      focus: false,
      date: new Date(2024, 8, 16, 10, 10),
      dateString: "2024年10月24日10時24分",
      titleColor: "black",
      forwarded: false,
      replyButton: false,
      removeButton: false,
      status: "read",
      notch: true,
      retracted: false,
      avatar: "https://placehold.jp/150x150.png",
    },
    {
      id: "1",
      title: "さとう じろう",
      position: 'right',
      type: 'text',
      text: 'こんにちは 私もさとうです',
      focus: false,
      date: new Date(2024, 8, 16, 10, 10),
      dateString: "2024年10月24日10時24分",
      titleColor: "black",
      forwarded: false,
      replyButton: false,
      removeButton: false,
      status: "sent",
      notch: true,
      retracted: false,
      avatar: "https://placehold.jp/150x150.png",
    },
  ]}
/>

dataSourceの中身はmessageboxコンポーネントに準じているっぽいので、そちらも見ながらひとまず適当に値を入れていきます。
なんかそれっぽくなりましたね!

ちょっとだけスタイルを加えて調整します。

といってもwidthとheightを調整して背景色指定して中央寄せにするだけです。
背景はLINEのテーマカラーにしてみました。

ここらへんの適当さはご容赦ください…

そして、入力要素のコンポーネントもあったのでとりあえずつけてみます。

<Input
  referance={inputReferance}
  placeholder='Aa'
  multiline={true}
  value=""
  rightButtons={<Button color='white' backgroundColor='black' text='送信' />}
  maxHeight={50}
/>

はい、こんな感じになりました。
なんとなく雰囲気出ました

では静的なひとまず見た目作成はこれで終了で、次からいよいよLINEの設定に入っていきます。

LINE公式アカウント作成

まず初めに、LINE公式アカウントを作成します。
LINE公式アカウントとググって出てくる公式サイトから作成できます。

LINEアカウントまたはメールアドレスで作成ができるとのこと。
今回はメールアドレスから作成することにします。

メールに登録用リンクが届くので、名前とパスワードを入力して登録します。

その後電話番号認証でSMSが届くので入力すると、各種情報入力画面になるので、入力していきます。

はい、ということでLINE公式アカウントが作成できました!!

「LINE Official  Account Managerへ」から管理画面に入れます。
今作った公式LINEを友達追加してみな!という案内があったので、QRを読み込むと、、

公式アカウントができていることを確認できると思います!

友達追加すると、自動的なメッセージも送られてきますね。

LINE Message APIの設定

LINE Messaging APIでググって出てくる公式サイトにアクセスします。

「いますぐ始めよう」から始めます。

先ほど公式アカウントを同じブラウザで作成してログイン状態だったので、LINEのログインは不要で勝手にログインされました。

開発者名とメールアドレスを入力し、アカウントを作成します!!

LINE Developersの管理画面に入ることができました。

ここで、先ほどの公式LINE管理画面から「Message apiを利用する」設定しておきましょう。

画面右上の「設定」から、「Message API」に進みます。

プロバイダー名を入力し、「同意する」です。

これで一通りの設定が完了しました。

この辺の設定などは公式サイトが分かりやすくて間違いないと思うので、参考にしてください。

Next.jsからメッセージを送信してみる

ではいよいよNextjsから実際にメッセージ送れるかを試してみます!

LINE message apiのドキュメントを読んでみますと…

なるほど、メッセージを送るには下記のapiを使用するとのこと

POST https://api.line.me/v2/bot/message/push

リクエストに必要な値は下記の通り

リクエストヘッダー

  • 必須 Content-Type  application/json
  • 必須 Authorization Bearer {channel access token}
  • 任意 X-Line-Retry-Key

リクエストボディ

  • 必須 to
  • 必須 messages
  • 任意 notificationDisabled
  • 任意 customAggregationUnits

ひとまず今回の目的はメッセージの送信なので、一旦必須項目だけでやってみます。

チャンネルアクセストークンの取得

では早速Next.jsでの実装に進みたいのですが、その前にAuthorization に含める、channel access token なるものを取得しなくてはなりません。

LINE developersの管理画面から、先ほど登録したチャンネルに進みます。

Message API設定のタブを選び

一番下の「チャンネルアクセストークン」から、発行します。

ではこれで材料は揃ったので、Next.jsに行きましょう!!

Next.jsの実装

ネットワークの通信には、お馴染みのaxiosを使用します。

npm install axios --save

先ほどのチャンネルアクセストークンはenvファイルで定数化しておきます
.envファイルに下記のように設定

NEXT_PUBLIC_LINE_CHANNEL_ACCESS_TOKEN=your_access_token

メッセージ送信に関する箇所はカスタムhook化しておこうと思います。
src/hooks/useSendLineMessage.tsx

import { useState } from 'react';
import axios from 'axios';

export const useSendLineMessage = () => {
    const [loading, setLoading] = useState(false);
    const [response, setResponse] = useState(null);
    const [error, setError] = useState(null);

    const sendMessage = async (message: string, userId: string) => {
        setLoading(true);
        setError(null);

        axios.post('/api/lineMessage', {
            userId,
            message
        })
            .then(response => {
                setResponse(response.data);
            })
            .catch(error => {
                setError(error);
            })
            .finally(() => {
                setLoading(false);
            });
    };

    return { sendMessage, loading, response, error };
};

ここでpostしている先は next.jsのAPI Routesです。
下記のように作成します。
src/pages/api/lineMessage.ts

import type { NextApiRequest, NextApiResponse } from 'next';
import axios from 'axios';
type Data = {
    success: boolean;
    data?: any;
    error?: string;
};
export default async function handler(
    req: NextApiRequest,
    res: NextApiResponse<Data>
) {
    if (req.method !== 'POST') {
        return res.status(405).json({ success: false, error: 'POSTじゃない!' });
    }
    const { message, userId } = req.body;
    if (!message || !userId) {
        return res.status(400).json({ success: false, error: 'メッセージかUserIDがない!' });
    }
    try {
        const response = await axios.post(
            'https://api.line.me/v2/bot/message/push',
            {
                to: userId,
                messages: [
                    {
                        type: 'text',
                        text: message,
                    },
                ],
            },
            {
                headers: {
                    'Content-Type': 'application/json',
                    Authorization: `Bearer ${process.env.NEXT_PUBLIC_LINE_CHANNEL_ACCESS_TOKEN}`,
                },
            }
        );
        res.status(200).json({ success: true, data: response.data });
    } catch (error: any) {
        res.status(500).json({ success: false, error: error.message });
    }
}

エラーハンドリングとかの部分はおいおいやっていきますので、ひとまずこれで…

そして、そのhookを使用するようにします。

先ほど静的に作成したメッセージリストの部分は一時的に削除しておき(せっかく作ったけど…)、入力欄だけにしておきます。

メッセージ送信先のLINEのidはとりあえずベタがきで入れておくことにしましょう。

import React, { useState } from 'react';
import styles from '../styles/style.module.scss';

// hooks
import { useSendLineMessage } from "@/hooks/useSendLineMessage";

// RCE CSS
import 'react-chat-elements/dist/main.css'
// MessageBox component
import { MessageList, Input, Button } from 'react-chat-elements';

export default function Home() {
  const inputReferance = React.createRef();
  const [inputText, setInputText] = useState('');
  const [message, setMessage] = useState('');
  const [userId, setUserId] = useState('U0f66~~');
  const { sendMessage, loading, response, error } = useSendLineMessage(); // フックを利用

  const handleSendMessage = async () => {
    if (!inputText) {
      alert('User IDとメッセージを入力してください');
      return;
    }
    await sendMessage(inputText, userId); // メッセージ送信
  };

  return (
    <div className={styles.container}>
      <div></div>
      <Input
        referance={inputReferance}
        placeholder='Aa'
        multiline={true}
        value=""
        rightButtons={
          <Button
            color='white'
            backgroundColor='black'
            text='送信'
            onClick={(e) => {
              handleSendMessage();
            }}
          />
        }
        maxHeight={50}
        onChange={(e) => setInputText(e.target.value)}
      />
    </div>
  );
}

一点、注意点です。

ここで使用するユーザーIDなのですが、LINEのアプリ上で確認できるユーザーIDとは異なります。
本来であればwebhookなどを利用してユーザーが公式LINEを追加した時などに取得できるものなのですが、今回はそこまではしません。

なので、普段私が使っているアカウントのIDを使用することにします。
こちらの公式ページ内の「開発者が自分自身のユーザーIDを取得する」で取得します。

さらに詳細はこちら

ビジネスアカウントにLINEアカウントを連携させることで、連携させたそのアカウントのユーザーIDを管理画面から取得することができます。

アカウント連携後、LINE Developers からチャンネル基本設定をみると「あなたのユーザーID」があるかと思います。

これをコピペして、ひとまずユーザーIDにベタがきしちゃいましょう。

ではでは、ついにテスト送信です。

いざ送信!!

送信できました!!!!

無事にnext.jsからLINEでメッセージ送信することができました!

あとがき

いやー私自身が未熟者ゆえ、メッセージ送信するだけでなかなか大変でした。

弊社のサービスでこれらを使うことはあまりなさそうですが、普段使っているLINEで遊べるのは楽しいですね。

本当はnext.jsの画面上にLINEのやり取りを表示させるところまで行きたかったのですが、今回はここまでにしておきましょう。

今回はパート1として、また2回目以降でLINE message APIを使って遊んでみようと思います!

ではまた次回の記事でお会いしましょう!

さよなら!!