紀錄在Laravel中使用Line message api以及LIFF

message api

建立message api

首先先到LINE Developers建立一個message api

點選新增

新增message api webhook url程式:

成功建立頻道後,先下載line-bot-sdk-php

composer require linecorp/line-bot-sdk

.env檔案中新增,並將頻道資訊填入

Basic settings找到Channel secret

Messaging API找到Channel access token

填入

LINE_BOT_CHANNEL_ACCESS_TOKEN=
LINE_BOT_CHANNEL_SECRET=

public function callback(Request $request)
{
$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(env('LINE_BOT_CHANNEL_ACCESS_TOKEN'));
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => env('LINE_BOT_CHANNEL_SECRET')]);
$response = $bot->getMessageContent('<messageId>');
if ($response->isSucceeded()) {
$tempfile = tmpfile();
fwrite($tempfile, $response->getRawBody());
} else {
error_log($response->getHTTPStatus() . ' ' . $response->getRawBody());
}
}

新增完成後點擊Messaging API將webhook url網址填入並測試

點擊Verify

回聲蟲

將程式做修改,取得使用者輸入的文字並回傳

public function callback(Request $request)
{
$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(env('LINE_BOT_CHANNEL_ACCESS_TOKEN'));
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => env('LINE_BOT_CHANNEL_SECRET')]);
$reply_token = $request->events[0]['replyToken'] ?? ''; // 回傳給誰
$message = $request->events[0]['message']['text'] ?? '您的訊息無法辨識'; // 使用者輸入文字
$textMessageBuilder = new \LINE\LINEBot\MessageBuilder\TextMessageBuilder($message); // 建立訊息
$response = $bot->replyMessage($reply_token, $textMessageBuilder); // 回傳
}

效果如下

訊息類型

這邊舉幾個例子

多頁訊息

use LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselColumnTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselTemplateBuilder;

public function callback(Request $request)
{
for ($i = 0; $i < 5; $i++) {
$actions = array(
new UriTemplateActionBuilder("查看", "https://linecorp.com"),
);
$column = new CarouselColumnTemplateBuilder('test', 'test', "https://imgur.com/Lh3gOFn.jpg", $actions);
$columns[] = $column;
}

$carousel = new CarouselTemplateBuilder($columns);
$textMessageBuilder = new TemplateMessageBuilder("請在手機中查看此訊息", $carousel);
$response = $bot->replyMessage($reply_token, $textMessageBuilder);
}

彈性訊息Flex Message

是具有可自定義佈局的消息,可以到彈性消息模擬器測試訊息,組成自己喜愛的版型,在電腦版中也會顯示哦。

今日用他的範例來操作,做出相同的訊息

程式碼
use LINE\LINEBot\MessageBuilder\FlexMessageBuilder;
use LINE\LINEBot\MessageBuilder\Flex\ContainerBuilder\CarouselContainerBuilder;
use LINE\LINEBot\MessageBuilder\Flex\ContainerBuilder\BubbleContainerBuilder;
use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\BoxComponentBuilder;
use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\FillerComponentBuilder;
use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\ImageComponentBuilder;
use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\TextComponentBuilder;
use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\ButtonComponentBuilder;
use LINE\LINEBot\MessageBuilder\Flex\ComponentBuilder\IconComponentBuilder;

