微信JSAPI支付

微信公众号支付流程:首先调用【网页授权获取用户信息】接口获取用户的openid和access_token:

一、 获取code及openid

1.前台页面首先判断code是否存在,不存在则构造网页授权获取code的URL

 mui.ready(function () {

        //读取localStorage的用户信息 if (user != undefined) { user = JSON.parse(user); userid = user.UserId; var vCode = getQueryString("code"); if (is_weixn()) { orderid = getQueryString("oid"); amount = getQueryString("amount"); } $("#h_amount").html(amount); if (is_weixn()) { mui.ajax({ url: '/Payment/WXPay/getWxInfo', type: 'post', data: { code: vCode }, dataType: 'JSON', //服务器返回json格式数据 //timeout: 5000, //超时时间设置为5秒; success: function (json) { var res = eval('(' + json + ')'); //获取json数据 openid = res.openid; access_token = res.access_token; }, error: function (xhr, type, errorThrown) { console.log('错误'); //异常处理; //mui.alert('网络延时,请重新加载!', '系统提示'); } }); } } else { } }); 

判断是否微信浏览器代码:

 //判断是否微信内部浏览器
    function is_weixn() { var ua = navigator.userAgent.toLowerCase(); if (ua.match(/MicroMessenger/i) == "micromessenger") { return true; } else { return false; } } 

------转到后台获取code

  /// <summary>
        /// 充值页面 /// </summary> /// <returns></returns> public ActionResult Recharge() { if (Session["openid"] == null) { try { //调用【网页授权获取用户信息】接口获取用户的openid和access_token string redirurl = HttpUtility.UrlEncode("http://xxx.com/Payment/WXPay/Recharge"); jsp.GetOpenidAndAccessToken(redirurl); } catch (Exception ex) { //Response.Write(ex.ToString()); //throw; } } return View(); } 

网页授权用户的过程:

 public void GetOpenidAndAccessToken(string redirecturi)
        {
            if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString["code"]))
            {
                //获取code码,以获取openid和access_token string code = HttpContext.Current.Request.QueryString["code"]; Log.Debug(this.GetType().ToString(), "Get code : " + code); GetOpenidAndAccessTokenFromCode(code); } else { //构造网页授权获取code的URL string redirect_uri = redirecturi;//HttpUtility.UrlEncode("http://share.chn-nbiot.com/Payment/WXPay/Recharge"); WxPayData data = new WxPayData(); data.SetValue("appid", WxPayConfig.JSAPI_APPID); data.SetValue("redirect_uri", redirect_uri); data.SetValue("response_type", "code"); data.SetValue("scope", "snsapi_base"); data.SetValue("state", "STATE" + "#wechat_redirect"); string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl(); Log.Debug(this.GetType().ToString(), "Will Redirect to URL : " + url); try { HttpContext.Current.Session["url"] = url; //触发微信返回code码 HttpContext.Current.Response.Redirect(url);//Redirect函数会抛出ThreadAbortException异常,不用处理这个异常 } catch (System.Threading.ThreadAbortException ex) { } } } 

解析:

1.首先支付页面会先调用【网页授权获取用户信息】接口获取用户的openid和access_token, 如果code没有获取到,则先构造网页授权获取code的URL。

2.HttpContext.Current.Response.Redirect(url); 就是重定向URL到微信端获取code码。获取到之后在返回到你的界面,取到code码之后,拿着code码获取openid和access_token。

二、统一下单获得签名数据

统一下单:

   public static WxPayData UnifiedOrder(WxPayData inputObj, int timeOut = 6) { inputObj.SetValue("appid", WxPayConfig.JSAPI_APPID);//公众账号ID inputObj.SetValue("mch_id", WxPayConfig.JSAPI_MCHID);//商户号 inputObj.SetValue("spbill_create_ip", WxPayConfig.IP);//终端ip inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串 //签名 inputObj.SetValue("sign", inputObj.MakeSign(WxPayConfig.JSAPI_KEY)); string xml = inputObj.ToXml(); var start = DateTime.Now; string response = HttpService.Post(xml, url, false, timeOut); var end = DateTime.Now; int timeCost = (int)((end - start).TotalMilliseconds); WxPayData result = new WxPayData(); result.FromXml(response); return result; } 

签名的KEY要是商户对应的API秘钥,否则签名错误。

获得统一下单结果:

   public WxPayData GetUnifiedOrderResult(string outno, decimal total_fee, string opid)
        {
            //统一下单 WxPayData data = new WxPayData(); data.SetValue("body", "余额充值"); data.SetValue("attach", "test"); data.SetValue("out_trade_no", outno); data.SetValue("total_fee", decimal.ToInt32(total_fee * 100).ToString()); data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss")); data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss")); data.SetValue("goods_tag", "test"); data.SetValue("trade_type", "JSAPI"); data.SetValue("openid", opid); WxPayData result = WxPayApi.UnifiedOrder(data); if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "") { Log.Error(this.GetType().ToString(), "UnifiedOrder response error!"); // throw new WxPayException("UnifiedOrder response error!"); } unifiedOrderResult = result; return result; } 

微信返回来的return_code和result_code都为SUCCESS的时候,才会正确返回数据,拿到我们想要的数据后,再进行一次签名

        WxPayData newpay = new WxPayData();
        newpay.SetValue("appId", WxPayConfig.JSAPI_APPID); newpay.SetValue("timeStamp", WxPayData.GetTimeStamp()); newpay.SetValue("nonceStr", wpd.GetValue("nonce_str")); newpay.SetValue("package", "prepay_id=" + wpd.GetValue("prepay_id")); newpay.SetValue("signType", "MD5"); newpay.SetValue("paySign", newpay.MakeSign(WxPayConfig.JSAPI_KEY)); //再次生成签名 

注意:时间戳是10位数字,package是固定写法prepay_id=微信返回来的prepay_id,签名方法signType是MD5。

组合一下对象返回到前台拉起微信支付:以下是我的对象名,可自行修改。

但appid、noncestr、timestamp、trade_type、package、signType、sign 是前台必须的字段,一个不能少!!


            ReturnWxpay rwpay = new ReturnWxpay
            {
                appid = newpay.GetValue("appId").ToString(), noncestr = newpay.GetValue("nonceStr").ToString(), timestamp = newpay.GetValue("timeStamp").ToString(), trade_type = wpd.GetValue("trade_type").ToString(), package = newpay.GetValue("package").ToString(), signType = newpay.GetValue("signType").ToString(), sign = newpay.GetValue("paySign").ToString() }; 

-----------回到前台调起支付,以下是固定写法。

注意注意::这里的前台字段的大小写,一定要对应,跟后台有差别,不要搞错了!!

    function callpay() {
        if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } } else { jsApiCall(); } } //调用微信JS api 支付 function jsApiCall() { WeixinJSBridge.invoke('getBrandWCPayRequest', { "appId": paystr.appid, //公众号名称,由商户传入 "timeStamp": paystr.timestamp, //时间戳,自1970年以来的秒数 "nonceStr": paystr.noncestr, //随机串 "package": paystr.package, "signType": paystr.signType, //微信签名方式: "paySign": paystr.sign //微信签名 }, function (res) { if (res.err_msg === "get_brand_wcpay_request:cancel") { mui.alert('支付异常!', '提示'); return false; } else if (res.err_msg === "get_brand_wcpay_request:ok") { window.location.href = "../../../m/PersonalCenter/wallet.html"; mui.alert('支付成功!', '提示'); } return true; } ); } 

如果调起支付没问题,就会有支付界面出现啦。。支付成功后有个回调函数,如果支付成功后会返回re "get_brand_wcpay_request:ok",失败会返回"get_brand_wcpay_request:cancel",可自行处理条抓页面!!

最后附上获取code码的JS
  //获取url的参数
    function getQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r != null) return unescape(r[2]); return null; }

猜你喜欢

转载自www.cnblogs.com/lxyang/p/9093491.html