uzullaがブログ

uzullaがブログです。

Azure App ServiceのPHPつかっていてcurlがSSLのエラーを吐くので対処

github.com

LINEのMessaging APIをたたくSDKがあり、今これをつかったアプリをかいておりますが、Azure App Serviceでうごかしてみています。

で、App ServiceにはいってるPHPにはca証明書の指定がないようで、以下の様なエラーがでました。*1

PHP Fatal error:  Uncaught LINE\LINEBot\Exception\CurlExecutionException: SSL certificate problem: unable to get local issuer certificate in D:\home\site\vendor\linecorp\line-bot-sdk\src\LINEBot\HTTPClient\CurlHTTPClient.php:110
Stack trace:
#0 D:\home\site\vendor\linecorp\line-bot-sdk\src\LINEBot\HTTPClient\CurlHTTPClient.php(73): LINE\LINEBot\HTTPClient\CurlHTTPClient->sendRequest('POST', 'https://api.lin...', Array, Array)
(以下略)

皆さんご存じでしょうが、これはSDKが悪いのではなくてcurlhttps通信の検証が出来ないエラーです。

解決策

証明書を指定しましょう。これが自分で書いたコードなら

curl_setopt($c, CURLOPT_CAINFO, __DIR__.'cacert.pem');

みたいなことをかけばOKなんですが、今回はSDKの中なので、そういった雑なことはしたくない。

正しい解決策としては、curl.cainfophp.iniにかけばOKですね。ただ、このcurl.cainfoは置くだけでつかえる.user.iniでは指定できないPHP_INI_SYSTEMの範囲なので、もう一手間かけます。

公式ドキュメントにも記載があります。

azure.microsoft.com

上記URLから抜粋すると、以下のような感じです。

1. アプリの設定 (キー PHP_INI_SCAN_DIR、値 d:\home\site\ini) を Web アプリに追加する
2. d:\home\site\ini ディレクトリに settings.ini ファイルを作成します。
3. 設定を settings.ini ファイルに追加します。たとえば
curl.cainfo="%ProgramFiles(x86)%\Git\bin\curl-ca-bundle.crt"
4. 変更内容を読み込むには、Web アプリを再起動します。


ただ、やってみて午前四時の脳にウケたんですが、%ProgramFiles(x86)%\Git\bin\curl-ca-bundle.crtこれは無いです。

なので、d:\home\siteとかに

https://curl.haxx.se/ca/cacert.pem

をダウンロードして保存し、settings.phpには

curl.cainfo=d:\home\site\cacert.pem

などと記述しましょう。これで正しく通信できるはずです。

まとめ

PHP_INI_SYSTEMも変更できるAzure の App Service最高! これくらいは最初から設定されててほしいな!

こちらからは以上です。

*1:これは多分PHP7の話なので、それより前にすれば(げふん)

続、LINEのMessaging APIを使うメモ:PHP-SDKでbotをつくるぞ

はっきりいって説明不要というか、よくできたSDKがあるのでそれをつかえば完成します。

github.com

Tokenを取得

LINE Developers

からchannel secret, channel tokenを取得します。

(なんかちがうアカウントがでてきてしまう…などの場合は前日のエントリを参照)

SDKをDLしてComposerする

$ mkdir my_bot
$ cd my_bot
$ php composer.phar require linecorp/line-bot-sdk
$ mkdir wwwroot
$ cd wwwroot

とかします。

最低限このような雑なコードを書きます

(たとえば)wwwroot以下に、自分がLINEに登録したcallback URLになるようにファイルを設置します。

(くわしくは前日のエントリをみてください)

<?php // callback.php
define("LINE_MESSAGING_API_CHANNEL_SECRET", 'your channel secret');
define("LINE_MESSAGING_API_CHANNEL_TOKEN", 'your channel token');

require __DIR__."/../vendor/autoload.php";

$bot = new \LINE\LINEBot(
    new \LINE\LINEBot\HTTPClient\CurlHTTPClient(LINE_MESSAGING_API_CHANNEL_TOKEN),
    ['channelSecret' => LINE_MESSAGING_API_CHANNEL_SECRET]
);

$signature = $_SERVER["HTTP_".\LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE];
$body = file_get_contents("php://input");

$events = $bot->parseEventRequest($body, $signature);

foreach ($events as $event) {
    if ($event instanceof \LINE\LINEBot\Event\MessageEvent\TextMessage) {
        $reply_token = $event->getReplyToken();
        $text = $event->getText();
        $bot->replyText($reply_token, $text);
    }
}

echo "OK";

このコードは色々とエラー処理を端折っていますが、何を返しても向こう側はなにかしてくれるわけでもないのでここでは省略します。

SDKのexample以下のKitchenSinkをみればあらゆるものがあります。