public function callback(Request $request)
{
$imageComponent = new ImageComponentBuilder("https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_1_cafe.png");
$imageComponent->setSize('full')
->setAspectMode('cover')
->setAspectRatio('20:13')
->setGravity('top');

$titleText = new TextComponentBuilder("Brown Cafe");
$titleText->setSize('xl')
->setWeight('bold');
$titleTextBox = new BoxComponentBuilder('vertical', [$titleText]);

$starIcon = new IconComponentBuilder("https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png");
$starIcon->setSize('sm');

$nonStarIcon = new IconComponentBuilder("https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gray_star_28.png");
$nonStarIcon->setSize('sm');

$rateText = new TextComponentBuilder("4.0");
$rateText->setSize('sm')
->setMargin('md')
->setColor('#999999')
->setFlex(0);

$rateTextBox = new BoxComponentBuilder(
'baseline',
[
$starIcon,
$starIcon,
$starIcon,
$starIcon,
$nonStarIcon,
$rateText,
]
);

$placeText = new TextComponentBuilder("Place");
$placeText->setSize('sm')
->setFlex(1)
->setColor("#aaaaaa");

$placeNameText = new TextComponentBuilder("Miraina Tower, 4-1-6 Shinjuku, Tokyo");
$placeNameText->setSize('sm')
->setFlex(5)
->setColor("#666666")
->setWrap(true);

$placeDetailTextBox = new BoxComponentBuilder(
'baseline',
[
$placeText,
$placeNameText,
]
);

$timeText = new TextComponentBuilder("Time");
$timeText->setSize('sm')
->setFlex(1)
->setColor("#aaaaaa");

$timeDetailText = new TextComponentBuilder("10:00 - 23:00");
$timeDetailText->setSize('sm')
->setFlex(5)
->setColor("#666666")
->setWrap(true);

$timeDetailTextBox = new BoxComponentBuilder(
'baseline',
[
$timeText,
$timeDetailText,
]
);

$contentBox = new BoxComponentBuilder(
'vertical',
[
$rateTextBox,
$placeDetailTextBox,
$timeDetailTextBox,
]
);
$contentBox->setSpacing('sm')
->setMargin('lg');

$bodyBox = new BoxComponentBuilder(
'vertical',
[
$titleText,
$contentBox,
]
);

$callButton = new ButtonComponentBuilder(
new UriTemplateActionBuilder('CALL', "https://linecorp.com")
);
$callButton->setHeight('sm')->setStyle('link');

$websiteButton = new ButtonComponentBuilder(
new UriTemplateActionBuilder('WEBSITE', "https://linecorp.com")
);
$websiteButton->setHeight('sm')->setStyle('link');

$footerBox = new BoxComponentBuilder(
'vertical',
[
$callButton,
$websiteButton,
]
);

$bubbleContainerBuilder = new BubbleContainerBuilder(
null,
null,
$imageComponent,
$bodyBox,
$footerBox,
null,
null
);

$flexMessageBuilder = new FlexMessageBuilder(
'FLEX MESSAGE SIMULATOR',
$bubbleContainerBuilder
);

$response = $bot->replyMessage($reply_token, $flexMessageBuilder);
}

成果

鏈接用戶帳戶

利用帳戶鏈接功能(Linking user accounts)功能,能將Line用戶與原先提供者(企業和開發者)的服務用戶帳戶連接,這將允許提供商利用他們獲得的用戶數據並使用 LINE 官方帳號來提供更好的服務。

例如,可以通過將購物網站上的用戶帳戶與 LINE 用戶帳戶關聯來提供這些服務:

  • 當用戶從購物網站購買產品時,從 LINE 官方帳號發送消息。
  • 當用戶向 LINE 官方帳號發送消息時,接受和處理訂單。
  • 帳戶也可以通過 LINE 登錄鏈接,但也需要 LINE 登錄渠道。即使僅使用消息傳遞 API,也可以實現帳戶鏈接功能。

帳號連接順序如下:

(圖片來自: LINE Developer Document: Link user account )

User:

  • LINE 的用戶。

Provider’s bot server:

  • 商業服務的 LINE 聊天機器人伺服器。

Provider’s web server:

  • 商業服務的網站伺服器,如果是購物網站就是該購物網站的後台伺服器。

LINE Platform:

  • 這個就是指 LINE 平台的資料處理系統。

順序分別為:

  1. 機器人服務器調用從 LINE 用戶 ID 發出鏈接令牌的 API。
  2. LINE 平台將鏈接令牌返回給機器人服務器。
  3. bot 服務器調用 Messaging API 將鏈接 URL 發送給用戶。
  4. LINE 平台向用戶發送鏈接 URL。
  5. 用戶訪問鏈接 URL。
  6. Web 服務器顯示登錄屏幕。
  7. 用戶輸入他們的憑據。
  8. Web 服務器從提供者的服務中獲取用戶 ID,並使用它來生成隨機數(使用一次的數字)。
  9. Web 服務器將用戶重定向到帳戶鏈接端點。
  10. 用戶訪問帳戶鏈接端點。
  11. LINE 平台通過 webhook 向機器人服務器發送一個事件(包括 LINE 用戶 ID 和 nonce)。
  12. bot 服務器使用 nonce 獲取提供者服務的用戶 ID。

