@simple8888

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

LINE Messaging API利用時のエックスサーバーで400エラーが出ます

Q&A

Closed

Google検索でもこれといった記事が見つからず、エックスサーバーへ問い合わせもしましたが、ご自身でお調べくださいとの回答であったため、初めて質問させて頂きます。

質問したいこと

LINE Messaging APIを使用してLINE公式アカウントをカスタマイズしています。
使用言語はPHPです。
テスト環境として、レンタルサーバーはさくらサーバーを利用し、LINE developersにてWEBHOOK先にhttps独自ドメイン(hoge-test.com)配下のindex.phpを指定。
基本的な機能(メッセージのやりとり・リッチメニューの表示切り替え等)が問題なく動作していました。

本番環境に移行するため、レンタルサーバーをエックスサーバーx10プランにして、必要なファイル群を本番用の独自ドメイン(hoge-honban.com)配下に設置してアクセスしたところ、curlでのapiレスポンスが400 Bad Requestとなり返ってくるようになったため、その原因を理解し、改善をするためのヒントを教えて頂きたいです。

実装しているリッチメニュー切り替えコード

index.php
$ch = curl_init("https://api.line.me/v2/bot/user/{$userID}/richmenu/{$richMenu}");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-Type: application/json",
        "Authorization: Bearer {$accessToken}"
    ));
    $result = curl_exec($ch);
    curl_close($ch);

実装しているリッチメニュー削除コード

index.php
$ch = curl_init("https://api.line.me/v2/bot/user/{$userID}/richmenu");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-Type: application/json",
        "Authorization: Bearer {$accessToken}"
    ));
    $result = curl_exec($ch);
    curl_close($ch);

その結果、$resultに格納されるレスポンス内容

<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>openresty</center>
</body>
</html>

$エックスサーバーのエラーログ内容の抜粋

[proxy_fcgi:error] AH01071: Got error

実装 / 処理の流れ

メッセージのやり取りの中間に、上記のリッチメニュー切り替え等の処理を入れ、その結果が正常であった場合のみ次の処理へと進む仕組みにしています。

処理のどこかでエラーが出た場合は、エラーメッセージとしてユーザーにメッセージ送信しています。
例:『現在サーバーにアクセス出来ません!』

理解できないこと

処理の最終段にある、リプライapiだけは正常に処理されます。
なので、処理途中で400エラーが出ていても、その旨を知らせるエラーメッセージはちゃんと送信できています。
ユーザーIDやアクセストークンは同じものを使いまわしているので、そこに関しての不備はないと思います。

index.php
$ch = curl_init("https://api.line.me/v2/bot/message/reply");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($json));//メッセージ内容
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-Type: application/json",
        "Authorization: Bearer {$accessToken}"
    ));
    $result = curl_exec($ch);
    curl_close($ch);

なぜリプライapiだけが正常で、他のリクエストがエラーとなるのか理解できず、修正の方法も検討すらついていない状況です。

proxy_fcgi error AH01071等のキーワードで検索してもこれといった情報が出て来ませんでした。
エックスサーバーのPHPバージョンは7.4.4となっており、テスト環境のさくらサーバーは7.4.9のCGI版となっています。

初めての質問で説明の不備があるかと思いますので、必要な情報は開示しますので教えてください。
どうぞ宜しくお願い致します。

0 likes

1Answer

【追記】コメント欄で解決したので転記しておきます。

PHP のバージョンによっては、 CURLOPT_POST をセットする場合は CURLOPT_POSTFIELDS もセットしないとリクエストに失敗することがあるようです。また、質問のスクリプトはすでに CURLOPT_CUSTOMREQUEST'POST' にセットしてあるので CURLOPT_POST は不要です。

【追記ここまで】


まずは問題を切り分けるためにリクエスト部分だけ実行できるようにするといいと思います。

change_richmenu.php
<?php
// ここで $userID, $richMenu, $accessToken をセットしておく

$ch = curl_init("https://api.line.me/v2/bot/user/{$userID}/richmenu/{$richMenu}");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-Type: application/json",
        "Authorization: Bearer {$accessToken}"
    ));
    $result = curl_exec($ch);
    curl_close($ch);

var_dump($result);

この部分をファイルに保存して php ファイル名 で実行できます。正常に動作しているでしょうか?

0Like

Comments

  1. @simple8888

    Questioner

    早速のご回答ありがとうございます。

    まさに同じ内容でphpファイルを当該サーバーに設置しアクセステストはしていました。
    結果としては変わらず400エラーが返されています。

    何かとっても初歩的なミスのような気がしていますがどうなんでしょうか。
  2. $accessToken が正しくなければ

    {"message":"Authentication failed due to the following reason: invalid token. Confirm that the access token in the authorization header is valid."}

    が返ってきますし、 $userID や $richMenu が正しくなければ404になりそうですね(これは未確認ですが)。400ということはリクエストの内容が不正なはずです。

    リクエストボディが空なのに "Content-Type: application/json" ヘッダを送るのがまずいかもしれません。空文字列は JSON としては不正なので。

    でもテスト環境では動いていたんですよね……
  3. @simple8888

    Questioner

    リクエスト部分を切り出したphpファイルも、さくらサーバーでは正常に動き、各情報を取得できています。

    本番用のエックスサーバーでは、本体phpファイルも全く同じコードを使っていますし、curlリクエストを除いてはメッセージのやり取りが正常に出来ています。

    リプライapiではエラーが出ないので謎は深まるばかりです。

    curlコマンドはサーバーの設定やPHPバージョンに依存するものなのでしょうか。。

  4. PHP 7.2 系でだけ、 CURLOPT_POST をセットする場合は CURLOPT_POSTFIELDS も指定しないと動かないという記事を見つけました https://qiita.com/shate/items/51dd9d4881f5f044698e

    7.4.4と7.4.9でこのあたりの挙動が二転三転するかどうかというと怪しいですが。

    そもそも CURLOPT_CUSTOMREQUEST をセットしているので CURLOPT_POST は不要では。
  5. @simple8888

    Questioner

    動きました!

    ご指摘の通り、
    CURLOPT_POSTの行をコメントアウトしたところ問題なく動作の確認が取れました。

    関連記事まで見つけて頂き感謝致します。
    本当にありがとうございました!
  6. おお、よかったです。

Your answer might help someone💌