line-bot-sdk-php/Route.php at master · line/line-bot-sdk-php · GitHub

SDKのサンプルは非常にちゃんとしてますので、受け取り方、メッセージの組み立て、大体全部の例があります、すごい。このエントリでなくそちらをまねましょう。実際の所、僕も上のコードは結構端折っており、実際にはそっちをマネてます。

これで完成です

botにはなしかけると、おうむがえしします。

            $text = $event->getText();
            $bot->replyText($reply_token, $text);

ここらへんかきかえると、自由に返事のテキストを組み立てできます。

オウム返しされない場合、エラーログなどをみてみましょう。多分なんかおかしいのでしょう。

まとめ

よくできたSDKなので説明することがありません。 サンプルがよくできすぎてるので、雑に書きなおしただけな気がします。

なお、PHP5.6以上が必要なので、気を付けましょう。

余談

当方はAzure App ServiceというPaaSがイケてるし安いので、PHP7がつかえるのでそれでやりました。

(その場合、curlの罠があるので、SSLのエラーがでたら一つ前のエントリをみてみてください)

uzulla.hateblo.jp

こちらからは以上です。

新・続LINEのMessaging APIを使うメモ:Beaconつかうぞ!

uzulla.hateblo.jp

一つ前の記事をまず見てください。

ビーコンとは

先日のLINE DEVELOPER DAY 2016で来場者にビーコンが配布されました。

f:id:uzulla:20161007153619p:plain

ビーコン、すごく夢があるやつで、「これがあればあんな案件もこんな案件も現実的だったのに…」と広告業界に片足あった男は思います*1。「その人がリアルにその場所にこないと発生しないトリガー」を皆がもとめていた時代があったのです(今でもあるけど)。

LINE DEV DAYでも、三箇所のビーコンのちかくにいくと、スタンプがもらえました。*2

まあビーコンのビジネス活用の話は他所に置きます。

ビーコンの登録

f:id:uzulla:20161007153900j:plain

ハコにURLがかいてあります、ハコをすててしまった人はしりません。*3

ビーコンの電池を抜くと、HWIDとCODEがあり、URLにそれを入力します。単語統一してくれ。

f:id:uzulla:20161007153922p:plain

うまくいけばビーコンがアカウントと連携し、LINE@MANAGERの左側にビーコンが現れ、アカウントのMessaging APIにビーコン検知のイベントがきます。

f:id:uzulla:20161007153941p:plain

使い方

昨日のサンプルコードをちょっとだけ修正して以下の感じにしてみました。

<?php // callback.php
define("LINE_MESSAGING_API_CHANNEL_SECRET", 'your channel secret');
define("LINE_MESSAGING_API_CHANNEL_TOKEN", 'your channel token');

require __DIR__."/../vendor/autoload.php";

$bot = new \LINE\LINEBot(
    new \LINE\LINEBot\HTTPClient\CurlHTTPClient(LINE_MESSAGING_API_CHANNEL_TOKEN),
    ['channelSecret' => LINE_MESSAGING_API_CHANNEL_SECRET]
);

$signature = $_SERVER["HTTP_".\LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE];
$body = file_get_contents("php://input");

$events = $bot->parseEventRequest($body, $signature);

foreach ($events as $event) {
    if ($event instanceof \LINE\LINEBot\Event\MessageEvent\TextMessage) {
        $reply_token = $event->getReplyToken();
        $text = $event->getText();
        $bot->replyText($reply_token, $text);
/* ================= ここから追記 =============================*/
    } elseif ($event instanceof \LINE\LINEBot\Event\BeaconDetectionEvent) {
        $reply_token = $event->getReplyToken();
        $bot->replyText($reply_token, "近くにいますね?");
/* ================= ここまで追記 =============================*/
    }
}

echo "OK";

追記の所をみてみればわかりますが、BeaconDetectionEventがきたらreply tokenをとりだして適当なテキストを送っています。

基本的にはテキストメッセージ受信とまったく同じです。

たったこれだけです、ちゃんとうごきますよ。

以上ですが

これだけでは何なので、もう少し書きます。

配布されたビーコンについて

