C#开发微信门户及选拔(40)–使用微信JSAPI达成微信支付功效

图片 1

在作者前边的几篇博客,有介绍了微信支付、微信红包、公司付款等各类和开发有关的操作,然而上边都是基于微信1般API的卷入,本篇小说继续微信支付那1核心,继续介绍基于微信网页JSAPI的主意提倡的微信支付效用完成,微信的JSAPI相对于平日的API操作,调节和测试未有那么方便,而且有时某些错误须求反复核实。本篇小说基于实际的微信网页支付案例,对微信JSAPI的开发完成进行介绍。

决定开始的201八,各大广播台的跨年晚会争相表演,娱乐八卦也在不断更新,永远不会少的各类谈话的资料。

1、微信JS-SDK的知识

在本身前边《C#支付微信门户及运用(3玖)–使用微信JSSDK完毕签到的法力》介绍的剧情之中,有介绍了许多JS-SDK的基础知识,我们根据网页发起的微信支付,大家也是依据JS-SDK的基本功上实行发起的,由此要求掌握这么些JS-SDK的运用手续。

貌似的话,我们网页JSAPI发起的微信支付,需求动用wx.chooseWXPay的操作方法,而那几个点子也是亟需在成就wx.config开端化的时候,由界面成分进行接触处理的。

诸如我们得以那样达成成套微信支付的处理进程:

壹)先选择JS对API实行开首化配置

    wx.config({
        debug: false,
        appId: appid, // 必填,公众号的唯一标识
        timestamp: timestamp, // 必填,生成签名的时间戳
        nonceStr: noncestr, // 必填,生成签名的随机串
        signature: signature, // 必填,签名,见附录1
        jsApiList: [
           'checkJsApi',
           'chooseWXPay',
           'hideOptionMenu'
        ]
    });

 

二)使用wx.chooseWXPay发起微信支付

wx.chooseWXPay({
    timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
    nonceStr: '', // 支付签名随机串,不长于 32 位
    package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
    signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
    paySign: '', // 支付签名
    success: function (res) {
        // 支付成功后的回调函数
    }
});

备注:prepay_id 通过微信支付统一下单接口得到,paySign
选取统一的微信支付 Sign 签名生成方法,注意那里 appId 也要到场签署,appId
与 config 中传来的 appId 1致,即最终插足签署的参数有appId, timeStamp,
nonceStr, package, signType。

 

叁)获取用户的openid

在部分JSAPI操作里面,有时候要求传入当前用户的openid,由于这一个值,一般是无法直接获取的,但足以由此用户授权代码获取,由此大家能够在菜单中陈设好重定向的ULX570L,依照U揽胜L获取相应的code,然后解析code为对应的openid即可。

通过code换取的是二个例外的网页授权access_token,与功底支撑中的access_token(该access_token用于调用其他接口)不相同。公众号可由此下述接口来赢得网页授权access_token。假设网页授权的功用域为snsapi_base,则本步骤中获得到网页授权access_token的同时,也博获得了openid,snsapi_base式的网页授权流程即到此甘休。

获取code后,请求以下链接获取access_token: 
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

 

1到跨年时刻就会特地敏感的样板,二零一9年的仇敌圈新浪都在晒1九虚岁的照片,起首没弄领会在这之中缘由,还想着一柒年的时候也有失晒18周岁的肖像。

二、微信支付JSAPI开端化的参数处理

要取得有关的JS-SDK的相干接口参数,大家需求先生成JSAPI-Ticket凭证,生成那几个证据代码接口完结如下所示。1般的话,这几个接口的数码须要缓存起来的,具体可以团结达成拍卖。

        /// <summary>
        /// 获取JSAPI_TICKET接口
        /// </summary>
        /// <param name="accessToken">调用接口凭证</param>
        /// <returns></returns>
        public string GetJSAPI_Ticket(string accessToken)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi", accessToken);
            var result = JsonHelper<GetTicketResult>.ConvertJson(url);
            return result != null ? result.ticket : null;
        }

作者们要落到实处JSSDK签名的处理,必须先依照多少个变量,营造好UCRUISERL字符串,具体的处理进程,大家能够把它们逐壹放在一个Hashtable里面,如下代码所示。

        /// <summary>
        /// 获取JSSDK所需要的参数信息,返回Hashtable结合
        /// </summary>
        /// <param name="appId">微信AppID</param>
        /// <param name="jsTicket">根据Token获取到的JSSDK ticket</param>
        /// <param name="url">页面URL</param>
        /// <returns></returns>
        public static Hashtable GetParameters(string appId, string jsTicket, string url)
        {
            string timestamp = GetTimeStamp();
            string nonceStr = GetNonceStr();

            // 这里参数的顺序要按照 key 值 ASCII 码升序排序  
            string rawstring = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url + "";

            string signature = GetSignature(rawstring);
            Hashtable signPackage = new Hashtable();
            signPackage.Add("appid", appId);
            signPackage.Add("noncestr", nonceStr);
            signPackage.Add("timestamp", timestamp);
            signPackage.Add("url", url);
            signPackage.Add("signature", signature);
            signPackage.Add("jsapi_ticket", jsTicket);
            signPackage.Add("rawstring", rawstring);

            return signPackage;
        }

