"laravel/framework": "^7.0",
"linecorp/line-bot-sdk": "^7.3"
以及
"laravel/framework": "^11.9",
"linecorp/line-bot-sdk": "^9.9",
此版本只撰寫LINE Message API 發送FLEX訊息,其他功能沒用到暫時懶的撰寫😵💫
首先先到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 Developer Document: Link user account )
User:
Provider’s bot server:
Provider’s web server:
LINE Platform:
順序分別為:
/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"
}
取得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);
}
}
當用戶訪問鏈接 URL
時,他們將看到您的服務的登錄屏幕。登錄後,您可以從您的服務中獲取用戶的 ID
。
官方說法是產生一個難以預測且只能使用一次的字符串的值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());
}
一旦 bot 服務器收到帳戶鏈接事件,就執行鏈接處理。
要鏈接的 LINE 用戶 ID 和步驟 4 中生成的 nonce 包含在 webhook 事件中。使用此 nonce 從您的服務中識別之前與 nonce 關聯並保存的用戶 ID。將此 ID 鏈接到 LINE 用戶 ID 後,帳戶鏈接將完成。
使用帳戶鏈接功能,需通知用戶有取消連結功能,並提供取消連結功能
以下為取消連接api
,line_id
為line
的user id
,user_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' => '解除綁定成功']);
}
(圖片來自於LINE Engineering)
有兩種方式可以創建豐富菜單一種是在line官方管理器設置,另一種是透過api方式設置
優先級別為以下(高到低)
Messaging API
替用戶設置豐富菜單Messaging API
設置的默認豐富菜單此範例為新增六格圖文選單,分為三個階段
圖文選單選項
size: 圖文選單圖片的長寬,必需為以下尺寸:
2500x1686
、2500x843
、1200x810
、1200x405
、800x540
、800x270
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;
}
}
新增圖文選單與上傳圖文選單圖片與上述相似就不在貼程式碼,直接來看用戶綁定
將取得的圖文選單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');
}
}
將line
的user 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');
}
}
在這個版本中,申請並使用一些 token 後,你需要做一個額外的步驟,和之前版本不同的是,這次在安裝完後需要發布設定檔案:
php artisan vendor:publish --provider="LINE\Laravel\LINEBotServiceProvider" --tag=config
然後,打開 .env 檔案,並填入以下所需的設定參數:
LINE_BOT_CHANNEL_ACCESS_TOKEN=
LINE_BOT_CHANNEL_SECRET=
LINE_BOT_CHANNEL_ID=
接下來,我們將示範如何使用 LINE API 發送像下面這種 Flex Message 模版:
以下是發送此類 Flex 訊息的範例程式碼:
public function sendFlexMsg()
{
$lineUID = '你要發送的 Line UID';
$heroImage = new FlexImage([
'type' => 'image',
'url' => 'https://developers-resource.landpress.line.me/fx/img/01_1_cafe.png',
'size' => 'full',
'aspectRatio' => '20:13',
'aspectMode' => 'cover',
'action' => [
'type' => 'uri',
'uri' => 'https://line.me/',
]
]);
$orderStatusBox = new FlexBox([
'type' => 'box',
'layout' => FlexBox::LAYOUT_BASELINE,
'spacing' => 'sm',
'contents' => [
new FlexText([
'type' => 'text',
'text' => '訂單狀態',
'flex' => 1,
'color' => '#94a3b8',
'size' => 'sm'
]),
new FlexText([
'type' => 'text',
'text' => '店家已接單',
'flex' => 3,
'size' => 'xl',
'color' => '#f86259',
'weight' => 'bold',
'wrap' => true
])
],
]);
$mealPickupNumberBox = new FlexBox([
'type' => 'box',
'layout' => FlexBox::LAYOUT_BASELINE,
'spacing' => 'sm',
'contents' => [
new FlexText([
'type' => 'text',
'text' => '取餐編號',
'flex' => 1,
'color' => '#94a3b8',
'size' => 'sm'
]),
new FlexText([
'type' => 'text',
'text' => '#123456',
'flex' => 3,
'size' => 'sm',
'color' => '#606266',
'wrap' => true
])
],
]);
$mealPickupTimeBox = new FlexBox([
'type' => 'box',
'layout' => FlexBox::LAYOUT_BASELINE,
'spacing' => 'sm',
'contents' => [
new FlexText([
'type' => 'text',
'text' => '取餐時間',
'flex' => 1,
'color' => '#94a3b8',
'size' => 'sm'
]),
new FlexText([
'type' => 'text',
'flex' => 3,
'color' => '#f86259',
'contents' => [
new FlexSpan([
'type' => 'span',
'text' => '2024-08-16 ',
'size' => 'sm',
'color' => '#f86259',
]),
new FlexSpan([
'type' => 'span',
'text' => '12:15',
'size' => 'sm',
'color' => '#f86259',
'weight' => 'bold',
]),
]
])
],
]);
$pickupLocationBox = new FlexBox([
'type' => 'box',
'layout' => FlexBox::LAYOUT_BASELINE,
'spacing' => 'sm',
'contents' => [
new FlexText([
'type' => 'text',
'text' => '取餐地點',
'flex' => 1,
'color' => '#94a3b8',
'size' => 'sm'
]),
new FlexText([
'type' => 'text',
'text' => "店家地址",
'flex' => 3,
'size' => 'sm',
'color' => '#606266',
'wrap' => true
])
],
]);
$orderPriceBox = new FlexBox([
'type' => 'box',
'layout' => FlexBox::LAYOUT_BASELINE,
'spacing' => 'sm',
'contents' => [
new FlexText([
'type' => 'text',
'text' => '訂單金額',
'flex' => 1,
'color' => '#94a3b8',
'size' => 'sm'
]),
new FlexText([
'type' => 'text',
'text' => "NT$ 600",
'flex' => 3,
'size' => 'sm',
'color' => '#606266',
'wrap' => true,
'weight' => 'regular',
])
],
]);
$paymentStatusBox = new FlexBox([
'type' => 'box',
'layout' => FlexBox::LAYOUT_BASELINE,
'spacing' => 'sm',
'contents' => [
new FlexText([
'type' => 'text',
'text' => '結帳狀態',
'flex' => 1,
'color' => '#94a3b8',
'size' => 'sm'
]),
new FlexText([
'type' => 'text',
'text' => "已付款(信用卡支付)",
'flex' => 3,
'size' => 'sm',
'color' => '#606266',
'wrap' => true,
'weight' => 'regular',
])
],
]);
$bodyBox = new FlexBox([
'type' => 'box',
'layout' => FlexBox::LAYOUT_VERTICAL,
'contents' => [
new FlexText([
'type' => 'text',
'text' => "店家名稱",
'weight' => 'bold',
'size' => 'lg',
'margin' => 'sm',
'color' => '#FAAE3F',
'wrap' => true
]),
new FlexText([
'type' => 'text',
'text' => '店家已確認並開始準備您的餐點!請稍候。',
'size' => 'xs',
'margin' => 'sm',
'color' => '#94a3b8',
'wrap' => true
]),
new FlexSeparator([
'type' => 'separator',
'margin' => 'sm'
]),
$orderStatusBox,
$mealPickupNumberBox,
$mealPickupTimeBox,
$pickupLocationBox,
$orderPriceBox,
$paymentStatusBox
],
'spacing' => 'xs',
'margin' => 'none'
]);
$footerBox = new FlexBox([
'type' => 'box',
'layout' => FlexBox::LAYOUT_VERTICAL,
'flex' => 0,
'contents' => [
new FlexButton([
'type' => 'button',
'action' => [
'type' => 'uri',
'label' => '查看訂單詳情',
'uri' => "https://line.me/",
],
'height' => 'md',
'style' => 'primary',
'color' => '#f86259',
'scaling' => true
]),
],
]);
// Setting up the footer style
$footerStyle = new FlexBlockStyle([
'separator' => true, // Example: Using a separator
]);
$styles = new FlexBubbleStyles();
$styles->setFooter($footerStyle);
$bubble = new FlexBubble([
'type' => 'bubble',
'styles' => $styles,
'hero' => $heroImage,
'body' => $bodyBox,
'footer' => $footerBox
]);
$flexMessageBuilder = new FlexMessage([
'type' => 'flex',
'altText' => '店家開始準備餐點',
'contents' => $bubble
]);
$msgRequest = new PushMessageRequest([
'to' => $lineUID,
'messages' => [$flexMessageBuilder]
]);
LINEMessagingApi::pushMessage($msgRequest);
}
liff
也就是line
的前端框架,先新增一個新的channel
來做測試
新增完後點擊ADD
新增
可以看到有很多選項要選擇
LIFF 瀏覽器可以以這三種尺寸之一顯示
(圖片來自於line developers)
這邊就是放入要開啟的連結,在點擊liff的連結後,會出現的頁面,假設填入https://www.google.com.tw/
,開啟時就會是google
的首頁
這邊就是選擇需要取到哪些資料,點擊View all
有一個chat_message.write
,這個就是如果需要主動幫使用者發送資料,就必須打勾,不然sendMessages
會無法使用
這邊就是當使用者登入我們的liff時,要不要推薦他加入我們的官方line@,以下為normal
及aggressive
差別
(圖片來自於line developers)
這邊指的是要不要使用 LIFF 打開 QR code 掃描器功能。
建立成功後可以看到我們剛剛新增的liff
橘色框框shareTargetPicker
,就是是否允許主動讓使用者發送我們指定的訊息給他的好友,
LIFF ID
在寫 JavaScript
時會用到。
LIFF URL
,這個就是 LIFF
的網址了,在 LINE
上點這個網址,就會開啟LIFF
,顯示的頁面就是剛剛填入Endpoint URL
的網址
初始化 LIFF 應用程式
<script charset="utf-8" src="https://static.line-scdn.net/liff/edge/2/sdk.js"></script>
終端中運行此命令以通過 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 可以取得一些使用者的環境資訊,條列如下:
程式碼如下:
// 回傳使用者作業系統: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()
登入、登出 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!"
}
利用 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傳送訊息有兩個:
需使用此功能,須將後台 Scopes 裡的chat_message.write 打勾,並且使用者在授權頁面,傳送訊息至聊天室 是許可狀態才可以使用
此功能在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')
})
}
這邊取得的網址不是 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 時須將 Scan QR打勾就可以使用
liff
.scanCodeV2()
.then((result) => {
// result = { value: "" }
})
.catch((error) => {
console.log("error", error);
});
在 LINE 的應用內瀏覽器或外部瀏覽器中打開指定的 URL,可以設置 external
,為 true
時在外部瀏覽器開啟,false
則在 line
內部瀏覽器裡面開啟
liff.openWindow({
url: "https://line.me",
external: true,
});
關閉LIFF應用程式
liff.closeWindow();
如果要讓其他人可以使用 LIFF,要將他轉為公開
當它變成 Published
就大功告成拉