環境 |
Visual Studio 2015 C# + MSSQL 2014 + Azure DB |
目的: |
當用戶加入LineBot後,可以與企業做相關聯的個人資料存取的功能。 這邊以銀行個人用戶查詢、存款、登入、登出做模擬應用 |
為何: | 最近找工作,面試提到的應用課題,覺得很有意思,故而做初步的簡易版本 |
Github: | https://github.com/gotoa1234/LineLoginExample |
本篇分為四部分: | |
一、 | 銀行餘額情境說明 + 手機上呈現的畫面 |
二、 | 開啟LineBot管理者平台,提供選單給使用者 |
三、 | 程式碼架構說明(Database) |
四、 | 實作LineAPI的4種功能 + 驗證方法 |
五、 | Line用戶Demo體驗 |
系列文章:
0001. Azure + LineBot 程式架設教學 : https://dotblogs.com.tw/milkgreenteaprograme_c_sharp/2016/12/29/001512
0002. 取得機器人好友帳號ID + 發送資料的實作(Line API Push Message) : https://dotblogs.com.tw/milkgreenteaprograme_c_sharp/2018/05/13/214926
一、銀行餘額情境說明 + 手機上呈現的畫面
Step 1:以下是系統架構流程圖
Step 2: 對用戶來說,加了Line Bot 的選單畫面:
說明 | |
1. 登入 | 用戶必須登入才可以進行 2 , 3的操作 |
2. 查詢銀行餘額 | 用戶查詢自己銀行帳戶的金額 |
3. 修改餘額 | 用戶需要存款、取款的【模擬操作】 |
4. 登出 | 用戶於Line上登出,即可避免他人操作個人資料 |
二、開啟LineBot管理者平台,提供選單給使用者
Step 1:我們進入 Line Manager -> 管理畫面 ->登入
Step 2: 建立圖文影音內容 -> 圖文選單 -> 新增
Step 3: 以下是各項目說明,如嫌麻煩可以直接複製上面的選項:
使用期間: | 在指定的時間範圍內用戶才會看到按鈕選單 |
標題 | 按鈕標題 |
選單顯示設定 |
直接選單:一打開LineBot時自動彈開 用戶點選展開:手動展開 |
選擇樣板 |
選擇樣板 :這邊用內建的圖標,如要客製化可以選 【以圖片製作】 |
選單內容設定 |
關鍵字: 抱歉沒研究 網址:當點擊時,直接彈出URL 文字:當點擊時,直接幫用戶輸入文字 |
三、程式碼架構說明(Database)
Step 1:程式分成3個Libary + 1個MVC Web應用專案
功能 | 參考對象 | |
1. LineLoginExample | LineBOT API + 登入頁面 | 2,4 |
2. CommonLibary | 共用的Model | |
3. Repository | 對DB進行CRUD的操作 | 2 |
4. Service | API呼叫時進行商業邏輯的組合 | 2,3 |
Step 2 : 記錄到資料庫中的資料表格式如下
/// <summary>
/// 資料表: Line機器人的連絡對象
/// </summary>
public class LineMemberTableModel
{
/// <summary>
/// 流水號
/// </summary>
public int Sn { get; set; }
/// <summary>
/// 唯一碼
/// </summary>
public string Id { get; set;}
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set;}
/// <summary>
/// 最後登入時間戳
/// </summary>
public DateTime LastLoginTime { get; set; }
/// <summary>
/// 帳號餘額
/// </summary>
public double AccountBalance { get; set;}
/// <summary>
/// 用戶帳號
/// </summary>
public string Account { get; set;}
/// <summary>
/// 用戶密碼
/// </summary>
public string Password { get; set;}
}
四、實作LineAPI的4種功能 + 驗證方法
Step 1:LineBot API 主程式 ,當用戶呼叫時,會先對傳進的字串分析
每當發現沒登入時會回傳 "登入失敗,請先登入帳戶"
※ 程式位置 : LineLoginExample\Controllers\LineBotAPIController.cs
public class LineBotAPIController : ApiController
{
//機器人Token : 仙草奶綠
string MyLineChannelAccessToken = "XXXXXXXXXXXX";
/// <summary>
/// Line機器人回覆API
/// </summary>
/// <returns></returns>
[HttpPost]
[Route("api/LineBotApi/post")]
public async void Post()
{
try
{
//取得 http Post RawData(should be JSON)
string postData = Request.Content.ReadAsStringAsync().Result;
//剖析JSON
var ReceivedMessage = isRock.LineBot.Utility.Parsing(postData);
var bot = new isRock.LineBot.Bot(this.MyLineChannelAccessToken);
//解析使用者傳給Bot的文字訊息
string userCommandString = ReceivedMessage.events[0].message.text;
//Service工作
LineBotMember _service = new LineBotMember();
//Return Message
string message = string.Empty;
//字串為save表示紀錄 ※實際應用應該偷偷記錄User ID ,這邊是範例
if (userCommandString == "save")
{
//測試方法: 紀錄
_service.InsertID(ReceivedMessage.events[0].source.userId);
//回覆API
var call = Task.Run(() =>
{
bot.ReplyMessage(ReceivedMessage.events[0].replyToken,
string.Format("紀錄成功: {0}", ReceivedMessage.events[0].source.userId));
});
}
else if (userCommandString.Contains("取得用戶金額"))//1.取得帳號金額
{
var result = _service.GetAccountBalance(ReceivedMessage.events[0].source.userId);
//取得更新後的錢
message = ( -1 == result) ? "登入失敗,請先登入帳戶" : string.Format("用戶當前金額: {0}", result);
//回覆API
var call = Task.Run(() =>
{
bot.ReplyMessage(
ReceivedMessage.events[0].replyToken,
message);
});
}
else if (userCommandString.Contains("更新金額"))//功能2 : 更新金額
{
string get= userCommandString.Substring(4, userCommandString.Length-4);
try
{
double money = double.Parse(get);
//更新金額
var isSuccess = _service.UpdateAccountBalance(ReceivedMessage.events[0].source.userId, money);
//取得更新後的錢
var result = _service.GetAccountBalance(ReceivedMessage.events[0].source.userId);
message =( false== isSuccess )? "登入失敗,請先登入帳戶" : string.Format("更新成功,當前金額: {0}", result);
//回覆API
var call = Task.Run(() =>
{
bot.ReplyMessage(ReceivedMessage.events[0].replyToken,
message);
});
}
catch (Exception ex)
{
//回覆API
var call = Task.Run(() =>
{
bot.ReplyMessage(ReceivedMessage.events[0].replyToken,
string.Format("資料格式錯誤"));
});
}
}
else if (userCommandString == "登出")// 功能4: 登出
{
_service.UpdateSingOut(ReceivedMessage.events[0].source.userId);
//回覆API
var call = Task.Run(() =>
{
bot.ReplyMessage(ReceivedMessage.events[0].replyToken,
string.Format("登出成功: {0}", DateTime.Now));
});
}
}
catch (Exception ex)
{
//取得 http Post RawData(should be JSON)
string postData = Request.Content.ReadAsStringAsync().Result;
//剖析JSON
var ReceivedMessage = isRock.LineBot.Utility.Parsing(postData);
var bot = new isRock.LineBot.Bot(this.MyLineChannelAccessToken);
//回覆API
var call = Task.Run(() =>
{
bot.ReplyMessage(ReceivedMessage.events[0].replyToken,
string.Format("錯誤資訊:{0}", ex.Message));
});
}
}
}
Step 2: 登入
※ 程式位置 : Service\LineBot\LineBotMember.cs
/// <summary>
/// 功能 : 登入
/// </summary>
/// <param name="usertoken"></param>
/// <returns></returns>
public bool UpdateLogin(string account ,string password )
{
bool result = false;
var allDatas = Repository.Pattern.Factory.RepostioryFactory.LineMemberRepository.GetAllData();
var getNowUser = allDatas.Where(o => o.Account == account && o.Password == password).FirstOrDefault();
//判斷是否有正確帳號
if (null != getNowUser)
{
//更新帳號時間戳-視為登入
result = Repository.Pattern.Factory.RepostioryFactory.LineMemberRepository.UpdateLogin(getNowUser.Id);
}
return result;
}
登入成功時,會將Db的時間紀錄為【當下時間】
Step 3: 取得UserID (個人用戶)的餘額
※會先檢查登入的時間,如果現在時間 減去 登入時間 相差 60 秒,表示過期,需要重新登入,這是一種簡單的時間戳驗證操作
/// <summary>
/// 功能 : 取得帳號金額
/// </summary>
/// <returns></returns>
public double GetAccountBalance(string userID)
{
double result = 0;
var allDatas = Repository.Pattern.Factory.RepostioryFactory.LineMemberRepository.GetAllData();
//取得餘額
if (true == IsVerification(userID))
{
result = allDatas.Where(o => o.Id == userID).FirstOrDefault().AccountBalance;
}
else
{
result = -1;
}
return result;
}
Step 4: 更新用戶餘額 (模擬存款、取款時的操作)
※會先檢查登入的時間,如果現在時間 減去 登入時間 相差 60 秒,表示過期,需要重新登入,這是一種簡單的時間戳驗證操作
/// <summary>
/// 功能 : 更新金額
/// </summary>
/// <param name="usertoken"></param>
/// <returns></returns>
public bool UpdateAccountBalance(string userID , double balance)
{
bool result = false;
var allDatas = Repository.Pattern.Factory.RepostioryFactory.LineMemberRepository.GetAllData();
//更新餘額
if (true == IsVerification(userID))
{
//更新餘額
result= Repository.Pattern.Factory.RepostioryFactory.LineMemberRepository.UpdateAccountBalance(userID, balance);
}
return result;
}
Step 5: 登出
※將時間戳寫為入一個過去時間,這邊是寫 1900-1-1 00:00:00
/// <summary>
/// 功能 : 登出
/// </summary>
/// <param name="usertoken"></param>
/// <returns></returns>
public bool UpdateSingOut(string userID)
{
bool result = false;
var allDatas = Repository.Pattern.Factory.RepostioryFactory.LineMemberRepository.GetAllData();
//登出,時間戳設為過期時間
if (true == IsVerification(userID))
{
result = Repository.Pattern.Factory.RepostioryFactory.LineMemberRepository.UpdateSignOut(userID);
}
return result;
}
五、Line用戶Demo體驗
Step 1:我們在沒有登入的情況下 點選 【查詢銀行餘額】
LineBOT回應 : 登入失敗,請先登入帳戶
Step 2:於是我們按下 【登入】按鈕,直接跳轉到登入頁面
輸入帳號:20180513 密碼:123456 => Submit 登入
Step 3 : 顯示登入成功,我們接著回到LineBot 機器人的對話中
Step 4 : 再次 點選 【查詢銀行餘額】
LineBOT回應 : 用戶當前餘額 : 3345678
Step 5 : 我們嘗試點選 【修改餘額】
LineBot 回應 : 資料格式錯誤 ※ 這是因為我們程式沒做好防呆 (´・ω・`) ,不過知道了指令
Step 6 : 用戶輸入 更新金額 54321
LineBot 回應 : 更新成功 ,當前金額 54321
※接收到了正確的指令,所以進行操作
Step 7 : 最後我們按下【登出】再按下【查詢銀行餘額】
LineBot 回應:登入失敗,請先登入帳戶 ※很明確安全機制是有的