實作綁定流程

1. 取得鏈接令牌

/bot/user/{userId}/linkToken向端點發送 HTTP POST 請求,並為您嘗試鏈接的用戶發出鏈接令牌。

curl -X POST https://api.line.me/v2/bot/user/{userId}/linkToken \
-H 'Authorization: Bearer {channel access token}'

如果請求成功,200將返回狀態碼和鏈接令牌。鏈接令牌有效期為 10 分鐘,並且只能使用一次。

{
"linkToken": "NMZTNuVrPTqlr2IF8Bnymkb7rXfYv5EY"
}
2. 將用戶重定向到鏈接 URL

取得user id以及鏈接令牌向用戶發送重導向連結訊息

以下程式情境為當偵測到使用者輸入會員綁定,傳送導向會員綁定連結訊息

public function callback(Request $request)
{
$message_type = $request->events[0]['message']['type'] ?? '';
if ($message_type == 'text' && $request->events[0]['message']['text'] == '會員綁定'){
$user_id = $request->events[0]['source']['userId'];
$hash_user_id = base64_encode($user_id);
try {
$response = Http::withToken(
env('LINE_BOT_CHANNEL_ACCESS_TOKEN')
)->post(
"https://api.line.me/v2/bot/user/$user_id/linkToken"
);
$linkToken = $response->json()['linkToken'];
} catch (Exception $e) {
return $e;
}
$actions = array(
new UriTemplateActionBuilder("開始綁定", "https://example.tw/line-binding?linkToken=$linkToken&userId=$hash_user_id"),
);
$carousel = new ButtonTemplateBuilder(null, '現在就開始進行Line個人化服務綁定,按下登入將XXX帳號連結在一起!將可以享受個人化功能。', null, $actions);
$textMessageBuilder = new TemplateMessageBuilder("請在手機中查看此訊息", $carousel);
$response = $bot->replyMessage($reply_token, $textMessageBuilder);
}

}

3. 獲取服務的用戶 ID

當用戶訪問鏈接 URL 時,他們將看到您的服務的登錄屏幕。登錄後,您可以從您的服務中獲取用戶的 ID

4. 生成隨機數並將用戶重定向到 LINE 平台

官方說法是產生一個難以預測且只能使用一次的字符串的值nonce並介於介於 10 到 255 個字符之間,並將nonce 與獲取的用戶 ID 關聯並保存。這邊是保存在資料庫裡

保存 nonce 和用戶 ID 後,將用戶重定向到以下端點。

https://access.line.me/dialog/bot/accountLink?linkToken={link token}&nonce={nonce}
當用戶訪問此端點時,LINE 平台將驗證該用戶是否是為其頒發鏈接令牌的用戶。

  • 如果帳戶可以成功鏈接:屬性值為的賬戶鏈接事件將通過 webhook 發送到 bot 服務器。result ok
  • 如果由於任何原因無法鏈接帳戶,例如由於用戶冒充:屬性值為的帳戶鏈接事件將通過 webhook 發送到機器人服務器。result failed
  • 如果鏈接令牌已過期或已被使用:不會發送任何 webhook 事件,並且會向用戶顯示錯誤
use Illuminate\Support\Str;
use Carbon\Carbon;

// line官方帳號鏈接用戶帳戶api
public function bindUser(Request $request)
{
$request->validate([
'id' => 'required|exists:camp.users,id|unique:line_links,user_id',
'line_id' => 'required|unique:line_links,line_id',
]);

$lineLink = LineLink::create([
'user_id' => $request->id,
'line_id' => $request->line_id,
'nonce' => $this->generateNonce(),
]);

$rich_menu_id = LineMenu::where('name', 'bind')->first()->rich_menu_id;

return response()->json(['success' => true, 'message' => '綁定成功', 'nonce' => $lineLink->nonce]);
}

