欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

利用微信公众号实现商品的展示和支付(1)

程序员文章站 2022-04-03 09:39:14
在前面随笔《利用微信公众号实现商品的展示和支付(1)》介绍了商品的列表和明细信息的处理,本篇随笔接着上一篇,继续介绍关于商品的微信支付和购物车处理方面,其中微信支付里面,也涉及到了获取微信共享地址的处理,从而个更加方便录入邮寄地址信息;购物车可以从本地的localStorage对象进行获取和处理,也... ......

在前面随笔《利用微信公众号实现商品的展示和支付(1)》介绍了商品的列表和明细信息的处理,本篇随笔接着上一篇,继续介绍关于商品的微信支付和购物车处理方面,其中微信支付里面,也涉及到了获取微信共享地址的处理,从而个更加方便录入邮寄地址信息;购物车可以从本地的localstorage对象进行获取和处理,也可通过接口获取数据库记录的购物车信息,本案例介绍通过localstorage进行购物车处理方式。

1、商品的微信支付处理

商品的微信支付处理,其中涉及了两个场景,一个是直接购买,一个是通过购物车的结算方式,两个处理界面有所差异,直接付款购买的界面是对当前选中商品进行单项的结算处理,默认数量为1;而购物车订单结算则是利用购物车的记录进行微信支付的处理,购物车可以从本地的localstorage对象进行获取和处理,也可通过接口获取数据库记录的购物车信息,本案例介绍通过localstorage进行购物车处理方式。

对选中商品直接结算界面如下所示。

利用微信公众号实现商品的展示和支付(1)

 购物车结算界面如下所示。

利用微信公众号实现商品的展示和支付(1) 

先来看看微信共享地址的处理界面,代码如下所示。

<!--配送地址处理-->
<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);
    });
}

而微信支付的处理,我们可以通过参考官方的接口定义来处理我们的代码。

利用微信公众号实现商品的展示和支付(1)

 我们先来金额汇总的界面展示,通过按钮我们发起微信支付的处理操作。

<!--金额及发起支付-->
<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);
}

这样我们就可以发起微信支付处理操作了。

利用微信公众号实现商品的展示和支付(1)

当然,我们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购物车的处理,我们引入一个对这个购物车的操作处理,主要就是添加、更新、获取列表、清空列表等相关操作。

利用微信公众号实现商品的展示和支付(1)

 对于以上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>

购物车列表界面如下所示,主要就是展开存储里面的商品信息,并汇总展示,如下所示。

利用微信公众号实现商品的展示和支付(1) 

这个页面视图的代码如下所示。

<!--主体-->
<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-id" value="${item.id}"/>
                                 </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>`;

        $("#divcart").append(html);
    });
    
    ...................

对于数量的修改,我们同时修改购物车里面的数据即可,如下代码所示。

//对数量改变进行处理,更新购物车的对应产品id的数量
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是对购物车数据的修改。

//修改购物车的内容
function updateproductnum(id, number) {
    console.log(id + ':' + number);
    cart.updateproductnum(id, number);

    //显示数量和金额            
    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 () {
        //取消操作
    });
});

购物车的结算页面,前面介绍过了,就是如下图所示,类似我们直接购买商品的界面。

利用微信公众号实现商品的展示和支付(1)

这个地方主要差异在于也是动态获取一个或多个商品记录的信息,如下所示。

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">规格:<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">数量×<em class="name">1</em></span></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>*@
        </div>

js代码主要就是动态构建列表,divcart里面的内容实现根据购物车商品列表进行处理,如下代码所示。

        //显示购物车列表
        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">规格:<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">数量×<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);

            //显示数量和金额
            var amount = orderdetail.totalamount;//获取购物车的总金额
            $("#totalmoney").text(amount);
        }