iT邦幫忙

2022 iThome 鐵人賽

DAY 27
0
自我挑戰組

30天建構出一個簡單 LineBot 機器人系列 第 27

DAY 27 LIFF 進階(資料回傳教學)

  • 分享至 

  • xImage
  •  

在第13.14天有提到了LIFF的設定以及如何用vercel來呈現網頁,那今天就要來教大家如何把在LIFF表單中填寫的東西回傳到與機器的對話上,方便我們進行下一步動作~

還沒看過之前的教學的話可以直接前往這邊↓↓↓
DAY 13:https://ithelp.ithome.com.tw/articles/10299652
DAY 14:https://ithelp.ithome.com.tw/articles/10300300


今天要示範的是簡單的電影購票,首先先將頁面寫出來。
完整程式碼如下:

<!DOCTYPE html>
<html>
<head>
	<meta name="viewport" content="width-device-width, initial-scale=1" />
	<meta charset="utf-8">
	<title>訂票</title>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
	<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</head>
<body style="background-color: #D3C4E3">
    <div class="row" style="margin:10px">
        <div class="container" style="margin-top:10%">
            <div class="col-12" >
                <div style="display: flex; flex-direction: column;align-items: flex-start;font-size:1rem;margin-bottom: 10%;">
                    <label style="width: 20% ;font-weight: bolder;margin-bottom: 0px;color: black;">電影</label>
                    <select id="sel_type" class-="form-control" style="margin-top: 10px;width: 100%;height: calc(2.25rem + 2px);border-radius:15px;padding: 0.375rem 1.75rem 0.375rem 0.75rem;border: 1px solid #ced4da;">
                    <option selected value="0">---</option>
                    <option value="1">小獅子王</option>
                    <option value="2">刀鋒劍客</option>
                    <option value="3">樂透大作戰</option>
                    <option value="4">心裏美</option>
                    <option value="5">拆彈倒數30分鐘</option>
                    </select>
                </div>
    				
                <div style="display: flex; flex-direction: column;align-items: flex-start;margin-bottom: 10%;">
                    <p style="font-weight: bolder;margin-bottom: 0px;color: black;">票價(線上只能購買成人票)</p>
                    <p id="exhmoney" style="font-weight: bolder;color: white ;margin-bottom: 0px;">$300</p>
                </div>		

                <div style="display: flex; flex-direction: column;align-items: flex-start;font-size:1rem;margin-bottom: 10px;">
                    <label style="width: 20%;font-weight: bolder;margin-bottom: 0px;color: black;">票數</label>
                    <select class="custom-select" id="sel_amount" style="border-radius:15px;margin-top: 10px;">
                        <option selected>---</option>
                        <option value="1">1</option>
                        <option value="2">2</option>
                        <option value="3">3</option>
                        <option value="4">4</option>
                        <option value="5">5</option>
                        <option value="6">6</option>
                    </select>
                </div>
    						
                <div style="flex-direction: row;display: flex;align-items: center;justify-content: center;height:65px;margin-top: 15%;">
                    <button  class="btr" id="btn_reserve" style="width: 100%;height: 100%;color:black;font-weight: bolder;background-color: #FFF275;border-radius:27px;border-color:#D4EBE9">
                    購買
                    </button>
                </div>
            </div>
        </div>
    	</div>
    <script src="https://static.line-scdn.net/liff/edge/2.1/sdk.js"></script>
	<script>
        var liffID = '1657103560-L9092REa';

            liff.init({
              liffId: liffID
            }).then(() => {
             var isInClient = liff.isInClient();
             console.log('isInClient', isInClient);
             $('#isInClient').val(isInClient);
            }).catch((err) => {
             console.log('初始化失敗')
            });

        var exhprice=['請選擇電影','$280','$280','$270','$300','$280'];
        

            
		function reserve(type, amount) {

			if(type == '0' || amount == '---'){  //資料檢查
				alert("每個項目都必須輸入!!");
				return;
			}

			var msg = "###";//回傳訊息字串
			msg = msg + type + "/" ;
			msg = msg + amount + "/";

            
			
			liff.sendMessages([//推送訊息
				{ 	
					type: 'text',
					text: msg
				}
			])
			
    			.then(function () {
                    window.alert("訂票成功!");
                    liff.closeWindow();
                }).catch(function (error) {
                    window.alert("Error sending message: " + error);
                });
		}

        //價錢轉換start

        $( '#sel_type' ).change(function () {
            var money = "";
            $( '#sel_type option:selected').each(function() {
              money += exhprice[$("#sel_type option:selected").val()];
            });
            $( '#exhmoney' ).text( money );
          })
          .change();

        //價錢轉換end

		$(document).ready(function (){
        			initializeLiff(1657103560-L9092REa);
			});
         $('#btn_reserve').click(function() { //按下確定送出
            reserve($('#sel_type option:selected').text(), $('#sel_amount').val());
		});



	</script>



