利用微信公眾號實現商品的展示和支付(2)

来源:https://www.cnblogs.com/wuhuacong/archive/2020/04/22/12751891.html
-Advertisement-
Play Games

在前面隨筆《利用微信公眾號實現商品的展示和支付(1)》介紹了商品的列表和明細信息的處理,本篇隨筆接著上一篇,繼續介紹關於商品的微信支付和購物車處理方面,其中微信支付裡面,也涉及到了獲取微信共用地址的處理,從而個更加方便錄入郵寄地址信息;購物車可以從本地的localStorage對象進行獲取和處理,也... ...


在前面隨筆《利用微信公眾號實現商品的展示和支付(1)》介紹了商品的列表和明細信息的處理,本篇隨筆接著上一篇,繼續介紹關於商品的微信支付和購物車處理方面,其中微信支付裡面,也涉及到了獲取微信共用地址的處理,從而個更加方便錄入郵寄地址信息;購物車可以從本地的localStorage對象進行獲取和處理,也可通過介面獲取資料庫記錄的購物車信息,本案例介紹通過localStorage進行購物車處理方式。

1、商品的微信支付處理

商品的微信支付處理,其中涉及了兩個場景,一個是直接購買,一個是通過購物車的結算方式,兩個處理界面有所差異,直接付款購買的界面是對當前選中商品進行單項的結算處理,預設數量為1;而購物車訂單結算則是利用購物車的記錄進行微信支付的處理,購物車可以從本地的localStorage對象進行獲取和處理,也可通過介面獲取資料庫記錄的購物車信息,本案例介紹通過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">規格:<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"]"
    }
    //獲取數據並綁定界面
    $.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

 我們先來金額彙總的界面展示,通過按鈕我們發起微信支付的處理操作。

<!--金額及發起支付-->
<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() {
            //統一下單的數據
            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,此參數必傳
                trade_type: "JSAPI",        //交易類型, JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付
                attach: "附加數據",         // 附加數據,在查詢API和支付通知中原樣返回,該欄位主要用於商戶攜帶訂單的自定義數據
            };

            //獲取預下單參數並調用支付處理
            var url = "/h5/GetPreOrder";
            $.getJSON(url, data, function (info) {
                WeixinJSBridge.invoke(
                    'getBrandWCPayRequest', {
                        "appId": info.appId,          //公眾號名稱,由商戶傳入
                        "timeStamp": info.timeStamp,  //時間戳,自1970年以來的秒數
                        "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();
            }
        }

這裡的支付所需的參數,我們通過後端的/h5/GetPreOrder 獲取生成,然後通過JS進行非同步發起支付操作。

這個GetPreOrder主要的操作就是根據我們傳入的商品信息,然後獲取對應的參數返回給前端。

/// <summary>
/// 預生成訂單支付需要的前端參數
/// </summary>
/// <param name="order">訂單數據</param>
/// <returns></returns>
public ActionResult GetPreOrder(PayOrderData order)
{
    dynamic obj = new ExpandoObject();
    if (order != null && order.total_fee > 0)
    {
        //調用支付API,獲取統一下單數據
        var payApi = new TenPayApi(this.accountInfo);
        var preResult = payApi.UnifiedOrder(order);
        var prepay_id = preResult.prepay_id;//預支付回話標識


        //生成支付所需數據和簽名
        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));//統一下單介面返回的prepay_id參數值,提交格式如:prepay_id=***     
        data.SetValue("signType", "MD5");//簽名類型,預設為MD5,支持HMAC-SHA256和MD5。註意此處需與統一下單的簽名類型一致         
        data.SetValue("paySign", data.MakeSign(accountInfo.PayAPIKey));//簽名

        //構建一個前端使用的對象,用於配置支付處理的JS參數
        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);
}

這樣我們就可以發起微信支付處理操作了。

當然,我們JS方面,除了剛纔利用getBrandWCPayRequest 來發起支付處理,我們還可以利用微信JSSDK的chooseWXPay函數支付發起處理的,如下代碼所示。