诸如此类把它们位于哈希表里面,方便咱们领到出来使用。

    wx.config({
        debug: false,
        appId: appid, // 必填,公众号的唯一标识
        timestamp: timestamp, // 必填,生成签名的时间戳
        nonceStr: noncestr, // 必填,生成签名的随机串
        signature: signature, // 必填,签名,见附录1
        jsApiList: [
           'checkJsApi',
           'chooseWXPay',
           'hideOptionMenu'
        ]
    });

为了在MVC视图页面里面,设置大家总计出来的值,壹般我们必要在后台实行计算好,并把它们放在ViewBag变量中就足以在页前面端采纳了,如下所示是MVC视图页面包车型地铁后台代码。

        /// <summary>
        /// 刷新JS-SDK的票据
        /// </summary>
        protected virtual void RefreshTicket(AccountInfo accountInfo)
        {
            Hashtable ht = baseApi.GetJSAPI_Parameters(accountInfo.AppID, accountInfo.AppSecret, Request.Url.AbsoluteUri);
            ViewBag.appid = ht["appid"].ToString();
            ViewBag.nonceStr = ht["noncestr"].ToString();
            ViewBag.timestamp = ht["timestamp"].ToString();
            ViewBag.signature = ht["signature"].ToString();
        }

如此那般,在MVC的视图页面里面,大家的代码能够这么落成JSAPI变量的起初化。

    <script language="javascript">
    var openid = '@ViewBag.openid';
    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',
           'chooseWXPay',
           'hideOptionMenu'
        ]
    });

 

固然未有共同进入晒照大队,但也记念了下17/1八的那段日子。庆幸当时温馨并不曾会师杀马特的大潮,就算当时拙劣又天真。

三、微信支付JSAPI发起微信支付的参数处理

在第叁小节里面,作者关系了,早先化JS-API后,还须要使用wx.chooseWXPay发起微信支付,这么些接口也有多少个相关的参数。

wx.chooseWXPay({
    timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
    nonceStr: '', // 支付签名随机串,不长于 32 位
    package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
    signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
    paySign: '', // 支付签名
    success: function (res) {
        // 支付成功后的回调函数
    }
});

中间那里的timestamp和nonceStr的规则和前边开端化操作的参数规则平等,可是注意不可能和初叶化接口的timestamp和nonceStr保持同等,不然发起支付会产出【 支付验证签名失败】的错误。

package的变量正是大家调用统一下单接口的得到的预下单id,格式如下所示:

prepay_id=wx2016051517463160322779de0375788970

而为了拿走这些预下单的ID,大家先须要依照统一下单接口的急需,创设3个数目对象,如下所示。

                PayOrderData data = new PayOrderData()
                {
                    product_id = id,
                    body = "测试支付" + id,
                    attach = "爱奇迪技术支持",
                    detail = "测试JSAPI支付" + id,
                    total_fee = 1,
                    goods_tag = "test" + id,
                    trade_type = "JSAPI",
                    openid = openid
                };

下一场调用前边封装过的联合下单接口API获取相应的联结下单ID

                TenPayApi api = new TenPayApi(accountInfo);
                var orderResult = api.UnifiedOrder(data);
                LogHelper.Debug(string.Format("统一下单结果:{0}", (orderResult != null) ? orderResult.ToJson() : "为空值"));

                if (string.IsNullOrEmpty(orderResult.prepay_id) || string.IsNullOrEmpty(orderResult.appid))
                {
                    throw new WeixinException("统一下单结果返回失败!");
                }

signType固定为MD5,