public function generateNonce()
{
return Str::random() . base64_encode(Carbon::now());
}
5. 關聯賬戶

一旦 bot 服務器收到帳戶鏈接事件,就執行鏈接處理。

要鏈接的 LINE 用戶 ID 和步驟 4 中生成的 nonce 包含在 webhook 事件中。使用此 nonce 從您的服務中識別之前與 nonce 關聯並保存的用戶 ID。將此 ID 鏈接到 LINE 用戶 ID 後,帳戶鏈接將完成。

6. 取消連接

使用帳戶鏈接功能,需通知用戶有取消連結功能,並提供取消連結功能

以下為取消連接apiline_idlineuser iduser_id為服務器用戶id

public function unbind(Request $request)
{
$lineLink = LineLink::where('line_id', $request->line_id)->where('user_id', $request->user_id);
$lineLink->delete();
return response()->json(['success' => true, 'message' => '解除綁定成功']);
}

使用情境

  1. 可以在使用者綁定後切換豐富選單,讓使用者體驗更佳
  2. 當原本就有很多使用者在大量網站上

(圖片來自於LINE Engineering)

使用豐富菜單

有兩種方式可以創建豐富菜單一種是在line官方管理器設置,另一種是透過api方式設置

優先級別為以下(高到低)

  1. 使用 Messaging API 替用戶設置豐富菜單
  2. 使用 Messaging API 設置的默認豐富菜單
  3. line官方管理器設置默認豐富菜單設置

如何設置的默認豐富菜單

此範例為新增六格圖文選單,分為三個階段

  1. 新增圖文選單
  2. 上傳圖文選單圖片
  3. 設置為默認豐富菜單

圖文選單選項

  • size: 圖文選單圖片的長寬,必需為以下尺寸:
  • 2500x16862500x8431200x8101200x405800x540800x270
  • selected: 選單是否預設開啟,true 或 false。

  • name: 選單名稱,用於識別和管理選單,不會外顯。

  • chatBarText: 顯示在聊天視窗下方的選單文字。

  • areas: 用於定義按鈕的可點墼區域。

  • bounds 用於定義座標和大小

  • x、y: 起始座標

  • width: 寬度

  • height: 高度

  • action 用於定義觸發的動作

  • type: 動作類型,詳細說明可以參考 官方文件

  • label: 動作標籤,用於客戶端輔助功能

  • text: 發送到聊天視窗的文字

  • data: 透過 webhook 回傳到後端的字串

    // 3. 設置為默認豐富菜單
    public function cretaeDefaultRichMenu()
    {
    $richMenuId = $this->createRichMenu();
    $uploadStatus = $this->uploadRichMenuImage($richMenuId, 'yourImage.jpg');
    if ($uploadStatus) {
    $this->setDefaultRichMenu($richMenuId);
    }
    LineMenu::updateOrCreate(
    ['name' => 'unbind'],
    ['rich_menu_id' => $richMenuId]
    );
    return response()->json(['status' => 'success']);
    }

    // 1. 新增圖文選單
    public function createRichMenu()
    {
    $httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(env('LINE_BOT_CHANNEL_ACCESS_TOKEN'));
    $bot = new \LINE\LINEBot($httpClient, ['channelSecret' => env('LINE_BOT_CHANNEL_SECRET')]);
    $richMenuBuilder = new \LINE\LINEBot\RichMenuBuilder(
    new \LINE\LINEBot\RichMenuBuilder\RichMenuSizeBuilder(1686, 2500),
    true,
    '未綁定前選單',
    '開啟選單',
    [
    new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBuilder(new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBoundsBuilder(0, 0, 833, 843), new \LINE\LINEBot\TemplateActionBuilder\MessageTemplateActionBuilder('文字', '會員綁定')),
    new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBuilder(new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBoundsBuilder(833, 0, 833, 843), new \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder('首頁', env('APP_URL'))),
    new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBuilder(new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBoundsBuilder(1666, 0, 833, 843), new \LINE\LINEBot\TemplateActionBuilder\MessageTemplateActionBuilder('文字', '測試')),
    new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBuilder(new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBoundsBuilder(0, 843, 833, 843), new \LINE\LINEBot\TemplateActionBuilder\MessageTemplateActionBuilder('文字', '測試')),
    new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBuilder(new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBoundsBuilder(833, 843, 833, 843), new \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder('line官方管理器', 'https://manager.line.biz/')),
    new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBuilder(new \LINE\LINEBot\RichMenuBuilder\RichMenuAreaBoundsBuilder(1666, 843, 833, 843), new \LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder('line官方管理器', 'https://manager.line.biz/')),
    ]
    );
    $response = $bot->createRichMenu($richMenuBuilder);
    $richMenuId = $response->getJSONDecodedBody()['richMenuId'];

    return $richMenuId;
    }

    2. 上傳圖文選單圖片
    public function uploadRichMenuImage($richMenuId, $picPath)
    {
    $httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(env('LINE_BOT_CHANNEL_ACCESS_TOKEN'));
    $bot = new \LINE\LINEBot($httpClient, ['channelSecret' => env('LINE_BOT_CHANNEL_SECRET')]);
    $imagePath = public_path($picPath);
    $contentType = 'image/jpeg';
    $response = $bot->uploadRichMenuImage($richMenuId, $imagePath, $contentType);
    if ($response->isSucceeded()) {
    return true;
    } else {
    return false;
    }
    }