</body>
</html>

完成後上傳到vercel點擊設好的圖文按鈕就能在LINEBOT裡面看到如圖的畫面。
這邊製作的就是很簡單的選擇電影、票數然後顯示票價在上面,按下購買直接訂票。


再來就是要寫一些回傳的部分(view.py)
先加入user資料表(讀寫LINE ID資料)

from testapi.models import users

若使用者表單無此使用者LINE ID,就要將其LINE ID寫入user資料表。

  for event in events:
    if isinstance(event, MessageEvent):  # 如果有訊息事件
            user_id = event.source.user_id  #取得LINE ID
            if not (users.objects.filter(uid=user_id).exists()):
                unit = users.objects.create(uid=user_id)
                unit.save()
            mtext = event.message.text

傳回字串以「###」為開頭,表示是使用者傳回的表單資料。

 elif mtext[:3] =='###' and len(mtext) > 3:
        func.manageForm(event, mtext, user_id)

fuc.py的部分就是接收view回傳的東西,再整理出來顯示資料給使用者。

ex = {"小獅子王":"280",
      "刀鋒劍客":"280",
      "樂透大作戰":"270",
      "心裏美":"300",
      "拆彈倒數30分鐘":"280",
        }
def manageForm(event, mtext, user_id): #處理LIFF傳回的from資料
    try:
        flist = mtext[3:].split('/') #去除前三個#再分解字串
        movietype = flist[0] #取得輸入資料
        amount = flist[1]
        money = ex[movietype]
        
        unit = booking.objects.create(bid=user_id,exhibittype=exhibittype,exhibitamount=amount,money=money)
        unit.save()
        
        total = int(money)*int(amount)
        
        text1 = "訂票成功,資料如下:"
        text1 += "\n 電影名稱:" + movietype
        text1 += "\n 票數:" + amount
        text1 += "\n 單價:" + money
        text1 += "\n 總價:" + str(total)
        message = TextSendMessage(
            text = text1
        )
        line_bot_api.reply_message(event.reply_token,message)
        
    except:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text='結帳錯誤'))  

在html的地方也有寫到如果沒有全部填寫就不能送出,所以會出現"每個項目都必須填寫"的提醒視窗~
送出訂單後就會跳出訂單成功的視窗,然後跳回LINE裡面先出現使用者輸入的部分,在將資料統整跟使用者做確認。


這樣就完成簡單的訂票回傳功能啦~當然還能在訂票成功後回傳的結帳畫面做更多的變化,像是加入確認或取消訂單的按鈕,讓它不單單只是回傳文字還有其他的功能,那這邊就交給大家自己去發想啦!
歡迎有問題留言給我們或是分享自己做出來的結果喔!(♡˙︶˙♡)


上一篇
DAY 26 專案介紹-5 (飲料訂購機器人實作-4)
下一篇
DAY 28 LINE Beacon介紹
系列文
30天建構出一個簡單 LineBot 機器人30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言