最后剩余paySign那几个相比较复杂的参数了,那个参数正是急需依据前面那么些参数举办签订契约的值。微信支付的签约依旧和普通API的做法(在方今介绍微信支付的时候,有介绍过有关的条条框框,具体能够看看《C#支出微信门户及使用(32)–微信支付接入和API封装使用》),引进实体类 WxPayData 来囤积一些事情参数,以及贯彻参数的签字处理。

值得注意的是,使用普通API的签订契约为Sign,而选择JSAPI的签订契约变量名字为paySign,两者处理逻辑一样,只是名称分裂。

那样大家在后台处理有关的变量的代码如下所示。

        /// <summary>
        /// 获取JSAPI方式的微信字符串参数对象
        /// </summary>
        /// <param name="accountInfo">当前账号</param>
        /// <param name="prepay_id">统一下单ID</param>
        /// <returns></returns>
        private WxPayData GetJSPayParam(AccountInfo accountInfo, string prepay_id)
        {
            WxPayData data = new WxPayData();
            data.SetValue("appId", ViewBag.appId);
            data.SetValue("timeStamp", data.GenerateTimeStamp());
            data.SetValue("nonceStr", data.GenerateNonceStr());
            data.SetValue("signType", "MD5");
            data.SetValue("package", string.Format("prepay_id={0}", prepay_id));

            data.SetValue("paySign", data.MakeSign(accountInfo.PayAPIKey));//签名
            return data;
        }

接下来,再定义贰个控制器接口,重返相关的参数数据,部分逻辑代码如下所示。那样方便前端通过JSON的格式获取相应的变量值。

                //支付需要的参数
                WxPayData param = GetJSPayParam(accountInfo, orderResult.prepay_id);
                LogHelper.Debug("GetJSPayParam:" + param.ToJson());

                var obj = new
                {
                    timeStamp = param.GetString("timeStamp"),
                    nonceStr = param.GetString("nonceStr"),
                    signType = param.GetString("signType"),
                    package = param.GetString("package"),
                    paySign = param.GetString("paySign")
                };
                return Content(obj.ToJson());

在头里页面,通过ajax方式赢得发起微信支付的连带参数,代码如下所示。

    //发起一个微信支付
    function chooseWXPay(id) {
        //alert(window.location.href);
        var uid = getUrlVars()["uid"];
        $.ajax({
            type: 'POST',
            url: '/JSSDKTest/GetWXPayData',
            //async: false, //同步
            dataType: 'json',
            data : {
                id: id,
                uid: uid,
                openid : openid
            },
            success: function (json) {
                wx.chooseWXPay({
                    appId: appid,
                    timestamp: json.timeStamp,  // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
                    nonceStr: json.nonceStr,    // 支付签名随机串,不长于 32 位
                    package: json.package,      // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
                    signType: json.signType,    // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
                    paySign: json.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("用户取消了支付");
                        //window.location.href = "/Pay/order_details?orderId=" + $("#orderId").val();
                    }
                });
                wx.error(function (res) {
                    $.toast("调用支付出现异常");
                    //window.location.href = "/Pay/order_details?orderId=" + $("#orderId").val();
                })
            },
            error: function (xhr, status, error) {
                $.toast("操作失败" + xhr.responseText); //xhr.responseText
            }
        });
    };

 

入秋以来还未有当真下过一场雪,却总感觉二零一九年的冬季专程寒冷,七月回了趟老家参预老哥的婚礼,捧了回茶领了回红包。

四、微信支付JSAPI发起微信支付的界面效果

经过上边的代码,大家能够顺遂发起微信支付,并得以见见实际的测试结果了,读者可以关切大家的民众号【都柏林爱奇迪】对中间微信支付实行测试通晓。

图片 2  图片 3  图片 4

图片 5 图片 6  图片 7

微信支付成功后,我们1致能够在微信支付的对话里面看到响应的结果了。

图片 8

 

假设对这些《C#开发微信门户及应用》类别感兴趣,能够关切自个儿的别样小说,类别小说如下所示:

C#支付微信门户及使用(40)–使用微信JSAPI达成微信支付作用

C#开发微信门户及运用(3玖)–使用微信JSSDK完结签到的作用

C#付出微信门户及应用(3八)–微信摇壹摇红包功效

C#支出微信门户及接纳(叁7)–微信公众号标签管理成效

C#支付微信门户及利用(3六)–微信卡劵管理的包装操作

C#开发微信门户及使用(35)–微信支付之集团付款封装操作

C#付出微信门户及运用(3四)–微信裂变红包

C#支付微信门户及应用(3三)–微信现荧光色包的包裹及应用

C#开发微信门户及采纳(3二)–微信支付接入和API封装使用

C#开发微信门户及利用(3一)–微信语义领会接口的落到实处和拍卖

C#付出微信门户及使用(30)–新闻的群发处理和预览效率

C#支出微信门户及运用(28)–微信“摇一摇·周围”功效的行使和接口的贯彻

C#支付微信门户及利用(二柒)-公众号模板消息管理 

C#开发微信门户及使用(二6)-公众号微信托投资料管理

