Laravel

Laravel + LIFF + LINE Messaging APIを使ってメッセージを送る

以前に「LIFF」アプリに関する記事を書きました。

しかし、大体のLIFFアプリを実装する場合にフロントエンドだけでなく、バックエンド側でメッセージを送ったりLINEユーザーと自分の開発したサービスと連携するようになります。
例えばショップの公式アカウントからLIFFアプリにアクセスしてもらい、そこでユーザーはボタンを押しただけでLINEで使用している名前などは省いてアンケートに登録することが出来ます。
ただしLINE公式はLIFFアプリで取得したプロフィール情報を直接バックエンドに送らず、トークンを元にバックエンド側でプロフィール情報を取得すると推奨しております。
今回はその実装例をまとめたいと思います。

環境

  • Lumen(Laravel) 9.1
  • line-bot-sdk 7.6
  • guzzle 7.5

今回の要件例

目的: LIFFアプリでアンケートを送信すると、LINEが返事をする。

処理の流れ:

  • [フロントエンド] LIFFアプリでトークン取得する
  • [フロントエンド] トークンをバックエンド側に送る
  • [バックエンド] トークンからLINEユーザーのプロフィールを取得する
  • [バックエンド] 送られたLINEユーザーに対して返答を送信する

LINE Messaging APIを使用出来るように設定する

LIFFアプリは以前に設定したものとして、今回は追加として「LINE Messaging API」の設定を行います。
まずは「LINE Developers」にログインします。

https://developers.line.biz/ja/

ログインすると「プロバイダー」を選択して、「チャネル設定」で「新規チャネル作成」を選択します。

表示されるダイアログで「Messaging API」を選択します。

チャネル作成で必要な各項目を入力して、チャネルの作成を完了します。

新規チャネルを登録後に、「Messaging API設定」タブを選択して、下の方にスクロールすると「チャネルアクセストークン」の項目があるのでチャネルアクセストークンを発行します。

また同様に「チャネル基本設定」から「チャネルシークレット」を確認します。

これらの「チャネル基本設定」と「チャネルシークレット」は、「LINE Messaging API」で使用しますので控えておくようにします。
またメッセージ送信などを行った後のコールバックURLの設定も可能ですが、こちらはまた何かの時に記述しようと思います。

LINE ユーザープロフィールを取得する

まずは「guzzlehttp/guzzle」をインストールします。
これはPHPで他のサーバーにAPIでアクセスするためのライブラリとなります。
トークンからプロフィールを取得する場合、後述する「line-bot-sdk」では出来ないため直接URLにアクセスするようになります。

$ composer require guzzlehttp/guzzle

トークンからプロフィールを取得するAPIは以下に公式ドキュメントに記載しております。

https://developers.line.biz/ja/reference/line-login/#profile

これを元にプロフィールを取得するクラス等を作成します。
LINEユーザー情報のクラスを作成します。

<?php

namespace App\Users;

/**
 * LINE ユーザープロフィール
 */
class LineUserProfile
{
    // ユーザーId
    public string $userId;

    // LINE ユーザー表示名
    public string $displayName;

    // ステータスメッセージ
    public string|null $statusMessage;

    // プロフィール写真URL
    public string $pictureUrl;

}

その後に以下のように、LINE APIを使用するマネージャークラスを作成します。

<?php

namespace App\Manager;

use App\Models\LineUserProfile;
use Illuminate\Support\Facades\Http;

/**
 * LINE の Messaging APIに関する処理のマネージャー
 */
class LineApiManager
{
    // ユーザーが取得したトークン
    private string $userToken;

    const LINE_API_BASE_URL = 'https://api.line.me/v2/';

    /**
     * 初期化
     * @param string $userToken
     */
    public function __construct(string $userToken)
    {
        $this->userToken = $userToken;
    }