如何設置綁定用戶豐富菜單

  1. 新增圖文選單
  2. 上傳圖文選單圖片
  3. 與用戶做綁定

新增圖文選單與上傳圖文選單圖片與上述相似就不在貼程式碼,直接來看用戶綁定

將取得的圖文選單id以及line的user_id傳入即可綁定,可以在使用者連接官方帳號後進行

public function linkRichMenuToUser($user_id, $richMenuId)
{
$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(env('LINE_BOT_CHANNEL_ACCESS_TOKEN'));
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => env('LINE_BOT_CHANNEL_SECRET')]);
$response = $bot->linkRichMenu($user_id, $richMenuId);
if ($response->isSucceeded()) {
Log::info('Link rich menu to user success');
} else {
Log::error('Link rich menu to user failed');
}
}

取消用戶豐富菜單

lineuser id帶入,發送api即可解除綁定

public function unlinkRichMenuFromUser($user_id)
{
$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(env('LINE_BOT_CHANNEL_ACCESS_TOKEN'));
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => env('LINE_BOT_CHANNEL_SECRET')]);
$response = $bot->unlinkRichMenu($user_id);
if ($response->isSucceeded()) {
Log::info('Unlink rich menu from user success');
} else {
Log::error('Unlink rich menu from user failed');
}
}

LIFF基本使用

建立Liff

liff也就是line的前端框架,先新增一個新的channel來做測試

新增完後點擊ADD新增

可以看到有很多選項要選擇

Size

LIFF 瀏覽器可以以這三種尺寸之一顯示

(圖片來自於line developers)

Endpoint URL

這邊就是放入要開啟的連結,在點擊liff的連結後,會出現的頁面,假設填入https://www.google.com.tw/,開啟時就會是google的首頁

Scopes

這邊就是選擇需要取到哪些資料,點擊View all有一個chat_message.write,這個就是如果需要主動幫使用者發送資料,就必須打勾,不然sendMessages 會無法使用

這邊就是當使用者登入我們的liff時,要不要推薦他加入我們的官方line@,以下為normalaggressive差別

(圖片來自於line developers)

Scan QR

這邊指的是要不要使用 LIFF 打開 QR code 掃描器功能。

LIFF 建立完成

建立成功後可以看到我們剛剛新增的liff

橘色框框shareTargetPicker,就是是否允許主動讓使用者發送我們指定的訊息給他的好友,

LIFF ID 在寫 JavaScript 時會用到。

LIFF URL,這個就是 LIFF 的網址了,在 LINE 上點這個網址,就會開啟LIFF,顯示的頁面就是剛剛填入Endpoint URL的網址

LIFF init