C#付出微信门户及运用(25)-微信公司号的客户端管住功能

C#支出微信门户及应用(2四)-微信小店货架新闻保管

C#支付微信门户及采纳(2三)-微信小店商品质量管理理理接口的包装和测试

C#支付微信门户及利用(2二)-微信小店的开销和应用

C#开发微信门户及使用(二一)-微信公司号的音讯和事件的选取处理及解密 

C#付出微信门户及选拔(20)-微信集团号的菜系管理

C#付出微信门户及利用(1玖)-微信公司号的音讯发送(文本、图片、文件、语音、录像、图像和文字音信等)

C#付出微信门户及利用(18)-微信集团号的通信录管理支出之成员管理

C#付出微信门户及使用(一七)-微信集团号的通信录管理支出之部门管理

C#支出微信门户及运用(1陆)-微信集团号的布置和动用

C#支付微信门户及利用(1伍)-微信菜单扩充扫一扫、发图片、发地理地点作用

C#支付微信门户及使用(14)-在微信菜单中央银行使重定向获取用户数量

C#支付微信门户及采用(一三)-使用地理地点扩张相关应用

C#开发微信门户及利用(1贰)-使用语音处理

C#支出微信门户及使用(1一)–微信菜单的有余呈现方法介绍

C#支出微信门户及运用(十)–在管理类别中一只微信用户分组消息

C#支付微信门户及利用(9)-微信门户菜单管理及提交到微信服务器

C#支付微信门户及使用(八)-微信门户应用管理连串机能介绍

C#开发微信门户及运用(七)-微信多客服作用及支付集成

C#付出微信门户及应用(陆)–微信门户菜单的田管操作

C#支出微信门户及选用(5)–用户分组音讯保管

C#支付微信门户及利用(4)–关切用户列表及详细音讯管理

C#付出微信门户及使用(三)–文本新闻和图像和文字消息的答问

C#付出微信门户及运用(2)–微信新闻的拍卖和回应

C#支出微信门户及应用(一)–开首应用微信接口

在老家过了几天吃吃喝喝的生活,蓝天白云阳光明媚,不可能不感慨乡下的好空气。告别乡亲父老之后又重返阴霾之中。

长大后第一回有人在火车站接送,出站的一刹那间寓指标大脸,有个别满意和安心。几天不见就接近隔了天长地远,兴高采烈联手回家。

1陆年的岁末本来陈设17年要1个人在世一年,作为从不曾家破人亡的3遍独居机会。可是结果陈设依然赶不上变化,结果从年中开端了新的相处画面。个中闹了一起大乌龙,事实大白了结果还更懊恼。

一7年四月又去了紫禁城和颐和园,前3回去照旧二十年前的胶卷时期,未来纵然各处举着自拍杠了,不过景区里的零食依旧1如既往价高。二拾年前是被领着去的孩子,本次就成了陪着孩子一块去的父老母了。紫禁城和颐和园也依旧那么大,人工新生儿窒息那么多,照样未有走个通透,照样依旧一知半解一般的记名。看看现在仍是能够不能来一遍真正的走心之旅。

二月尾东戴河的2天壹夜跟团游,因为外出匆忙未有准备泳衣救生圈,没能下水只是在水边踩着沙子走圈。让海水一点一点地打湿脚面,细腻的砂石一点一点在当下蹋陷,瞧着对面和海连成一片的天。

找了几趟房子后,6月尾正式迁居到高碑店,不熟悉的地方素不相识的小区。3个又1个拉开的包装箱,开始找到各自安置的职分,空荡的空中一丝丝被填满。找超级市场找小吃然后启幕摆灶开火,房子初阶成为投机的窝点。

九月匆匆促地去了王府井,拍了些照片,吃了顿炸鸡就往回赶,得赶时间去高铁站,夜里的车站又是另1种样子。

四月的某一天坐大巴去了趟秦皇岛市区,在公园散步,看看因为过往换乘费用了些日子,到六月春池,直隶总督府时就早已8九不离10他们的下班时间,所以都不曾订票进入。在相邻逛了逛街,吃了点小吃就又到车站等车回去。二个多刻钟的车程后到家。

1七年的其余时间里就不曾去别的地点了,布署的外出都以1八年的移动了。

一七年还做了众多梦,种种各个奇奇怪怪的梦。差不离是因为喜好旅行,梦中出发去了累累地点,坐车厢里通过海边和油绿菜花,满是驼灰气球的欧式建筑群,变成小玩偶拉线前行,绿意满满的大老林,站在硝烟弥漫的大街宗旨……身当其境的天生丽质梦境,希望1八年也能间接有梦。