├── Procfile ├── app.json ├── index.js ├── package.json ├── public ├── style.css ├── index.html └── liff-starter.js ├── LICENSE.txt └── README.md /Procfile: -------------------------------------------------------------------------------- 1 | web: node index.js -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LINE LIFF v2 Starter", 3 | "description": "Sample LIFF v2 application", 4 | "repository": "https://github.com/line/line-liff-v2-starter" 5 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const port = process.env.PORT || 5000; 4 | const myLiffId = process.env.MY_LIFF_ID; 5 | 6 | app.use(express.static('public')); 7 | 8 | app.get('/send-id', function(req, res) { 9 | res.json({id: myLiffId}); 10 | }); 11 | 12 | app.listen(port, () => console.log(`app listening on port ${port}!`)); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "line-liff-v2-starter", 3 | "version": "1.0.0", 4 | "description": "This is a small web application that demonstrates the basic functionality of the [LINE Front-end Framework (LIFF)](https://developers.line.biz/en/docs/liff/overview/).", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/line/line-liff-v2-starter" 13 | }, 14 | "license": "MIT", 15 | "dependencies": { 16 | "express": "^4.17.1" 17 | }, 18 | "engines": { 19 | "node": "10.x" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /public/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 11px; 3 | } 4 | 5 | table { 6 | width: 100%; 7 | table-layout: fixed; 8 | word-break: break-all; 9 | } 10 | 11 | div { 12 | max-width: 100%; 13 | text-align: center; 14 | } 15 | 16 | th { 17 | text-align: center; 18 | } 19 | 20 | table, th, td { 21 | border: 1px solid black; 22 | } 23 | 24 | img { 25 | max-width: 25%; 26 | height: auto; 27 | } 28 | 29 | button { 30 | margin: 4px; 31 | } 32 | 33 | #code-block { 34 | background-color: #eee; 35 | border: 1px solid #999; 36 | display: block; 37 | padding: 20px; 38 | width: 50%; 39 | margin-left: auto; 40 | margin-right: auto; 41 | overflow-x: auto; 42 | white-space: nowrap; 43 | } 44 | 45 | #profilePictureDiv { 46 | text-align: center; 47 | } 48 | 49 | #profileImageDiv { 50 | height: 100px; 51 | width: 100px; 52 | } 53 | 54 | #statusMessage { 55 | position: relative; 56 | top: 40px; 57 | } 58 | 59 | .textLeft { 60 | text-align: left; 61 | } 62 | 63 | .buttonGroup { 64 | padding-top: 20px; 65 | } 66 | 67 | .hidden { 68 | display: none; 69 | } 70 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 LINE Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | LIFF Starter 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 | 15 | 16 |
17 |
18 | 19 | 20 |
21 |
22 | 23 | 24 |
25 |
26 | 27 |
28 |
29 |
30 | 31 | 41 | 42 | 52 | 53 | 73 | 74 |
75 |

LIFF Data

76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 |
OS
Language
LIFF SDK Version
LINE Version
isInClient
isLoggedIn
102 |
103 | 104 |
105 | 106 | 107 |
108 |
109 |
110 |
111 |

Available LIFF methods vary depending on the browser you use to open the LIFF app.

112 |

Please refer to the API reference page for more information.

