Q&A

Messaging API line-bot-sdk-phpで特定のLineBotのメソッドを使用したとき、プロトコルエラーが発生する

前提・実現したいこと

curlを使用せずに、LINEBotのlinkRichMenuやcreateLinkTokenのメソッドを使用して MessagingAPIを利用したい。

発生している問題・エラーメッセージ

 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1) {"exception":"[object] (LINE\\LINEBot\\Exception\\CurlExecutionException(code: 0): HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1) at /var/www/laravel/matool/vendor/linecorp/line-bot-sdk/src/LINEBot/HTTPClient/CurlHTTPClient.php:184)
 #0 /var/www/laravel/matool/vendor/linecorp/line-bot-sdk/src/LINEBot/HTTPClient/CurlHTTPClient.php(84): LINE\\LINEBot\\HTTPClient\\CurlHTTPClient->sendRequest('POST', 'https://api.lin...', Array, Array)
#1 /var/www/laravel/matool/vendor/linecorp/line-bot-sdk/src/LINEBot.php(552): LINE\\LINEBot\\HTTPClient\\CurlHTTPClient->post('https://api.lin...', Array)

該当のソースコード

$this->botはLINEBotのインスタンスです。 linkRichMenuやcreateLinkToken、setDefaultRichMenuIdなどのメソッドでhttp2のエラーが発生しています。

    $this->bot->linkRichMenu($lineUserId, $richId);
    $this->bot->createLinkToken($userId);
	$this->bot->setDefaultRichMenuId($richId);

試したこと

試しにcreateLinkTokenのメソッドを curlを使用して書き換え CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, のオプションをつけるとうまく動作しました。

        $userId = $event->getUserId();
        $curl = curl_init();

        curl_setopt_array($curl, array(
            CURLOPT_URL => "https://api.line.me/v2/bot/user/{$userId}/linkToken",
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => "",
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 0,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "POST",
            CURLOPT_HTTPHEADER => array(
                "Authorization: Bearer {$this->accessToken}"
            ),
        ));

        $response = curl_exec($curl);

        curl_close($curl);
        $responseObject = json_decode($response);
        $linkToken = object_get($responseObject, "linkToken");

補足情報(FW/ツールのバージョンなど)

php 7.1.3 laravel 6.0 linecorp/line-bot-sdk: 5.1,

  • 1
  • 1
  • 3472
  • twitter facebook

こちらのinterfaceを実装したクラスを用意していただければ、curlを使用せずにご利用いただけます。 https://github.com/line/line-bot-sdk-php/blob/master/src/LINEBot/HTTPClient.php

例(Guzzleを使った場合のイメージです。動作未検証です。)↓

class CustomHTTPClient implements HTTPClient
{
    public function __construct()
    {
        $this->client = new GuzzleHttp\Client();
    }

    public function setAccessToken(string $token)
    {
        $this->token = $token;
    }

    public function get($url, array $data = [], array $headers = [])
    {
        $r = $this->client->get($url, [
            'headers' => $this->convertHeaders($headers + ['Authorization' => 'Bearer ' . $token]),
            'query' => $data,
        ]);
        return new Response($r->getBody()->getContents(), $r->getStatusCode(), $r->getHeaders());
    }
		
    public function convertHeaders(array $headers)
    {
        $converted = [];
        foreach ($headers as $header) {
            $splited = explode(': ', $header);
            $converted[splited[0]] = splited[1];
        }
        return $converted;
    }
    
    ......
}
$client = new CustomHTTPClient();
$client->setAccessToken('<channel access token>'); // CustomHTTPClientの実装次第
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => '<channel secret>']);
  • 0
本当によろしいですか? question.vm