配布されたビーコンの感覚値をかいておきます。これは配布された開発者用のビーコンと手元のGalaxy S7 edgeでの話であり、飛距離は(これをもっている開発者以外にはw)あまり意味がないでしょう。 電波状況やつかっているHWでは変わるでしょうし。

  • スイッチいれて、イベントがくるまで約1分、案外早い
  • 屋内ドア二枚くらいなら電波とどく(が、とぎれとぎれ)
  • 10mは余裕そう(うわさによれば、1mでも100mでも調整できる(ハードが新しく出る?)とか…?)
  • 一度でも検知されれば良いようなので、即時性をかんがえなければ実効はもっとひろそう
  • 検知するとenterイベントがくる
  • leaveイベントはない
  • 検出のインターバルは15秒くらいなのでは?
    • 微妙な距離に置くと、イベントが30秒間隔で発生する事があった(有効>無効>有効のワンクールで15*2?)
    • つまり無限にenterがくるので、一度きたら一時間無視みたいなのは自分で調整しなければいけない(自由度がたかくてよい)
    • 人が多いイベントでこれうごかすと、アプリサーバ側も相応にまちかまえないとダメそう
  • ハードウェアの説明書がもうちょっとほしい
    • 電池の持ちがさっぱりわからん
    • LEDの意味とか…スペックとか
    • まあ、こまったことはないので説明書は不要かもしれないが
  • もう一個ほしいんですが

まあ公式APIドキュメントにビーコンのことはまだほとんどないし、しかたないね。

色々やって自分でたしかめろ!ということなのでしょう。

まとめ

よくできていて、迷う所がない。

とにかく管理画面以外文句がない。

こちらからは以上です、つづく 。

*1:最近は疎遠です

*2:LINEは主に奥さんとやっているので、使いどころがない

*3:固定っぽいけど

How to use LINE Messaging API with PHP sdk in an hour.

this entry for beginner.

https://developers.line.me/messaging-api/overview

github.com

if you are expert, please see line-bot-sdk-php's examples. that is more better(more strict).

requirement

  • Public web server
  • need https
  • PHP version >= 5.6
  • curl extention
  • Composer

registration Developer trial

https://developers.line.me/

get tokens

You need to get channel token and channnel secret.

goto

https://developers.line.me/

and click channels at header right side.

you will see Channels basic infomation.

if you get wrong bot account?

if you try "TRIAL_BOT" before, open bellow url and click account list.

https://business.line.me/

then, open your developers trial bot account's Messaging API's LINE DEVELOPER button.

Okey, create your project

example file tree.

/project_root/
             /wwwroot/ # your httpd document root dir
                     /index.html # not require
                     /callback.php
             /vendor # will create by composer
             /composer.* # will create by composer

these are example. you can change wwwroot to htdocs,public and other as you like.

install sdk

$ mkdir project_root
$ cd project_root
$ wget https://getcomposer.org/composer.phar
$ php composer.phar require linecorp/line-bot-sdk

# will generate composer.json, composer.lock, vendor/

create callback.php at project_root/wwwroot/

this is sample echo bot.

<?php // callback.php
define("LINE_MESSAGING_API_CHANNEL_SECRET", 'your channel secret');
define("LINE_MESSAGING_API_CHANNEL_TOKEN", 'your channel token');

require __DIR__."/../vendor/autoload.php";

$bot = new \LINE\LINEBot(
    new \LINE\LINEBot\HTTPClient\CurlHTTPClient(LINE_MESSAGING_API_CHANNEL_TOKEN),
    ['channelSecret' => LINE_MESSAGING_API_CHANNEL_SECRET]
);

$signature = $_SERVER["HTTP_".\LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE];
$body = file_get_contents("php://input");

$events = $bot->parseEventRequest($body, $signature);

foreach ($events as $event) {
    if ($event instanceof \LINE\LINEBot\Event\MessageEvent\TextMessage) {
        $reply_token = $event->getReplyToken();
        $text = $event->getText();
        $bot->replyText($reply_token, $text);
    }
}

echo "OK";

please edit your channel secret, your channel token to your tokens.

register webhook URL(callback URL)

set your callback.php url to webhook URL.

you can edit webhook URL at Channels basic infomation.

open bellow url and click channnels (same as get token).

https://developers.line.me/

TEST!

follow your bot account, and send a text.

echo bot will echo back same text.

(sticker(and other) message is not normal text message, this echo bot will ignore.)

if you got any reply

at first, CHECK YOUR ACCESS_LOG and ERROR LOG! (IMPORTANT!!!)

You can not trust access from webhook from line?

this code will dump any request post body to /tmp/dump.txt.

<?php
ob_start();
$raw = file_get_contents('php://input');
var_dump(json_decode($raw,1));
$raw = ob_get_clean();
file_put_contents('/tmp/dump.txt', $raw."\n=====================================\n", FILE_APPEND);

echo "OK";

FYI: webhook access is not encoded by application/x-www form-urlencoded, so $_POST will blank.

SSL Error

SSL certificate problem: unable to get local issuer certificate

this is cause by YOUR php settings.

you need set curl ca certification

please google with 'curl.cainfo php.ini'.

done!

that's all. very simple.

see also

if you want to listen other messaging api events, plz see SDK example/KitchenSink.

enjoy!

for japanese

ここ数日のエントリをみてくれ。