113 |
114 |
115 |
116 | 117 | 132 | 133 | 137 | 138 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /public/liff-starter.js: -------------------------------------------------------------------------------- 1 | window.onload = function() { 2 | const useNodeJS = true; // if you are not using a node server, set this value to false 3 | const defaultLiffId = ""; // change the default LIFF value if you are not using a node server 4 | 5 | // DO NOT CHANGE THIS 6 | let myLiffId = ""; 7 | 8 | // if node is used, fetch the environment variable and pass it to the LIFF method 9 | // otherwise, pass defaultLiffId 10 | if (useNodeJS) { 11 | fetch('/send-id') 12 | .then(function(reqResponse) { 13 | return reqResponse.json(); 14 | }) 15 | .then(function(jsonResponse) { 16 | myLiffId = jsonResponse.id; 17 | initializeLiffOrDie(myLiffId); 18 | }) 19 | .catch(function(error) { 20 | document.getElementById("liffAppContent").classList.add('hidden'); 21 | document.getElementById("nodeLiffIdErrorMessage").classList.remove('hidden'); 22 | }); 23 | } else { 24 | myLiffId = defaultLiffId; 25 | initializeLiffOrDie(myLiffId); 26 | } 27 | }; 28 | 29 | /** 30 | * Check if myLiffId is null. If null do not initiate liff. 31 | * @param {string} myLiffId The LIFF ID of the selected element 32 | */ 33 | function initializeLiffOrDie(myLiffId) { 34 | if (!myLiffId) { 35 | document.getElementById("liffAppContent").classList.add('hidden'); 36 | document.getElementById("liffIdErrorMessage").classList.remove('hidden'); 37 | } else { 38 | initializeLiff(myLiffId); 39 | } 40 | } 41 | 42 | /** 43 | * Initialize LIFF 44 | * @param {string} myLiffId The LIFF ID of the selected element 45 | */ 46 | function initializeLiff(myLiffId) { 47 | liff 48 | .init({ 49 | liffId: myLiffId 50 | }) 51 | .then(() => { 52 | // start to use LIFF's api 53 | initializeApp(); 54 | }) 55 | .catch((err) => { 56 | document.getElementById("liffAppContent").classList.add('hidden'); 57 | document.getElementById("liffInitErrorMessage").classList.remove('hidden'); 58 | }); 59 | } 60 | 61 | /** 62 | * Initialize the app by calling functions handling individual app components 63 | */ 64 | function initializeApp() { 65 | displayLiffData(); 66 | displayIsInClientInfo(); 67 | registerButtonHandlers(); 68 | 69 | // check if the user is logged in/out, and disable inappropriate button 70 | if (liff.isLoggedIn()) { 71 | document.getElementById('liffLoginButton').disabled = true; 72 | } else { 73 | document.getElementById('liffLogoutButton').disabled = true; 74 | } 75 | } 76 | 77 | /** 78 | * Display data generated by invoking LIFF methods 79 | */ 80 | function displayLiffData() { 81 | document.getElementById('browserLanguage').textContent = liff.getLanguage(); 82 | document.getElementById('sdkVersion').textContent = liff.getVersion(); 83 | document.getElementById('lineVersion').textContent = liff.getLineVersion(); 84 | document.getElementById('isInClient').textContent = liff.isInClient(); 85 | document.getElementById('isLoggedIn').textContent = liff.isLoggedIn(); 86 | document.getElementById('deviceOS').textContent = liff.getOS(); 87 | } 88 | 89 | /** 90 | * Toggle the login/logout buttons based on the isInClient status, and display a message accordingly 91 | */ 92 | function displayIsInClientInfo() { 93 | if (liff.isInClient()) { 94 | document.getElementById('liffLoginButton').classList.toggle('hidden'); 95 | document.getElementById('liffLogoutButton').classList.toggle('hidden'); 96 | document.getElementById('isInClientMessage').textContent = 'You are opening the app in the in-app browser of LINE.'; 97 | } else { 98 | document.getElementById('isInClientMessage').textContent = 'You are opening the app in an external browser.'; 99 | document.getElementById('shareTargetPicker').classList.toggle('hidden'); 100 | } 101 | } 102 | 103 | /** 104 | * Register event handlers for the buttons displayed in the app 105 | */ 106 | function registerButtonHandlers() { 107 | // openWindow call 108 | document.getElementById('openWindowButton').addEventListener('click', function() { 109 | liff.openWindow({ 110 | url: 'https://line.me', 111 | external: true 112 | }); 113 | }); 114 | 115 | // closeWindow call 116 | document.getElementById('closeWindowButton').addEventListener('click', function() { 117 | if (!liff.isInClient()) { 118 | sendAlertIfNotInClient(); 119 | } else { 120 | liff.closeWindow(); 121 | } 122 | }); 123 | 124 | // sendMessages call 125 | document.getElementById('sendMessageButton').addEventListener('click', function() { 126 | if (!liff.isInClient()) { 127 | sendAlertIfNotInClient(); 128 | } else { 129 | liff.sendMessages([{ 130 | 'type': 'text', 131 | 'text': "You've successfully sent a message! Hooray!" 132 | }]).then(function() { 133 | window.alert('Message sent'); 134 | }).catch(function(error) { 135 | window.alert('Error sending message: ' + error); 136 | }); 137 | } 138 | }); 139 | 140 | // scanCode call 141 | document.getElementById('scanQrCodeButton').addEventListener('click', function() { 142 | if (!liff.isInClient()) { 143 | sendAlertIfNotInClient(); 144 | } else { 145 | liff.scanCode().then(result => { 146 | // e.g. result = { value: "Hello LIFF app!" } 147 | const stringifiedResult = JSON.stringify(result); 148 | document.getElementById('scanQrField').textContent = stringifiedResult; 149 | toggleQrCodeReader(); 150 | }).catch(err => { 151 | document.getElementById('scanQrField').textContent = "scanCode failed!"; 152 | }); 153 | } 154 | }); 155 | 156 | // get access token 157 | document.getElementById('getAccessToken').addEventListener('click', function() { 158 | if (!liff.isLoggedIn() && !liff.isInClient()) { 159 | alert('To get an access token, you need to be logged in. Please tap the "login" button below and try again.'); 160 | } else { 161 | const accessToken = liff.getAccessToken(); 162 | document.getElementById('accessTokenField').textContent = accessToken; 163 | toggleAccessToken(); 164 | } 165 | }); 166 | 167 | // get profile call 168 | document.getElementById('getProfileButton').addEventListener('click', function() { 169 | liff.getProfile().then(function(profile) { 170 | document.getElementById('userIdProfileField').textContent = profile.userId; 171 | document.getElementById('displayNameField').textContent = profile.displayName; 172 | 173 | const profilePictureDiv = document.getElementById('profilePictureDiv'); 174 | if (profilePictureDiv.firstElementChild) { 175 | profilePictureDiv.removeChild(profilePictureDiv.firstElementChild); 176 | } 177 | const img = document.createElement('img'); 178 | img.src = profile.pictureUrl; 179 | img.alt = 'Profile Picture'; 180 | profilePictureDiv.appendChild(img); 181 | 182 | document.getElementById('statusMessageField').textContent = profile.statusMessage; 183 | toggleProfileData(); 184 | }).catch(function(error) { 185 | window.alert('Error getting profile: ' + error); 186 | }); 187 | }); 188 | 189 | document.getElementById('shareTargetPicker').addEventListener('click', function () { 190 | if (liff.isApiAvailable('shareTargetPicker')) { 191 | liff.shareTargetPicker([{ 192 | 'type': 'text', 193 | 'text': 'Hello, World!' 194 | }]).then( 195 | document.getElementById('shareTargetPickerMessage').textContent = "Share target picker was launched." 196 | ).catch(function (res) { 197 | document.getElementById('shareTargetPickerMessage').textContent = "Failed to launch share target picker."; 198 | }); 199 | } 200 | }); 201 | 202 | // login call, only when external browser is used 203 | document.getElementById('liffLoginButton').addEventListener('click', function() { 204 | if (!liff.isLoggedIn()) { 205 | // set `redirectUri` to redirect the user to a URL other than the front page of your LIFF app. 206 | liff.login(); 207 | } 208 | }); 209 | 210 | // logout call only when external browse 211 | document.getElementById('liffLogoutButton').addEventListener('click', function() { 212 | if (liff.isLoggedIn()) { 213 | liff.logout(); 214 | window.location.reload(); 215 | } 216 | }); 217 | } 218 | 219 | /** 220 | * Alert the user if LIFF is opened in an external browser and unavailable buttons are tapped 221 | */ 222 | function sendAlertIfNotInClient() { 223 | alert('This button is unavailable as LIFF is currently being opened in an external browser.'); 224 | } 225 | 226 | /** 227 | * Toggle access token data field 228 | */ 229 | function toggleAccessToken() { 230 | toggleElement('accessTokenData'); 231 | } 232 | 233 | /** 234 | * Toggle profile info field 235 | */ 236 | function toggleProfileData() { 237 | toggleElement('profileInfo'); 238 | } 239 | 240 | /** 241 | * Toggle scanCode result field 242 | */ 243 | function toggleQrCodeReader() { 244 | toggleElement('scanQr'); 245 | } 246 | 247 | /** 248 | * Toggle specified element 249 | * @param {string} elementId The ID of the selected element 250 | */ 251 | function toggleElement(elementId) { 252 | const elem = document.getElementById(elementId); 253 | if (elem.offsetWidth > 0 && elem.offsetHeight > 0) { 254 | elem.style.display = 'none'; 255 | } else { 256 | elem.style.display = 'block'; 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LIFF v2 starter app 2 | 3 | This is a small web application that demonstrates the basic functionality of the [LINE Front-end Framework (LIFF)](https://developers.line.biz/en/docs/liff/overview/). 4 | 5 | ## Deploy methods 6 | 7 | Depending on how you want to use LIFF, choose one of these methods for deploying the LIFF v2 starter app: 8 | 9 | - If you merely want to try the functions LIFF offers, see [Use Heroku button to deploy the app without using the terminal](#Use-Heroku-button-to-deploy-the-app-without-using-the-terminal) 10 | - If you want to develop a LIFF app using Heroku and Node.js, see [Customize the app and deploy it on Heroku via the terminal](#Customize-the-app-and-deploy-it-on-Heroku-via-the-terminal) 11 | - If you want to develop a LIFF app using a server platform of your choice, see [Use any other server platform](#deploy-the-app-using-any-other-server-platform) 12 | 13 | ## Use Heroku button to deploy the app without using the terminal 14 | 15 | Follow the below instructions to deploy your app using the Heroku button and Node.js without customization. 16 | 17 | ### What you'll need 18 | 19 | | Item | Description | 20 | | ---- | ----------- | 21 | | LINE Messaging API channel | A channel forms the connection between your app and the LINE Platform. Create a channel on the [LINE Developers console](https://developers.line.biz/console/register/messaging-api/channel/). | 22 | | Heroku account (optional) | [Heroku](https://www.heroku.com) is a cloud service that lets you deploy and serve web apps for free. You don't need a Heroku account if you're [deploying the app on another platform](#deploy-the-app-using-any-other-server-platform). | 23 | 24 | ### Deploy the app using 'Deploy to Heroku' button 25 | 26 | [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/line/line-liff-v2-starter) 27 | 28 | 1. Click **Deploy to Heroku** above. 29 | 2. On the "Create New App" page in Heroku, fill in the required information. 30 | 3. Click **Deploy app**. 31 | 4. Click **View** to confirm that your app is successfully deployed. You should see a page with the text "You have not assigned any value for LIFF ID". 32 | 5. Take a note of your app's URL (`https://{Heroku app name}.herokuapp.com`). You'll need it when you add the app to LIFF. 33 | 34 | ### Add the starter app to LIFF 35 | 36 | 1. Follow the instructions on the page [Adding a LIFF app](https://developers.line.biz/en/docs/liff/registering-liff-apps/). 37 | 2. Take a note of your LIFF ID, because you'll need it for the next part. The LIFF ID is the final part of the **LIFF URL** shown in the console: `https://liff.line.me/{liffId}`. 38 | 3. Locate the **Scope** option and click the **Edit** button. 39 | 4. Click the **View all** option and enable `chat_message.write`. This scope is required for the LIFF app to send messages on behalf of the user. 40 | 5. Change the status of LIFF app to **Published**. 41 | 42 | ### Pass your LIFF ID to the app using an environment variable 43 | 44 | 1. In Heroku, go to [Dashboard](https://dashboard.heroku.com/). 45 | 2. Select your app. 46 | 3. On the **Settings** tab, click **Reveal Config Vars**. 47 | 4. Enter a new key called `MY_LIFF_ID` with your LIFF ID as the value. 48 | 5. Click **Add** to save. 49 | 6. Browse back to your app's URL (`https://{Heroku app name}.herokuapp.com`) and confirm that your app is operational. You should see a number of buttons, such as **Open External Window** and **Close LIFF App**. 50 | 51 | For more information about how to try the app, see [Trying the app](#trying-the-app). 52 | 53 | ### Checking logs 54 | 55 | To get more information, you can check your app's logs using Heroku's GUI or [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli). 56 | 57 | #### Check your app's logs using Heroku's GUI 58 | 59 | To get more information, check your app's logs online: 60 | 61 | 1. In Heroku, go to [Dashboard](https://dashboard.heroku.com/). 62 | 2. Select the app you just created. 63 | 3. In the top-right corner, click **More**. 64 | 4. Click **View logs**. 65 | 66 | You'll find the log under **Application Logs**. 67 | 68 | #### Check your app's logs using Heroku CLI 69 | 70 | 1. Log in to Heroku from the command line (if you haven't already). 71 | 72 | ```shell 73 | $ heroku login 74 | ``` 75 | 76 | 2. Check the logs. 77 | 78 | ```shell 79 | $ heroku logs --app {Heroku app name} --tail 80 | ``` 81 | 82 | 83 | ## Customize the app and deploy it on Heroku via the terminal 84 | 85 | Follow the below instructions to deploy your customized app using Heroku and Node.js. 86 | 87 | ### Install the app on your local machine 88 | 89 | 1. Make sure you have the following installed. 90 | 91 | - [Git](https://git-scm.com/) 92 | - [Node.js](https://nodejs.org/en/) 93 | - Items listed [here](#what-youll-need) 94 | 95 | 2. Clone the [line-liff-starter](https://github.com/line/line-liff-v2-starter) GitHub repository. 96 | 97 | ```shell 98 | git clone https://github.com/line/line-liff-v2-starter 99 | ``` 100 | 3. `cd` into `line-liff-v2-starter` directory. 101 | 102 | 4. Install the dependencies by running: 103 | ```shell 104 | $ npm install 105 | ``` 106 | 107 | ### Link your local repository to Heroku 108 | 109 | 1. Log in to Heroku from the command line. 110 | 111 | ```shell 112 | $ heroku login 113 | ``` 114 | 115 | 2. Create a named Heroku app. 116 | 117 | ```shell 118 | $ heroku create {Heroku app name} 119 | ``` 120 | 121 | 3. Take a note of your app's URL (`https://{Heroku app name}.herokuapp.com`). You'll need it when you add the app to LIFF. 122 | 123 | 4. Add a remote for Heroku to your local repository. 124 | 125 | ```shell 126 | $ heroku git:remote -a {Heroku app name} 127 | ``` 128 | 129 | ### Add the starter app to LIFF 130 | 131 | 1. Follow the instructions on the page [Adding a LIFF app](https://developers.line.biz/en/docs/liff/registering-liff-apps/). 132 | 2. Take a note of your LIFF ID, because you'll need it for the next part. The LIFF ID is the final part of the LIFF URL shown in the console: `line://app/{liffId}` 133 | 134 | ### Customize and deploy the app via terminal 135 | 136 | 1. Set your LIFF ID using an environment variable. 137 | 138 | ```shell 139 | heroku config:set MY_LIFF_ID={liffId} 140 | ``` 141 | 142 | 2. Copy your environment variable into the `.env` file for local testing. 143 | 144 | Heroku recommends setting up an `.env` file to use an environment variable in a local environment. 145 | ```shell 146 | $ heroku config:get MY_LIFF_ID -s >> .env 147 | ``` 148 | Note: Don't commit the `.env` file to GitHub. To exclude it, add the `.env` file to your `.gitignore`. 149 | 150 | 3. Customize your app. For more information about available LIFF methods, see [API reference](https://developers.line.biz/en/reference/liff/). 151 | 152 | 4. Run the app locally to preview your changes: 153 | 154 | ```shell 155 | heroku local 156 | ``` 157 | View the app by browsing to [localhost:5000](http://localhost:5000/). 158 | 159 | 5. If you're happy with your changes, stage, commit, and deploy the app. 160 | 161 | ```shell 162 | $ git add . 163 | $ git commit -m "My first commit" 164 | $ git push heroku master 165 | ``` 166 | 167 | 6. Browse to your app's URL (`https://{Heroku app name}.herokuapp.com`) and confirm that your app is operational. You should see a number of buttons, such as **Open External Window** and **Close LIFF App**. 168 | 169 | 7. Lastly, check whether your channel status is **Published**. 170 | 171 | For more information about how to try the app, see [Trying the app](#trying-the-app). 172 | 173 | ### Checking logs 174 | 175 | To get more information, check your app's logs using Heroku's GUI or [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli). 176 | Refer to [this section](#checking-logs) for more information. 177 | 178 | ## Deploy the app using any other server platform 179 | 180 | Follow the below instructions to deploy your app using the server platform of your choice. 181 | 182 | ### Prerequisites 183 | | Item | Description | 184 | | ---- | ----------- | 185 | | LINE Messaging API channel | A channel forms the connection between your app and the LINE Platform. Create a channel on the [LINE Developers console](https://developers.line.biz/console/register/messaging-api/channel/). | 186 | 187 | 188 | ### Clone the repository 189 | 190 | 1. Clone the [line-liff-starter](https://github.com/line/line-liff-v2-starter) repository. 191 | 192 | ```shell 193 | git clone https://github.com/line/line-liff-v2-starter 194 | ``` 195 | 196 | 2. `cd` into `line-liff-v2-starter` directory. 197 | 198 | ### Prepare your app and server 199 | 200 | 1. Set the `useNodeJS` variable to `false` in `public/liff-starter.js`. 201 | 202 | ```shell 203 | const useNodeJS = false; 204 | ``` 205 | 2. Remove Heroku and Node.js specific files (`app.json` , `index.js`, `package.json`, and `Procfile`) from your workspace. 206 | 3. Host the files on a web server. 207 | 208 | ### Add the starter app to LIFF 209 | 210 | 1. Follow the instructions on the page [Adding a LIFF app](https://developers.line.biz/en/docs/liff/registering-liff-apps/). 211 | 2. Take a note of your LIFF ID, because you'll need it for the next part. The LIFF ID is the final part of the LIFF URL shown in the console: `line://app/{liffId}` 212 | 213 | 3. Set your LIFF ID to the `defaultLiffId` variable in `public/liff-starter.js`. 214 | ```shell 215 | const defaultLiffId = "{liffId}"; 216 | ``` 217 | 218 | ## Trying the app 219 | 220 | ### Try the app in LINE 221 | 222 | You can open your LIFF app in LINE by creating a simple link from any chat: 223 | 224 | 1. In any LINE chat, type `line://app/{liffId}` and send the message. (For example, if your LIFF ID is `123`, send the message `line://app/123`.) 225 | 2. Tap the link in your own message. 226 | 3. Agree to grant the required permissions to the LIFF app. 227 | 228 | ### Try the app in your browser 229 | 230 | To open your LIFF app in your browser, enter the app's Heroku URL: `https://{Heroku app name}.herokuapp.com` 231 | 232 | ## App features 233 | 234 | You'll find the following buttons in the starter app. 235 | 236 | ℹ️ Some buttons are available only in either LINE's in-app browser or in a regular browser. See also the [API reference](https://developers.line.biz/en/reference/liff/). 237 | 238 | | Button | Description | LINE browser | Regular browser | 239 | | ------ | ----------- | :------------: | :---------------: | 240 | | Open External Window | Opens `https://line.me` in LINE's in-app browser. | ✅ | ✅ | 241 | | Close LIFF App | Closes the LIFF app. | ✅ | ❌ | 242 | | Open QR Code Reader | Opens the QR code reader and outputs the result.
⚠️ **Due to a technical issue, `liff.scanCode()` is temporarily unavailable on LINE for iOS v9.19.0 and later.**
| ✅ | ❌ | 243 | | Send Message | Sends a sample message on behalf of the user if the LIFF app is opened in the chat screen. | ✅ | ❌ | 244 | | Get Access Token | Gets the current user's access token. | ✅ | ✅ | 245 | | Get Profile | Gets the current user's profile. | ✅ | ✅ | 246 | | Open Share Target Picker | Displays the target picker (screen for selecting a group or friend) and sends a sample message to the selected target. | ✅ | ❌ | 247 | | Log In | Performs LINE Login for web apps. Once the user is authenticated and authorized, the LIFF app will be able to obtain information such as access token and user profile. | ❌ | ✅ | 248 | | Log Out | Logs out the user. | ✅ | ✅ | 249 | 250 | For API calls associated with the buttons, see [Calling the LIFF API](https://developers.line.biz/en/docs/liff/developing-liff-apps#calling-liff-api). 251 | 252 | [heroku-cli]: https://devcenter.heroku.com/articles/heroku-cli 253 | [liff-api-ref]: https://developers.line.biz/en/reference/liff/ 254 | [calling-liff-api]: https://developers.line.biz/en/docs/liff/developing-liff-apps#calling-liff-api 255 | --------------------------------------------------------------------------------