初始化 LIFF 應用程式

引入sdk

CDN

<script charset="utf-8" src="https://static.line-scdn.net/liff/edge/2/sdk.js"></script>

使用 npm 包

終端中運行此命令以通過 npm 安裝 LIFF SDK
$ npm install --save @line/liff

或是透過 Yarn 安裝 LIFF SDK
$ yarn add @line/liff

import liff from '@line/liff';

liff.init({
liffId: '1234567890-AbcdEfgh', // Use own liffId
});

引入完成後透過 javascript 來撰寫

var liffID = 'XXXXXXXXXXXX';

liff.init({
liffId: liffID
}).then(function() {
console.log('LIFF init');

// 開始使用liff其他功能

}).catch(function(error) {
console.log(error);
});

liffID 做替換即可,因為 init 要先執行,所以是一個 promise,相關功能要撰寫在 then 函式中

LIFF獲取環境訊息

LIFF 可以取得一些使用者的環境資訊,條列如下:

  • 使用者運行 LIFF 應用程序的環境:web、android、ios
  • 頁面中的語系(lang)
  • 獲取 LIFF SDK 的版本
  • 獲取用戶的 LINE 版本
  • 確定 LIFF 應用程序是否在 LIFF 瀏覽器中運行
  • 檢查用戶是否已登錄。
  • 檢查指定的 API 在您啟動 LIFF 應用程序的環境中是否可用。
  • 獲取啟動 LIFF 應用程序的屏幕類型

程式碼如下:

// 回傳使用者作業系統:ios、android、web
liff.getOS();

// 引用 LIFF SDK 的頁面,頁面中的 lang 值
liff.getLanguage();

// LIFF SDK 的版本
liff.getVersion();

// 使用者的 LINE 版本
liff.getLineVersion();

// 回傳是否由 LINE App 存取
liff.isInClient();

// 使用者是否登入 LINE 帳號
liff.isLoggedIn();

// 是否啟用shareTargetPicker api
liff.isApiAvailable('shareTargetPicker')

// 獲取啟動 LIFF 應用程序的屏幕類型
liff.getContext()

LIFF 功能:登入、登出

登入、登出 LINE 的功能只能在外部瀏覽器時有作用。

不能在 LIFF 瀏覽器中使用liff.login(),因為它在執行時會自動liff.init()。

假設在登入後要轉址的網址是

https://example.com

必須先到 LINE Developers 的後台,在設定頁中將網址填入,這邊 Line 要確認我們是這個頻道的管理者,在這邊加入指定連接,可以防止被發現了我們的 ID 後,拿我們的 LIFF 來做登入動作竊取個資

如有多個網址就是,再往下一行,輸入完成後按下 Update ,就填寫完成

登入,登出程式碼

// 登入
if (!liff.isLoggedIn()) {
liff.login({
// 登入後要轉址到哪個網站
redirectUri:"https://example.com/path"
});
}

// 登出
liff.logout();

取得使用者資料

取得使用者公開資料

利用 liff.getProfile() 獲取當前用戶的個人資料信息

在新增 LIFF 應用程序時,在 Scopes 選項中請勾選 profile。如果沒有勾選,或者用戶未授予權限,您將無法獲取用戶配置文件。

liff
.getProfile()
.then((profile) => {
const name = profile.displayName;
})
.catch((err) => {
console.log("error", err);
});

取回來的資料為用戶ID,顯示名稱,圖片網址,狀態消息

{
"userId": "U4af4980629...",
"displayName": "Brown",
"pictureUrl": "https://profile.line-scdn.net/abcdefghijklmn",
"statusMessage": "Hello, LINE!"
}

取得Email

利用 liff.getDecodedIDToken() 取得用戶顯示名稱、個人資料圖片 URL、電子郵件地址等信息。

如要取得用戶email訊息需先至
Basic settings 找到 Email address permission 點擊 Apply

填寫以下資訊點擊送出

送出後就成功了

再到LIFF Scope設置將email打勾

如果使用者在授權頁面不允許存取email,那一樣取不到Email資訊

