【開発者ブログ】LINE Messaging APIをcurl方式で実装してみた話と、リッチメッセージ仕様の注意点

こんにちは、開発部の久保見です。

今回は、前回ご紹介した LINE Messaging API 実装の第2弾として、SDKを使わず、curl形式でメッセージ送信を行う方法を試してみました。

前回の記事では SDK を用いた実装をご紹介しましたが、調べていく中でMessaging API は curl でも問題なく実装できることが分かり、あらためて検証しています。

また、API経由で LINE公式アカウントの「リッチメッセージ(imagemap)」を送信する際に、仕様上かなりクセがありハマったポイントがあったため、今回はその点も含めてまとめておきます。

この記事の要点
  • LINE Messaging API を SDKを使わず curl方式で実装する方法を検証
  • テキスト・画像・imagemap(リッチ系メッセージ)の 基本的な送信例を紹介
  • imagemap送信では baseUrlの指定方法や画像配置ルールに強いクセがある
  • 特に 「ディレクトリ指定」「5サイズ画像」「拡張子なし」 の仕様がハマりどころ
  • リッチメッセージ用画像を リサイズ+自動生成する実装例を掲載
  • SDK方式とcurl方式の両方を試し、用途に応じた使い分けの感触を整理

前回の記事はこちら

1. 基本的な送信方法(テキスト)

まずは最もシンプルなテキスト送信です。

構成自体は非常に単純で、特にクセはありません。

$channelAccessToken = 'YOUR_CHANNEL_ACCESS_TOKEN'; //チャネルアクセストークン
$userId = 'Uxxxxxxxxxxxxxxxxxxxx'; //ユーザーID

$message = [
    'to' => $userId,
    'messages' => [
        [
            'type' => 'text',
            'text' => 'こんにちは!テストメッセージです'
        ]
    ]
];

$ch = curl_init('https://api.line.me/v2/bot/message/push');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: Bearer ' . $channelAccessToken
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message));

$result = curl_exec($ch);
curl_close($ch);

実際にコードを実行すると、LINE上ではこのようにテキストメッセージが届きます。

API経由で送信した内容が、そのままトーク画面に反映されていることが確認できました。

SDKを使わなくても、エンドポイント+Authorizationヘッダー+JSONだけで問題なく送信できます。

2. 画像メッセージ送信

画像送信も、基本構造はテキストと同じでmessages 内の type を image に変更するだけです。

$message = [
    'to' => $userId,
    'messages' => [
        [
            'type' => 'image',
            'originalContentUrl' => 'https://example.com/img/original.jpg',
            'previewImageUrl' => 'https://example.com/img/preview.jpg'
        ]
    ]
];

ここも特にクセはなく、直感的に実装できます。

3. リッチメッセージ(imagemap)送信 ※ハマりやすいポイント

リッチメッセージ(imagemap)は、1枚の画像の中に複数のタップ領域を作れる、LINE独自のメッセージ形式です。

imagemapでは、1枚の画像をこのように分割し、それぞれに異なるアクションを設定できます。

上図のように、左右(A / B)でタップ領域を分け、リンク遷移やメッセージ送信などを割り当てるのが基本的な使い方です。

実装自体は同じく $message の中身を差し替えるだけですが、仕様の理解不足でかなり時間を取られました。

$message = [
    'to' => $userId,
    'messages' => [
        [
            'type' => 'imagemap',
            'baseUrl' => 'https://example.com/imagemap/menu',
            'altText' => 'メニューを選択してください',
            'baseSize' => [
                'width' => 1040,
                'height' => 1040
            ],
            'actions' => [
                [
                    'type' => 'uri',
                    'linkUri' => 'https://example.com/lp',
                    'area' => [
                        'x' => 0,
                        'y' => 0,
                        'width' => 520,
                        'height' => 520
                    ]
                ],
                [
                    'type' => 'message',
                    'text' => 'お問い合わせ',
                    'area' => [
                        'x' => 520,
                        'y' => 0,
                        'width' => 520,
                        'height' => 520
                    ]
                ]
            ]
        ]
    ]
];

baseUrl には 画像URLではなくディレクトリを指定します。
このディレクトリ内には、240 / 300 / 460 / 700 / 1040 という横幅(px)をファイル名にした画像を5つ用意しておく必要があります。

特に注意したいポイントは、次の2点です。

  • baseUrl にはディレクトリを指定すること
  • ディレクトリ内には、拡張子を付けずに5サイズ分の画像を配置すること

この仕様にかなりハマりました。

当初は baseUrl に画像URLを指定してしまっており、LINE側では「写真を読み込めません」というエラーメッセージが表示されていました。

「拡張子を付けない」という仕様も珍しく、公式ドキュメントもやや分かりづらいため、ChatGPTに聞いてみても明確な回答が得られず、原因特定まで時間がかかりました。

画像を手作業で5サイズ用意するのは手間がかかるため、以下のように リサイズ処理と拡張子を付けない保存を自動化する仕組みにしておくと運用しやすいと思います。

$srcImage = './org.jpg' //元画像;
$sizes = [240, 300, 460, 700, 1040];

foreach ($sizes as $w) {
    $dstImage = imagecreatetruecolor($w, $w);

    // PNG透過保持
    imagealphablending($dstImage, false);
    imagesavealpha($dstImage, true);
    $transparent = imagecolorallocatealpha($dstImage, 0, 0, 0, 127);
    imagefill($dstImage, 0, 0, $transparent);

    // 正方形リサイズ
    imagecopyresampled(
        $dstImage,
        $srcImage,
        0, 0, 0, 0,
        $w, $w,
        imagesx($srcImage),
        imagesy($srcImage)
    );

    // 保存(拡張子なし)
    $destPath = $destFolder . "/$w";
    imagepng($dstImage, $destPath);

    imagedestroy($dstImage);
}

以上です。

今回、SDK方式とcurl方式の両方をテストしましたが、特にリッチメッセージ(imagemap)については、仕様を正しく理解していないと簡単に詰まってしまう点が印象に残りました。

一方で、こうした仕様やクセを把握したうえで実装できれば、LINE公式アカウントの配信表現をより柔軟にコントロールできる手応えも感じています。

アプリメンバーズ コネクトでも近日中にLINE公式アカウントとの連携予定となっており、LINEミニアプリ、LINE公式アカウント運用を一元管理できるようになります。

ご興味いただけましたらぜひお問合せください。

▼過去の記事はこちら

お問合せ&資料請求