在前面隨筆《利用微信公眾號實現(xiàn)商品的展示和支付(1)》介紹了商品的列表和明細信息的處理,本篇隨筆接著上一篇间聊,繼續(xù)介紹關于商品的微信支付和購物車處理方面,其中微信支付里面,也涉及到了獲取微信共享地址的處理谆奥,從而個更加方便錄入郵寄地址信息;購物車可以從本地的localStorage對象進行獲取和處理拂玻,也可通過接口獲取數(shù)據庫記錄的購物車信息酸些,本案例介紹通過localStorage進行購物車處理方式宰译。
1渣磷、商品的微信支付處理
商品的微信支付處理蓖乘,其中涉及了兩個場景,一個是直接購買质礼,一個是通過購物車的結算方式市栗,兩個處理界面有所差異缀拭,直接付款購買的界面是對當前選中商品進行單項的結算處理,默認數(shù)量為1肃廓;而購物車訂單結算則是利用購物車的記錄進行微信支付的處理智厌,購物車可以從本地的localStorage對象進行獲取和處理,也可通過接口獲取數(shù)據庫記錄的購物車信息盲赊,本案例介紹通過localStorage進行購物車處理方式铣鹏。
對選中商品直接結算界面如下所示。
購物車結算界面如下所示哀蘑。
先來看看微信共享地址的處理界面诚卸,代碼如下所示。
<!--配送地址處理-->
<div class="weui-panel">
<div class="weui-panel__bd">
<div class="weui-media-box weui-media-box_small-appmsg">
<div class="weui-cells">
<div class="weui-cell weui-cell_access">
<div class="weui-cell__bd weui-cell_primary">
<p class="font-14"><span class="mg-r-10">配送地址</span><span class="fr"><a onclick="GetAddress()" class="weui-btn_mini weui-btn_primary">獲取微信地址</a></span></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="wy-media-box weui-media-box_text address-select">
<div class="weui-media-box_appmsg">
<div class="weui-media-box__hd proinfo-txt-l" style="width:20px;"><span class="promotion-label-tit"><img src="~/Content/wechat/web/images/icon_nav_city.png" /></span></div>
<div class="weui-media-box__bd">
<a href="/h5/address" class="weui-cell_access">
<h4 class="address-name"></h4>
<div class="address-txt"></div>
</a>
</div>
<div class="weui-media-box__hd proinfo-txt-l" style="width:16px;"><div class="weui-cell_access"><span class="weui-cell__ft"></span></div></div>
</div>
</div>
獲取微信共享地址绘迁,需要配合微信的JSSDK的JS代碼進行處理合溺,如下是處理的代碼。
<script language="javascript">
var appid = '@ViewBag.appid';
var noncestr = '@ViewBag.noncestr';
var signature = '@ViewBag.signature';
var timestamp = '@ViewBag.timestamp';
wx.config({
debug: false,
appId: appid, // 必填缀台,公眾號的唯一標識
timestamp: timestamp, // 必填棠赛,生成簽名的時間戳
nonceStr: noncestr, // 必填,生成簽名的隨機串
signature: signature, // 必填膛腐,簽名睛约,見附錄1
jsApiList: [
'checkJsApi',
'chooseImage',
'previewImage',
'uploadImage',
'downloadImage',
'getLocalImgData',
'openAddress'
]
});
//所有準備好后
wx.ready(function () {
});
//獲取微信共享地址
function GetAddress() {
wx.openAddress({
success: function (res) {
var userName = res.userName; // 收貨人姓名
var postalCode = res.postalCode; // 郵編
var provinceName = res.provinceName; // 國標收貨地址第一級地址(省)
var cityName = res.cityName; // 國標收貨地址第二級地址(市)
var countryName = res.countryName; // 國標收貨地址第三級地址(國家)
var detailInfo = res.detailInfo; // 詳細收貨地址信息
var nationalCode = res.nationalCode; // 收貨地址國家碼
var telNumber = res.telNumber; // 收貨人手機號碼
//$.alert(`${detailInfo}`);
$(".address-name").html(`<span>${userName}</span><span>${telNumber}</span>`);
$(".address-txt").text(`${detailInfo}`);
}
});
}
</script>
而直接購買的產品信息哲身,就是通過ID獲取對應商品信息辩涝,綁定在控件上即可,如下界面代碼所示勘天。
<!--購買商品信息-->
<div class="wy-media-box weui-media-box_text">
<div class="weui-media-box__bd">
<div class="weui-media-box_appmsg ord-pro-list">
<div class="weui-media-box__hd"><a href="pro_info.html"><img id="productimg" class="weui-media-box__thumb" src="" alt=""></a></div>
<div class="weui-media-box__bd">
<h1 class="weui-media-box__desc"><a href="/h5/ProductDetail?id=@Request["ID"]" class="ord-pro-link"><span id="productname"></span></a></h1>
<p class="weui-media-box__desc">規(guī)格:<span>套</span></p>
<div class="clear mg-t-10">
<div class="wy-pro-pri fl">¥<em class="num font-15" id="price">0</em></div>
<div class="pro-amount fr"><div id="spinner-amount" class="Spinner"></div></div>
</div>
</div>
</div>
</div>
</div>
JS處理代碼如下所示
//綁定產品明細
function GetProductDetail() {
var url = "/H5/GetProductDetail";
var data = {
id: "@Request["ID"]"
}
//獲取數(shù)據并綁定界面
$.getJSON(url, data, function (result) {
$("#productname").text(result.ProductName);
$("#price").text(result.Price);
$("#productimg").attr("src", result.Picture);
//$("#description").text(result.Description);
$("#totalmoney").text(result.Price);
});
}
而微信支付的處理怔揩,我們可以通過參考官方的接口定義來處理我們的代碼。
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
我們先來金額匯總的界面展示脯丝,通過按鈕我們發(fā)起微信支付的處理操作商膊。
<!--金額及發(fā)起支付-->
<div class="wy-media-box weui-media-box_text">
<div class="mg10-0 t-c">總金額:<span class="wy-pro-pri mg-tb-5">¥<em class="num font-20" id="totalmoney">0</em></span></div>
<div class="mg10-0"><a onclick="PayMoney()" class="weui-btn weui-btn_primary">微信付款</a></div>
<div class="mg10-0"><a href="/h5/ProductList" class="weui-btn weui-btn_plain-primary">返回產品列表</a></div>
</div>
參考下官方案例,我們處理的JS代碼如下所示巾钉。
//微信支付的調用處理
function onBridgeReady() {
//統(tǒng)一下單的數(shù)據
var total_fee = parseFloat($("#totalmoney").text()) * 100;//轉換為分單位
var data = {
total_fee: total_fee, //訂單金額,單位為分
body: $("#productname").text(), //商品或支付單簡要描述
detail: $("#productname").text(), //商品名稱明細列表
openid: "@ViewBag.openid", //當前用戶標識
product_id: "@Request["ID"]", //商品ID, trade_type=NATIVE翘狱,此參數(shù)必傳
trade_type: "JSAPI", //交易類型, JSAPI--公眾號支付、NATIVE--原生掃碼支付砰苍、APP--app支付
attach: "附加數(shù)據", // 附加數(shù)據,在查詢API和支付通知中原樣返回潦匈,該字段主要用于商戶攜帶訂單的自定義數(shù)據
};
//獲取預下單參數(shù)并調用支付處理
var url = "/h5/GetPreOrder";
$.getJSON(url, data, function (info) {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": info.appId, //公眾號名稱阱高,由商戶傳入
"timeStamp": info.timeStamp, //時間戳,自1970年以來的秒數(shù)
"nonceStr": info.nonceStr, //隨機串
"package": info.package,
"signType": info.signType, //微信簽名方式:
"paySign": info.paySign //微信簽名
},
function (res) {
switch (res.err_msg) {
case 'get_brand_wcpay_request:cancel':
$.alert("取消支付");
break;
case 'get_brand_wcpay_request:fail':
$.alert("支付失敗茬缩,可能的原因:簽名錯誤赤惊、未注冊APPID、項目設置APPID不正確凰锡、注冊的APPID與設置的不匹配未舟、其他異常等。");
break;
case 'get_brand_wcpay_request:ok':
$.alert("支付成功");
break;
}
});
});
}
//微信付款
function PayMoney() {
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady();
}
}
這里的支付所需的參數(shù)掂为,我們通過后端的/h5/GetPreOrder 獲取生成裕膀,然后通過JS進行異步發(fā)起支付操作。
這個GetPreOrder主要的操作就是根據我們傳入的商品信息勇哗,然后獲取對應的參數(shù)返回給前端昼扛。
/// <summary>
/// 預生成訂單支付需要的前端參數(shù)
/// </summary>
/// <param name="order">訂單數(shù)據</param>
/// <returns></returns>
public ActionResult GetPreOrder(PayOrderData order)
{
dynamic obj = new ExpandoObject();
if (order != null && order.total_fee > 0)
{
//調用支付API,獲取統(tǒng)一下單數(shù)據
var payApi = new TenPayApi(this.accountInfo);
var preResult = payApi.UnifiedOrder(order);
var prepay_id = preResult.prepay_id;//預支付回話標識
//生成支付所需數(shù)據和簽名
WxPayData data = new WxPayData();
data.SetValue("appId", accountInfo.AppID);//公眾帳號id
data.SetValue("timeStamp", data.GenerateTimeStamp());//隨機字符串
data.SetValue("nonceStr", data.GenerateNonceStr());//隨機字符串
data.SetValue("package", string.Format("prepay_id={0}", prepay_id));//統(tǒng)一下單接口返回的prepay_id參數(shù)值欲诺,提交格式如:prepay_id=***
data.SetValue("signType", "MD5");//簽名類型抄谐,默認為MD5,支持HMAC-SHA256和MD5扰法。注意此處需與統(tǒng)一下單的簽名類型一致
data.SetValue("paySign", data.MakeSign(accountInfo.PayAPIKey));//簽名
//構建一個前端使用的對象蛹含,用于配置支付處理的JS參數(shù)
obj.appId = accountInfo.AppID;
obj.nonceStr = data.GetValue("nonceStr");
obj.timeStamp = data.GetValue("timeStamp");
obj.package = data.GetValue("package");
obj.signType = data.GetValue("signType");
obj.paySign = data.GetValue("paySign");
}
return ToJsonContent(obj);
}
這樣我們就可以發(fā)起微信支付處理操作了。
當然塞颁,我們JS方面浦箱,除了剛才利用getBrandWCPayRequest 來發(fā)起支付處理,我們還可以利用微信JSSDK的chooseWXPay函數(shù)支付發(fā)起處理的祠锣,如下代碼所示憎茂。
//發(fā)起一個微信支付
function chooseWXPay() {
//統(tǒng)一下單的數(shù)據
var total_fee = parseFloat($("#totalmoney").text()) * 100;//轉換為分單位
var data = {
total_fee: total_fee, //訂單金額,單位為分
body: $("#productname").text(), //商品或支付單簡要描述
detail: $("#productname").text(), //商品名稱明細列表
openid: "@ViewBag.openid", //當前用戶標識
product_id: "@Request["ID"]", //商品ID, trade_type=NATIVE,此參數(shù)必傳
trade_type: "JSAPI", //交易類型, JSAPI--公眾號支付锤岸、NATIVE--原生掃碼支付、APP--app支付
attach: "附加數(shù)據", // 附加數(shù)據,在查詢API和支付通知中原樣返回板乙,該字段主要用于商戶攜帶訂單的自定義數(shù)據
};
//獲取預下單參數(shù)并調用支付處理
var url = "/h5/GetPreOrder";
$.getJSON(url, data, function (info) {
wx.chooseWXPay({
appId: info.appId,
timestamp: info.timeStamp, // 支付簽名時間戳是偷,注意微信jssdk中的所有使用timestamp字段均為小寫。但最新版的支付后臺生成簽名使用的timeStamp字段名需大寫其中的S字符
nonceStr: info.nonceStr, // 支付簽名隨機串募逞,不長于 32 位
package: info.package, // 統(tǒng)一支付接口返回的prepay_id參數(shù)值蛋铆,提交格式如:prepay_id=***)
signType: info.signType, // 簽名方式,默認為'SHA1'放接,使用新版支付需傳入'MD5'
paySign: info.paySign, // 支付簽名
success: function (res) { // 支付成功后的回調函數(shù)
if (res.errMsg == 'chooseWXPay:ok') {
$.toast('支付成功');
//setTimeout(function () {
// window.location.href = "/";//這里默認跳轉到主頁
//}, 2000);
//window.location.href = "/Pay/order_details?orderId=" + $("#orderId").val();
} else if (res.errMsg == 'chooseWXPay:cancel' || res.errMsg == 'chooseWXPay:fail') {
$.toast("支付失敗");
//window.location.href = "/Pay/order_details?orderId=" + $("#orderId").val();
}
},
cancel: function () {
$.toast("用戶取消了支付2");
//window.location.href = "/Pay/order_details?orderId=" + $("#orderId").val();
}
});
wx.error(function (res) {
$.toast("調用支付出現(xiàn)異常");
});
});
}
同樣可以實現(xiàn)一樣的微信支付效果刺啦。
2、商品的購物車處理
前面介紹過纠脾,購物車可以從本地的localStorage對象進行獲取和處理玛瘸,也可通過接口獲取數(shù)據庫記錄的購物車信息蜕青,本案例介紹通過localStorage進行購物車處理方式。
為了封裝對localStorage購物車的處理糊渊,我們引入一個對這個購物車的操作處理右核,主要就是添加、更新渺绒、獲取列表贺喝、清空列表等相關操作。
對于以上JS的代碼使用demo代碼如下所示宗兼。
<script>
$(function () {
var product = {
'id': 1, 屬性名用引號括起來躏鱼,屬性間由逗號隔開
'name': '商品1',
'num': 1,
'price': 1
};
cart.addProduct(product); 商品加入到購物車
var productlist = cart.getProductList(); 取出購物車商品
console.log(productlist);
var isExist = cart.existProduct();
console.log(isExist);
cart.deleteProduct(1);
var isExist1 = cart.existProduct();
console.log(isExist1);
});
</script>
購物車列表界面如下所示,主要就是展開存儲里面的商品信息殷绍,并匯總展示染苛,如下所示。
這個頁面視圖的代碼如下所示篡帕。
<!--主體-->
<header class="wy-header">
<div class="wy-header-icon-back"><span></span></div>
<div class="wy-header-title">購物車</div>
</header>
<div class="weui-content" id="divCart">
</div>
<!--底部導航-->
<div class="foot-black"></div>
<div class="weui-tabbar wy-foot-menu">
<div class="npd cart-foot-check-item weui-cells_checkbox allselect">
<div class="weui-cell allsec-well weui-check__label" for="all">
<div class="weui-cell__hd">
<input type="checkbox" class="weui-check" name="all-sec" id="all">
<i class="weui-icon-checked"></i>
</div>
<div class="weui-cell__bd">
<p class="font-14">全選</p>
</div>
</div>
</div>
<div class="weui-tabbar__item npd">
<p class="cart-total-txt">合計:<i>¥</i><em class="num font-16" id="zong1">0.00</em></p>
</div>
<a href="/h5/shopcartorder" class="red-color npd w-90 t-c">
<p class="promotion-foot-menu-label">去結算</p>
</a>
</div>
這里主要就是根據數(shù)據殖侵,動態(tài)構建divCart里面的列表數(shù)據,相關的JS代碼如下所示镰烧。
//顯示購物車列表
function showCartList() {
var productlist = cart.getProductList(); //取出購物車商品
$("#divCart").html("");
//構建HTML控件
$.each(productlist, function (i, item) {
var html = `
<div class="weui-panel weui-panel_access">
<div class="weui-panel__hd"><span>廣州愛奇迪</span><a href="javascript:;" class="wy-dele"></a></div>
<div class="weui-panel__bd">
<div class="weui-media-box_appmsg pd-10">
<div class="weui-media-box__hd check-w weui-cells_checkbox">
<div class="weui-check__label" for="cart-pto1">
<div class="weui-cell__hd cat-check"><input type="checkbox" class="weui-check" name="cartpro" id="cart-pto1"><i class="weui-icon-checked"></i></div>
</div>
</div>
<div class="weui-media-box__hd"><a href="/h5/ProductDetail?id=${item.id}"><img class="weui-media-box__thumb" src="${item.picture}" alt=""></a></div>
<div class="weui-media-box__bd">
<h1 class="weui-media-box__desc"><a href="/h5/ProductDetail?id=${item.id}" class="ord-pro-link">${item.name}</a></h1>
<p class="weui-media-box__desc">規(guī)格:<span>套</span></p>
<div class="clear mg-t-10">
<div class="wy-pro-pri fl">¥<em class="num font-15">${item.price}</em></div>
<div class="pro-amount fr">
<div class="weui-count">
<a class="weui-count__btn weui-count__decrease"></a>
<input class="weui-count__number" type="number" value="${item.num}" />
<a class="weui-count__btn weui-count__increase"></a>
<input type="hidden" class="pro-id" value="${item.id}"/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>`;
$("#divCart").append(html);
});
...................
對于數(shù)量的修改拢军,我們同時修改購物車里面的數(shù)據即可,如下代碼所示怔鳖。
//對數(shù)量改變進行處理茉唉,更新購物車的對應產品id的數(shù)量
var MAX = 99, MIN = 1;
$('.weui-count__decrease').each(function (i) {
$(this).click(function (e) {
var $input = $(e.currentTarget).parent().find('.weui-count__number');
var number = parseInt($input.val() || "0") - 1
if (number < MIN) number = MIN;
$input.val(number);
var id = $(e.currentTarget).parent().find(".pro-id").val();
updateProductNum(id, number);
});
});
$('.weui-count__increase').each(function (i) {
$(this).click(function (e) {
var $input = $(e.currentTarget).parent().find('.weui-count__number');
var number = parseInt($input.val() || "0") + 1
if (number > MAX) number = MAX;
$input.val(number);
var id = $(e.currentTarget).parent().find(".pro-id").val();
updateProductNum(id, number);
});
});
其中updateProductNum是對購物車數(shù)據的修改。
//修改購物車的內容
function updateProductNum(id, number) {
console.log(id + ':' + number);
cart.updateProductNum(id, number);
//顯示數(shù)量和金額
var amount = orderdetail.totalAmount;//獲取購物車的總金額
$("#zong1").text(amount);
}
購物車的清空指定商品的JS代碼如下所示结执。
$(document).on("click", ".wy-dele", function () {
$.confirm("您確定要把此商品從購物車刪除嗎?", "確認刪除?", function () {
var id = $(this).parent().parent().find(".pro-id").val();
cart.clearProduct(id);//移除指定商品
showCartList();//更新列表
$.toast("文件已經刪除!");
}, function () {
//取消操作
});
});
購物車的結算頁面度陆,前面介紹過了,就是如下圖所示献幔,類似我們直接購買商品的界面懂傀。
這個地方主要差異在于也是動態(tài)獲取一個或多個商品記錄的信息,如下所示蜡感。
HTML視圖界面代碼如下所示蹬蚁。
<div id="divCart">
@*<div class="wy-media-box weui-media-box_text">
<div class="weui-media-box__bd">
<div class="weui-media-box_appmsg ord-pro-list">
<div class="weui-media-box__hd"><a href="pro_info.html"><img id="productimg" class="weui-media-box__thumb" src="" alt=""></a></div>
<div class="weui-media-box__bd">
<h1 class="weui-media-box__desc"><a href="/h5/ProductDetail?id=@Request["ID"]" class="ord-pro-link"><span id="productname"></span></a></h1>
<p class="weui-media-box__desc">規(guī)格:<span>套</span></p>
<div class="clear mg-t-10">
<div class="wy-pro-pri fl">¥<em class="num font-15" id="price">0</em></div>
<div class="pro-amount fr"><span class="font-13">數(shù)量×<em class="name">1</em></span></div>
</div>
</div>
</div>
</div>
</div>*@
</div>
JS代碼主要就是動態(tài)構建列表,divCart里面的內容實現(xiàn)根據購物車商品列表進行處理郑兴,如下代碼所示犀斋。
//顯示購物車列表
function showCartList() {
var productlist = cart.getProductList(); //取出購物車商品
$("#divCart").html("");
//構建HTML控件
var html = "";
$.each(productlist, function (i, item) {
html += `
<div class="wy-media-box weui-media-box_text">
<div class="weui-media-box__bd">
<div class="weui-media-box_appmsg ord-pro-list">
<div class="weui-media-box__hd"><a href="/h5/ProductDetail?id=${item.id}"><img id="productimg" class="weui-media-box__thumb" src="${item.picture}" alt=""></a></div>
<div class="weui-media-box__bd">
<h1 class="weui-media-box__desc"><a href="/h5/ProductDetail?id=${item.id}" class="ord-pro-link">${item.name}</a></h1>
<p class="weui-media-box__desc">規(guī)格:<span>套</span></p>
<div class="clear mg-t-10">
<div class="wy-pro-pri fl">¥<em class="num font-15" id="price">${item.price}</em></div>
<div class="pro-amount fr"><span class="font-13">數(shù)量×<em class="name">${item.num}</em></span></div>
<input type="hidden" class="pro-id" value="${item.id}"/>
</div>
</div>
</div>
</div>
</div>`;
});
$("#divCart").append(html);
//顯示數(shù)量和金額
var amount = orderdetail.totalAmount;//獲取購物車的總金額
$("#totalmoney").text(amount);
}