    /**
     * ユーザートークンからLINE APIのプロフィールを取得する
     * @return LineUserProfile | null
     */
    public function getUserProfile() :LineUserProfile | null
    {
        // LINEのユーザープロフィールを取得する
        $response = Http::withToken($this->userToken)
            ->get(self::LINE_API_BASE_URL . "profile", [
                'name' => 'Taylor',
                'page' => 1,
            ]);

        // 取得に失敗した場合は、nullを返却する
        if (!$response) {
            return null;
        }

        // レスポンスをクラスに設定
        $res = $response->object();

        // 型変換に失敗した場合は、nullを返却する
        if (!property_exists($res, 'userId')
            || !property_exists($res, 'displayName')) {
            return null;
        }


        // Make response class
        $lineUserProfile = new LineUserProfile();
        $lineUserProfile->userId = $res->userId;
        $lineUserProfile->displayName = $res->displayName;
        if (property_exists($res, 'statusMessage')) {
            $lineUserProfile->statusMessage = $res->statusMessage;
        } else {
            $lineUserProfile->statusMessage = null;
        }
        if (property_exists($res, 'pictureUrl')) {
            $lineUserProfile->pictureUrl = $res->pictureUrl;
        }
        return $lineUserProfile;
    }

}

使用する場合は、以下のように使用します。

$lineAccessToken = {LIFFで取得したアクセストークン};
$lineApiManager = new LineApiManager($lineAccessToken);
$lineUserProfile = $lineApiManager->getUserProfile();

これにより「$lineUserProfile」に、取得したLINEユーザーの情報を取得することが出来ます。
ただし「ユーザーID」について気をつける事は、LIFFアプリが異なるもので取得したトークンは別のユーザーIdとなります。
これにより公式アプリなどを跨いで管理するのは考える必要があります。

LINEにメッセージで返信する

次にLINEのアクセストークンから取得したユーザーに対してLINEからメッセージを送るようにします。
まずはPHPのLINE Bot用のSDKである「linecorp/line-bot-sdk」をインストールします。

$ composer require linecorp/line-bot-sdk

「.env」に「LINE Developer」で控えておいた「チャネルアクセストークン」と「チャネルシークレット」を記述します。

LINE_TOKEN_KEY={チャネルアクセストークン}
LINE_SECRET={チャネルシークレット}

以下のようにLINE bot を使いやすいようにマネージャーを作成します。

<?php

namespace App\Manager;

use LINE\LINEBot;
use LINE\LINEBot\HTTPClient\CurlHTTPClient;
use LINE\LINEBot\MessageBuilder\TextMessageBuilder;

/**
 * LINE BOT用のマネージャー
 */
class LineBotManager
{
    private LINEBot $bot;

    /**
     * 初期化
     * @param string $accessToken
     * @param string $secret
     */
    public function __construct(string $accessToken, string $secret)
    {
        $httpClient = new CurlHTTPClient($accessToken);
        $this->bot = new LINEBot($httpClient, ["channelSecret" => $secret]);
    }


    /**
     * メッセージ
     * @param $to
     * @param $message
     * @return LINEBot\Response
     */
    public function sendMessage($to, $message): LINEBot\Response
    {
        $textMessageBuilder = new TextMessageBuilder($message);
        return $this->bot->pushMessage($to, $textMessageBuilder);
    }

}

以下使用例となります。
「ユーザーId」は上記のプロフィールしたユーザーIdでお送りする事が出来ます。

$lineUserId = {ユーザーId};
$message = "送るメッセージ内容";
$lineBotManager = new LineBotManager(env("LINE_TOKEN_KEY"), env("LINE_SECRET"));
$response = $lineBotManager->sendMessage($lineUserId, $message);

一旦はLIFFアプリからバックエンドでメッセージを返却剃る仕組みが出来ました。
他にもユーザーがLINEの公式アカウントにメッセージを送った場合に、コールバックにLINEからアクセスイベントが発生剃る場合などもあります。
また引き続きこのあたりもまとめていこうとおもいます。