//發起一個微信支付
function chooseWXPay() {
    //統一下單的數據
    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,此參數必傳
        trade_type: "JSAPI",        //交易類型, JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付
        attach: "附加數據",         // 附加數據,在查詢API和支付通知中原樣返回,該欄位主要用於商戶攜帶訂單的自定義數據
    };

    //獲取預下單參數並調用支付處理
    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,      // 統一支付介面返回的prepay_id參數值,提交格式如:prepay_id=***)
            signType: info.signType,    // 簽名方式,預設為'SHA1',使用新版支付需傳入'MD5'
            paySign: info.paySign,      // 支付簽名
            success: function (res) {   // 支付成功後的回調函數
                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("調用支付出現異常");
        });
    });
}

同樣可以實現一樣的微信支付效果。 

 

2、商品的購物車處理

前面介紹過,購物車可以從本地的localStorage對象進行獲取和處理,也可通過介面獲取資料庫記錄的購物車信息,本案例介紹通過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>

這裡主要就是根據數據,動態構建divCart裡面的列表數據,相關的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">規格:<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-

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • `@SessionAttributes` 註解只用作用在 類 上,作用是將指定的 Model 的鍵值對保存在 session 中。可以讓其他請求共用 session 中的鍵值對。 指定保存的屬性名 作用是將 Model 中指定 屬性名 的鍵值對保存在 session 中。 下麵的代碼中, 請求將 M ...
  • 當下,Python 比以往的任何時候都更加流行,人們每天都在實踐著 Python 是多麼的強大且易用。 我從事 Python 編程已經有幾年時間了,但是最近6個月才是全職的。下麵列舉的這些事情,是我最開始使用 Python 的時候,就希望清楚的: 字元串操作 列表推導 Lambda 和 Map 函數 ...
  • 什麼是 Opcache 每一次執行 PHP 腳本的時候,該腳本都需要被編譯成位元組碼,而 OPcache 可以對該位元組碼進行緩存,這樣,下次請求同一個腳本的時候,該腳本就不需要重新編譯,這極大節省了腳本的執行時間,從而讓應用運行速度更快,同時也節省了伺服器的開銷。 用數字說話 我們當然很想知道到底進行 ...
  • 【目錄】 一、操作系統發展史 二、進程發展史及演算法演變 三、多道技術 四、同步非同步/阻塞非阻塞概念 五、創建進程的兩種方式 一、操作系統發展史 1、第一代電腦(1940~1955):真空管和穿孔卡片 (1)特點: 沒有操作系統的概念 所有的程式設計都是直接操控硬體 (2)優點:程式員在申請的時間段 ...
  • 輸入一個1到7的數字,輸出對應的星期名的縮寫。1 Mon2 Tue3 Wed4 Thu5 Fri6 Sat7 Sun輸入格式:輸入1到7之間數字輸出格式:輸出對應的星期名的縮寫代碼如下:#!/usr/bin/python# -*- coding: utf-8 -*-n = int(input())i... ...
  • #創建一個文件,在該文件中創建兩個字典,一個保存名字和星座,另一個保存星座和性格特點,#最後從這兩個字典取出相應的信息組合成想要的結果:name = ['綺夢','冷伊一','香凝','黛蘭'] sign_person = ['水瓶座','射手座','雙魚座','雙子座'] sign_all =[' ...
  • 在經過前面八篇文章(abp(net core)+easyui+efcore實現倉儲管理系統——入庫管理之一(三十七) 至abp(net core)+easyui+efcore實現倉儲管理系統——入庫管理之八(四十四) )的學習之後,我們知道了已經基本完成了入庫管理功能。在這篇文章中我們來增加更新與刪... ...
  • 如題,納悶為什麼有空白子項並且Clear也沒用,所以搜了下,傳送門https://www.cnblogs.com/gc2013/p/4103910.html 使用的是ListView的Details視圖,提一下。 由於博主分析了很多我沒細看,因為我只是想解決這個簡單的問題,類似於直接把第一項給移除掉 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...