// 取得使用者 email
// 後台的 Email address permission 要是「Applied」
// LIFF 的設定,Scopes 的「email*」要打勾
// 使用者在登入時,「電子郵件帳號」也要是「許可」的
var user = liff.getDecodedIDToken();
var email = user.email;
console.log(email);

user資料如下

{
"iss":"",
"sub":"",
"aud":"",
"exp":,
"iat":,
"name":"xx",
"picture":"https://profile.line.jpg",
"email":"xxx@gmail.com"
}

請勿將此 API 獲取的用戶數據發送至服務器

如有需要在服務器取得用戶數據可以透過 liff.getAccessToken()token 傳送至服務器,在後台中取得

const accessToken = liff.getAccessToken();

const config = {
headers: { Authorization: `Bearer ${accessToken}` }
};
axios.post(
'https://api.line.me/v2/profile',
null,
config
).then((res) => {
console.log(`使用者資料: ${JSON.stringify(res.data)}`);
}).catch(console.log);

LIFF傳送訊息

LIFF傳送訊息有兩個:

  • sendMessages(): 發送至一對一用戶聊天室
  • shareTargetPicker(): 可選擇發送目標發送

sendMessages

需使用此功能,須將後台 Scopes 裡的chat_message.write 打勾,並且使用者在授權頁面,傳送訊息至聊天室 是許可狀態才可以使用

shareTargetPicker

此功能在LIFF設定頁面要將 shareTargetPicker 開啟,並且使用者在授權頁面,傳送訊息至聊天室 是許可狀態才能使用

程式碼

// 傳送訊息
// 訊息對象: https://developers.line.biz/en/reference/messaging-api/#message-objects
liff
.sendMessages([
{
type: "text",
text: "Hello, World!",
},
])
.then(() => {
console.log("message sent");
})
.catch((err) => {
console.log("error", err);
});


// 傳送訊息給好友
// https://developers.line.biz/en/reference/liff/#share-target-picker
liff.shareTargetPicker(
[
{
type: "text",
text: "Hello, World!",
},
],
{
isMultiple: true,
}
)
.then(function (res) {
if (res) {
// 成功通過目標選擇器發送消息
console.log(`[${res.status}] Message sent!`)
} else {
const [majorVer, minorVer] = (liff.getLineVersion() || "").split('.');
if (parseInt(majorVer) == 10 && parseInt(minorVer) < 11) {
// LINE 10.3.0 - 10.10.0
// 舊版本Line
console.log('目標選擇器已打開,有無成功發送不清楚')
} else {
// LINE 10.11.0 -
// sending message canceled
console.log('目標選擇器已關閉')
}
}
}).catch(function (error) {
// something went wrong before sending a message
console.log('something wrong happen')
})
}

LIFF 連結

取得當下連接

這邊取得的網址不是 Endpoint URL,而是 LIFF 的網址。

除了取得當前網址還可以替網址加上參數

// 取得當前網址
const myLink = liff.permanentLink.createUrl();

// 替網址加上參數
// For example, if current location is
// /food?menu=pizza
// (LIFF ID = 1234567890-AbcdEfgh)
liff.permanentLink.setExtraQueryParam("user_tracking_id=8888");
const myLink = liff.permanentLink.createUrl();

// myLink equals "https://liff.line.me/1234567890-AbcdEfgh/food?menu=pizza&user_tracking_id=8888"

LIFF掃描二維碼

在設置 LIFF 時須將 Scan QR打勾就可以使用

liff
.scanCodeV2()
.then((result) => {
// result = { value: "" }
})
.catch((error) => {
console.log("error", error);
});

LIFF開啟即關閉視窗

開啟視窗

在 LINE 的應用內瀏覽器或外部瀏覽器中打開指定的 URL,可以設置 external,為 true 時在外部瀏覽器開啟,false 則在 line 內部瀏覽器裡面開啟

liff.openWindow({
url: "https://line.me",
external: true,
});

關閉視窗

關閉LIFF應用程式

liff.closeWindow();

公開LIFF

如果要讓其他人可以使用 LIFF,要將他轉為公開

當它變成 Published 就大功告成拉