樂優商城(三十六)——訂單微服務
目錄
二、訂單結算頁
2.1 頁面跳轉
在購物車頁面的最下方,有一個去結算按鈕:
當點選結算,我們應該跳轉到訂單結算頁,即:getOrderInfo.html
檢視購物車的結算
按鈕:
可以看到,地址是正確的。但是隻有登入使用者才可以去結算付款,因此不能直接跳轉,而是在跳轉前校驗使用者的登入狀態,如果發現是未登入,應該重定向到登入頁!
繫結點選事件:
toOrderInfo(){ //1.判斷是否登入 ly.verifyUser().then(() => { //2.已登入 window.location.href = "/getOrderInfo.html"; }).catch(() => { window.location.href = "/login.html?returnUrl=" + window.location.href; }) }
登入後測試:
此處頁面需要渲染的內容主要包含3部分:
-
收貨人資訊
-
支付方式
-
商品資訊
2.2 收貨人資訊
這裡的收貨人資訊肯定是當前登入使用者的收貨地址。所以需要根據當前登入使用者去查詢,目前是假資料,為了展示效果,具體開發,下一篇介紹。
2.3 支付方式
支付方式有2種:
-
微信支付
-
貨到付款
與訂單資料中的paymentType
關聯:
所以在Vue例項中定義一個屬性來記錄支付方式:
然後在頁面渲染時與這個變數關聯:
2.4 商品列表
效果圖:
這裡的送貨清單,其實就是購物車中使用者選擇的要付款的商品
因此,需要在購物車跳轉過來的同時,攜帶選中的購物車的資訊
2.4.1 購物車資訊獲取
修改cart.html
中的頁面跳轉邏輯,把使用者選中的購物車資訊傳遞過來:
然後在created
鉤子函式中獲取購物車資料,儲存到本地屬性,要注意的是,應該在獲取資料前校驗使用者登入狀態,如果發現未登入,則直接重定向到登入頁:
重新載入頁面,檢視本地資料:
2.4.2 頁面渲染
2.5 總金額
可以看出這裡主要有4個數據:
-
總金額:totalPay
-
優惠返現:discount
-
運費:postFee
-
實付金額:actualPay
不過我們沒有做優惠活動,另外運費需要結合物流系統來計算,暫時都設定為0,在order屬性中寫死:
通過計算屬性來得到totalPay
和actualPay
值:
computed:{
totalNum(){
return this.carts.reduce((c1,c2) => c1 + c2.num,0);
},
totalPay(){
return this.carts.reduce((c1,c2) => c1 + c2.price * c2.num,0);
},
actualPay(){
return this.totalPay + this.order.postFee - this.order.discount;
}
}
然後在頁面渲染:
效果:
2.6 提交訂單
2.6.1 頁面提交
分析
檢視訂單介面所需要的資料
{
"totalPay": 236800,
"postFee": 0,
"paymentType": 2,
"actualPay": 236800,
"buyerMessage": null,
"buyerNick": "huge",
"orderDetails": [
{
"skuId": 3893493,
"num": 1,
"title": "蘋果(Apple)iPhone 6 (A1586) 16GB 金色 移動聯通電信4G手機3",
"price": 236800,
"ownSpec": "{\"機身顏色\":\"鑽雕藍\",\"記憶體\":\"4GB\",\"機身儲存\":\"64GB\"}",
"image": "http://image.leyou.com/images/9/4/1524297342728.jpg"
}
],
"receiver": "鋒哥",
"receiverMobile": "15800000000",
"receiverState": "上海",
"receiverCity": "上海",
"receiverDistrict": "浦東新籤",
"receiverAddress": "航頭鎮航頭路18號傳智播客3號樓",
"receiverZip": "210000",
"invoiceType": 0,
"sourceType":2
}
-
訂單本身的基本資訊
-
總金額
-
實付金額
-
付款型別
-
買家資訊就是當前使用者
-
-
訂單詳情
-
就是購物車中的商品,不過購物車資料會多出一個userId,去除即可:
-
- 物流資訊:當前使用者選中的地址
繫結事件
注:使用@click.prevent是因為要阻止a標籤的預設跳轉,去執行submit函式。
方法
submit(){
//1.把購物車資料處理成訂單物件
const orderDetails = this.carts.map(({userId, ...rest}) => rest);
//1.1將ownSpec欄位轉換成json
orderDetails.forEach(s =>{
s.ownSpec = JSON.stringify(s.ownSpec);
});
//2.處理物流資訊
const addr = this.addresses[this.selectedAddress];
const obj = {
receiver:addr.name,
receiverState:addr.state,
receiverCity:addr.city,
receiverAddress:addr.address,
receiverDistrict:addr.district,
receiverMobile:addr.phone,
receiverZip:addr.zipCode
};
//3.複製到訂單物件
Object.assign(this.order,obj,{
orderDetails,
totalPay:this.totalPay,
actualPay:this.actualPay,
});
//4.提交訂單
//console.log(this.order);
ly.http.post("/order",this.order).then(({data}) => {
//4.1線上支付,需要到付款頁
window.location = "pay.html?orderId=" + data;
}).catch(() => {
alert("訂單提交失敗,請稍後再試!");
})
}
2.6.2 精度損失問題
頁面點選提交進行測試:
生成訂單成功!
然後頁面跳轉:
好像有什麼不對?訂單號的最後2位不正確啊!
這其實是因為JS的長整數精度有限,java的Long型別資料超出了範圍,所以出現了精度損失。
因為後臺返回的是Json的字串,在axios內部會自動呼叫 JSON.parse()方法把json字串轉為JS資料,就會出現進度損失。如果不進行轉換,依然當做字串來使用,就不會有問題了。
因此,重寫axios對響應的處理回撥函式:
三、微信支付
3.1 介紹
微信支付官方文件:https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2F
選擇開發文件,而後進入選擇頁面:
選擇掃碼支付:
此處使用模式二來開發
3.2 開發流程
3.2.1 介紹
模式二與模式一相比,流程更為簡單,不依賴設定的回撥支付URL。商戶後臺系統先呼叫微信支付的統一下單介面,微信後臺系統返回連結引數code_url,商戶後臺系統將code_url值生成二維碼圖片,使用者使用微信客戶端掃碼後發起支付。注意:code_url有效期為2小時,過期後掃碼不能再發起支付。
流程圖:
業務流程說明:
(1)商戶後臺系統根據使用者選購的商品生成訂單。
(2)使用者確認支付後呼叫微信支付【統一下單API】生成預支付交易;
(3)微信支付系統收到請求後生成預支付交易單,並返回交易會話的二維碼連結code_url。
(4)商戶後臺系統根據返回的code_url生成二維碼。
(5)使用者開啟微信“掃一掃”掃描二維碼,微信客戶端將掃碼內容傳送到微信支付系統。
(6)微信支付系統收到客戶端請求,驗證連結有效性後發起使用者支付,要求使用者授權。
(7)使用者在微信客戶端輸入密碼,確認支付後,微信客戶端提交授權。
(8)微信支付系統根據使用者授權完成支付交易。
(9)微信支付系統完成支付交易後給微信客戶端返回交易結果,並將交易結果通過簡訊、微信訊息提示使用者。微信客戶端展示支付交易結果頁面。
(10)微信支付系統通過傳送非同步訊息通知商戶後臺系統支付結果。商戶後臺系統需回覆接收情況,通知微信後臺系統不再發送該單的支付通知。
(11)未收到支付通知的情況,商戶後臺系統呼叫【查詢訂單API】。
(12)商戶確認訂單已支付後給使用者發貨。
3.2.2 具體工作
這裡把商戶要做的事情總結一下:
-
1、商戶生成訂單
-
2、商戶呼叫微信下單介面,獲取預交易的連結
-
3、商戶將連結生成二維碼圖片,展示給使用者;
-
4、使用者支付並確認
-
5、支付結果通知:
-
微信非同步通知商戶支付結果,商戶告知微信支付接收情況
-
商戶如果沒有收到通知,可以呼叫介面,查詢支付狀態
-
-
6、如果支付成功,發貨,修改訂單狀態
在前面的業務中,已經完成了:
-
1、生成訂單
接下來需要完成的是:
-
2、呼叫微信介面,生成連結。
-
3、並且生成二維碼圖片
3.3 生成二維碼
3.3.1 生成預交易連結
先根據訂單的編號,呼叫後臺服務,生成交易連結,而後才能根據連結生成二維碼。
在頁面發起請求:
var payVm = new Vue({
el:"#payVm",
data:{
ly,
orderId:0, //訂單id
},
components:{
shortcut: () => import("/js/pages/shortcut.js")
},
created(){
this.loadData();
},
methods:{
loadData(){
//1.判斷使用者是否登入
ly.verifyUser().then(() => {
//2.獲取訂單編號
this.orderId = ly.getUrlParam("orderId");
//3.獲取請求連結
ly.http.get("/order/url/" + this.orderId).then(resp => {
console.log(resp.data);
new QRCode(document.getElementById("qrImage"),{
text:resp.data,
width:250,
height:250,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
});
});
}).catch(() => {
//4.未登入,跳轉至登入頁
location.href = "/login.html?returnUrl=" + location.href;
})
}
}
});
注意:app.js要最後引入,因為要先有id為app的div,vue才能獲取相應的元素。否則會報錯: [Vue warn]: Cannot find element
後臺已經定義好生成付款地址的介面:
重新整理頁面:
3.3.2 生成二維碼
使用一個生成二維碼的JS外掛:qrcode,官網:https://github.com/davidshimjs/qrcodejs
將這個指令碼引入到專案中
官方使用案例
頁面引用
頁面定義一個div用來展示二維碼
獲取到付款連結後生成二維碼
效果
此時,客戶用手機掃描二維碼,可以看到付款頁面。
3.4 付款狀態查詢
跳轉到支付頁面後,等待使用者付款,付款完成則跳轉到付款成功頁面
3.4.1 頁面迴圈查詢支付狀態
不過,因為不清楚使用者何時會付款,因此這裡採用迴圈的方式,不斷請求判斷是否支付成功。
3.4.2 付款成功頁面
當付款成功後,自動跳轉到付款成功頁面: