Edited at

LINE Botが超便利になるLINE Loginバージョン2の解説と実装方法(Heroku+PHP)

More than 1 year has passed since last update.

LINE Login v2がものすごく便利なのに解説した記事が見当たらないので、LINE Messaging APIとの連携を例として書いておきます。(すいません、Salesforce版はありました > http://qiita.com/hhayai/items/c7d1d8e30751871aafc7)

これが使えるとLINE Botで出来ることが格段に増えるのでBot Awardとか狙っている人にはものすごく便利かと。

LINE Bot Awards


LINE Login バージョン2とMessaging APIを組み合わせて出来ること


  • LINEのIn AppブラウザでユーザーはLINEのアカウントを利用してログインできる

  • 2度目以降はIDパスワード入力無しの自動ログイン

  • ログイン後はブラウザ上でもLINEの表示名、サムネイル、Messaging APIと共通のuserIdが取得できる(それを使ってメッセージのPushができる)


準備



  • LINE Business CenterでLINE Messaging APIとLINE Loginのアカウントを開設

  • Messaging APIのChannel SecretとChannel Access Token、LINE LoginのChannel IDとChannel Secretを控えとく


  • LINE Messaging APIの設定を終わらせておきます。わからない方はググって。

  • LINE LoginのTechnical Configurationにログイン後のコールバック先を入力 ← 忘れがち


  • CSRF対策用にaura/sessionを入れときます。

composer require composer require aura/session


index.php(Botからのリクエストを受け取るスクリプト)


index.php

<?php

require_once __DIR__ . '/vendor/autoload.php';

$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(getenv('CHANNEL_ACCESS_TOKEN'));
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => getenv('CHANNEL_SECRET')]);

$signature = $_SERVER['HTTP_' . \LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE];
try {
$events = $bot->parseEventRequest(file_get_contents('php://input'), $signature);
} catch(\LINE\LINEBot\Exception\InvalidSignatureException $e) {
error_log('parseEventRequest failed. InvalidSignatureException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownEventTypeException $e) {
error_log('parseEventRequest failed. UnknownEventTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\UnknownMessageTypeException $e) {
error_log('parseEventRequest failed. UnknownMessageTypeException => '.var_export($e, true));
} catch(\LINE\LINEBot\Exception\InvalidEventRequestException $e) {
error_log('parseEventRequest failed. InvalidEventRequestException => '.var_export($e, true));
}

foreach ($events as $event) {
$bot->replyText($event->getReplyToken(), "https://" . $_SERVER["HTTP_HOST"] . "/line_login.php");
}

?>


イベントに対してログイン用のWebサイトへのリンクを返信するだけ。


line_login.php(ログインボタンを表示するWebページ)


line_login.php

<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>

<html xmlns='http://www.w3.org/1999/xhtml' lang='ja' xml:lang='ja'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>LINE Login v2 Sample</title>
</head>
<body>
<?php

require_once __DIR__ . '/vendor/autoload.php';

$session_factory = new \Aura\Session\SessionFactory;
$session = $session_factory->newInstance($_COOKIE);
$segment = $session->getSegment('Vendor\Package\ClassName');

$csrf_value = $session->getCsrfToken()->getValue();

$callback = urlencode('https://' . $_SERVER['HTTP_HOST'] . '/line_callback.php');
$url = 'https://access.line.me/dialog/oauth/weblogin?response_type=code&client_id=' . getenv('LOGIN_CHANNEL_ID') . '&redirect_uri=' . $callback . '&state=' . $csrf_value;
echo '<a href=' . $url . '><button class="contact">LINE Login v2 Sample</button></a>';

?>
</body>
</html>


ログインボタンを表示する用のページ。このページ表示せずいきなりログインAPI叩くのも可能。


line_callback.php(ログイン後に飛ばされるページ)


line_login.php

<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>

<html xmlns='http://www.w3.org/1999/xhtml' lang='ja' xml:lang='ja'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>LINE Login v2 Sample Callback</title>
</head>
<body>
<?php

require_once __DIR__ . '/vendor/autoload.php';

$unsafe = $_SERVER['REQUEST_METHOD'] == 'POST'
|| $_SERVER['REQUEST_METHOD'] == 'PUT'
|| $_SERVER['REQUEST_METHOD'] == 'DELETE';

$session_factory = new \Aura\Session\SessionFactory;
$session = $session_factory->newInstance($_COOKIE);
$csrf_value = $_GET['state'];
$csrf_token = $session->getCsrfToken();
if ($unsafe || !$csrf_token->isValid($csrf_value)) {
return;
}

$callback = 'https://' . $_SERVER['HTTP_HOST'] . '/line_callback.php';
if (isset($_GET['code'])) {
$url = 'https://api.line.me/v2/oauth/accessToken';
$data = array(
'grant_type' => 'authorization_code',
'client_id' => getenv('LOGIN_CHANNEL_ID'),
'client_secret' => getenv('LOGIN_CHANNEL_SECRET'),
'code' => $_GET['code'],
'redirect_uri' => $callback
);
$data = http_build_query($data, '', '&');
$header = array(
'Content-Type: application/x-www-form-urlencoded'
);
$context = array(
'http' => array(
'method' => 'POST',
'header' => implode('\r\n', $header),
'content' => $data
)
);
$resultString = file_get_contents($url, false, stream_context_create($context));
$result = json_decode($resultString, true);

if(isset($result['access_token'])) {
$url = 'https://api.line.me/v2/profile';
$context = array(
'http' => array(
'method' => 'GET',
'header' => 'Authorization: Bearer '. $result['access_token']
)
);
$profileString = file_get_contents($url, false, stream_context_create($context));
$profile = json_decode($profileString, true);
        echo '<img src="' . htmlspecialchars($profile["pictureUrl"], ENT_QUOTES) . '" />';
echo '<p>displayName : ' . htmlspecialchars($profile["displayName"], ENT_QUOTES) . '</p>';
echo '<p>userId : ' . htmlspecialchars($profile["userId"], ENT_QUOTES) . '</p>';

$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(getenv('CHANNEL_ACCESS_TOKEN'));
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => getenv('CHANNEL_SECRET')]);
$bot->pushMessage($profile["userId"], new \LINE\LINEBot\MessageBuilder\TextMessageBuilder('Logged in via LINE Login v2.'));
}
}
else {
echo '<p>Login Failed.</p>';
}
?>
</body>
</html>



結果

友達追加するとリンクが送られます。

ログインページ。

ボタンをタップするとログインを試みます。

ログインしたことないLogin先の場合は認証画面が開きます。一度同意すると次回からは表示されず、自動でログイン。

ログイン完了。Web上でLINEアカウントの表示名やサムネイル、ステータスメッセージ、ユーザーIDが取得できます。

このユーザーIDはLINE Messaging APIと共通なので、Push APIを利用してユーザーにメッセージ送信できます。

こんな感じ。Botとのトーク画面にメッセージを送信できました。


まとめ

LINE Loginを上手く使うとBotのインターフェースを考える時、トーク画面上でのコミュニケーションに限定されず必要に応じてWebに遷移させればいいので開発者にもユーザーにもとても優しいですね。

設定画面とかはWebに飛ばすのが当たり前になりそうです。