微信公众号开发(三)微信支付

统一下单接口URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder

1、提交支付的视图页面
@{
    Layout = null;
    ViewBag.Title = "订单支付";
    string subNumber = ViewBag.SubNumber;//订单号
    string errmsg = ViewBag.Errmsg;//失败信息
    string json = ViewBag.Json;//jsapi支付请求json
    string callBackUrl = ViewBag.CallBackUrl;//支付完成回调url
    string hiscallBackUrl = ViewBag.HiscallBackUrl;//订单url
}

<script type="text/javascript" src="http://images.zhongmin.cn/js/jquery-1.9.1.min.js"></script>

<body onload="wxPay()">
    <form id="form1">
        <input type="hidden" id="hdnSubNumber" value="@subNumber" />
    </form>
    <script type="text/javascript">
    function wxPay() {
        if ('@errmsg' == null) {//判断是否下单成功
            document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
                //公众号支付
               WeixinJSBridge.invoke('getBrandWCPayRequest', '@json',
                 function (res) {
                     if (res.err_msg == "get_brand_wcpay_request:ok") {
                         alert('支付完成!');
                         location.href = "@callBackUrl";//支付完成转到回调页面
                     }
                     else {
                         location.href = "@hiscallBackUrl?key=@subNumber";//失败,返回订单页面
                     }                         
                 });
                WeixinJSBridge.log('pay ready.');
            }, false)
        } else {
            alert('@errmsg'); //失败信息              
        }
    }
    </script>
</body>
2、Controller后台处理
public ActionResult Trade()
{
    string subNumber = '';
    ViewBag.HdnIsWxPay = "0";
    if (!string.IsNullOrEmpty(Request.QueryString["key"]))
    {
        subNumber = Request.QueryString["key"].Trim();
        try
        {
            WxPay();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    return View();
}

private void WxPay()
{
    WxPayHelper wxPayHelper = new WxPayHelper();
    //先设置基本信息
    wxPayHelper.SetAppId(Config.APPID); //微信AppId
    wxPayHelper.Setmch_id(Config.SETMCH_ID);//商户id
    wxPayHelper.SetPayKey(Config.PAYKEY);//签名

    wxPayHelper.SetParameter("body", productName);//商品描述
    wxPayHelper.SetParameter("out_trade_no", OrderID);//商户订单号
    wxPayHelper.SetParameter("notify_url", Config.NOTURL);//下单结果回调地址
    wxPayHelper.SetParameter("spbill_create_ip", Config.getIp());//终端IP
    wxPayHelper.SetParameter("total_fee", allPrice);//价格,整数,需要转换成以‘分’为单位
    wxPayHelper.SetParameter("trade_type", "JSAPI");//交易类型,JSAPI表示公众号支付
    string wxOpenId = Session["weixinOpenId"];
    ViewBag.WxOpenId = wxOpenId;
    wxPayHelper.SetParameter("openid", wxOpenId);//获取openId
    //先设置基本信息
    Wxpay.WxPayHelper.UnifyReceive receiveModel = null;
    string json = wxPayHelper.CreateBizPackage(out receiveModel);//获取json数据
    string errmsg = receiveModel.ErrorInfo;

    ViewBag.Errmsg = errmsg;
    ViewBag.Json = json;
    ViewBag.HiscallBackUrl = "";
    ViewBag.SubNumber = subNumber;
    ViewBag.CallBackUrl = "";
    ViewBag.Openid = wxPayHelper.GetParameter("openid");
}
3.WxPayHelper微信支付下单
public class WxPayHelper
    {
        public WxPayHelper()
        {
            this.parameters = new Dictionary<string, string>();
            this.AppId = "";
            this.AppKey = "";
            this.PayKey = "";
            this.SignType = "MD5";
            this.mch_id = "";
        }

        private Dictionary<string, string> parameters;
        private string AppId;
        private string AppKey;
        private string PayKey;
        private string SignType;
        private string mch_id;

        public void SetAppId(string str)
        {
            AppId = str;
        }
        public void SetPayKey(string str)
        {
            PayKey = str;
        }
        public void Setmch_id(string str)
        {
            mch_id = str;
        }
        public void SetParameter(string key, string value_ren)
        {
            parameters.Add(key, value_ren);
        }
        public string GetParameter(string key)
        {
            return parameters[key];
        }
        private Object CheckParameters()
        {
            if (parameters["body"] == "" || parameters["out_trade_no"] == ""
                    || parameters["total_fee"] == "" || parameters["trade_type"] == "" || parameters["notify_url"] == null || parameters["spbill_create_ip"] == ""
                    )
            {
                return false;
            }
            return true;
        }
        public string GetPayPackage(out UnifyReceive receiveModel)
        {
            if (!parameters.ContainsKey("appid"))//判断是否包含指定的键
            {
                parameters.Add("appid", AppId);
            }
            if (!parameters.ContainsKey("nonce_str"))
            {
                parameters.Add("nonce_str", Wxpay.CommonUtil.CreateNoncestr());
            }
            if (!parameters.ContainsKey("mch_id"))
            {
                parameters.Add("mch_id", mch_id);
            }
            string unSignParaString = Wxpay.CommonUtil.FormatBizQueryParaMap(parameters);//拼接签名字符串
            parameters.Add("sign", Wxpay.MD5SignUtil.Sign(unSignParaString, PayKey));//生成签名
            //把 parameters 组装成xml  发送这个XML取得PrePay_Id
            string xml = Wxpay.CommonUtil.ArrayToXml(parameters);
            receiveModel = new UnifyReceive(HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder", xml));
            return receiveModel.prepay_id;//获取预支付交易会话标识,该值有效期为2小时
        }
        // 生成jsapi支付请求json
        public string CreateBizPackage(out UnifyReceive receiveModel)
        {
            Dictionary<string, string> nativeObj = new Dictionary<string, string>();
            if ((bool)((CheckParameters())) == false)
            {
                throw new SDKRuntimeException("生成package参数缺失!");
            }
            nativeObj.Add("appId", AppId);
            string prepay_id = GetPayPackage(out  receiveModel);
            nativeObj.Add("package", string.Format("prepay_id={0}", prepay_id));//订单详情扩展字符串
            nativeObj.Add("timeStamp", ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000).ToString());//时间戳
            nativeObj.Add("nonceStr", Wxpay.CommonUtil.CreateNoncestr());//随机字符串
            nativeObj.Add("signType", SignType);//签名方式
            string unSignParaString = Wxpay.CommonUtil.FormatBizQueryParaMap(nativeObj);//拼接字符串
            nativeObj.Add("paySign", Wxpay.MD5SignUtil.Sign(unSignParaString, PayKey));//进行MD5签名
            var entries = nativeObj.Select(d => string.Format("\"{0}\": \"{1}\"", d.Key, d.Value));
            return "{" + string.Join(",", entries.ToArray()) + "}";
        }

        //post请求方法
        public string HttpPost(string url, string param)
        {
            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);//验证服务器证书回调自动验证
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.Accept = "*/*";
            request.Timeout = 15000;
            request.AllowAutoRedirect = false;

            StreamWriter requestStream = null;
            WebResponse response = null;
            string responseStr = null;

            try
            {
                requestStream = new StreamWriter(request.GetRequestStream());
                requestStream.Write(param);
                requestStream.Close();

                response = request.GetResponse();
                if (response != null)
                {
                    StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                    responseStr = reader.ReadToEnd();
                    reader.Close();
                }
            }
            catch (Exception ex)
            {
                Tools.PublicConfig.log_Append("HttpPost 请求失败" + ex.Message, "Pay", "WxPay_V3.log");

            }
            finally
            {
                request = null;
                requestStream = null;
                response = null;
            }
            Tools.PublicConfig.log_Append("HttpPost 响应数据:" + responseStr, "Pay", "WxPay_V3.log");
            return responseStr;
        }

        public bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {   // 总是接受  
            return true;
        }

        public class UnifyReceive
        {
            /// <summary>
            /// SUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
            /// </summary>
            public string return_code { get; set; }
            /// <summary>
            /// 返回信息,如非空,为错误原因
            /// </summary>
            public string return_msg { get; set; }
            /// <summary>
            /// 微信分配的公众账号ID
            /// </summary>
            public string appid { get; set; }
            /// <summary>
            /// 微信支付分配的商户号
            /// </summary>
            public string mch_id { get; set; }
            /// <summary>
            /// 随机字符串,不长于32位
            /// </summary>
            public string nonce_str { get; set; }
            /// <summary>
            /// 签名
            /// </summary>
            public string sign { get; set; }
            /// <summary>
            /// 业务结果
            /// </summary>
            public string result_code { get; set; }

            private string _prepay_id = string.Empty;
            /// <summary>
            /// 预支付ID
            /// </summary>
            public string prepay_id
            {
                get { return _prepay_id; }
                set { _prepay_id = value; }
            }
            /// <summary>
            /// 交易类型
            /// </summary>
            public string trade_type { get; set; }

            private string _code_url = string.Empty;
            /// <summary>
            /// 二维码链接
            /// </summary>
            public string code_url
            {
                get { return _code_url; }
                set { _code_url = value; }
            }

            private string _error = string.Empty;

            /// <summary>
            /// 错误提示
            /// </summary>
            public string ErrorInfo
            {
                get { return _error; }
                set { _error = value; }

            }

            public UnifyReceive(string xml)
            {
                try
                {

                    XElement doc = XElement.Parse(xml);
                    return_code = doc.Element("return_code").Value;

                    if (return_code == "SUCCESS")
                    {
                        appid = doc.Element("appid").Value;
                        mch_id = doc.Element("mch_id").Value;
                        nonce_str = doc.Element("nonce_str").Value;
                        sign = doc.Element("sign").Value;
                        result_code = doc.Element("result_code").Value;
                        if (result_code == "SUCCESS")
                        {
                            trade_type = doc.Element("trade_type").Value;
                            prepay_id = doc.Element("prepay_id").Value;
                            if (trade_type == "NATIVE")
                            {
                                code_url = doc.Element("code_url").Value;
                            }
                            trade_type = doc.Element("trade_type").Value;
                        }
                        else
                        {
                            ErrorInfo = "err_code:" + doc.Element("err_code").Value + ";err_code_des" + doc.Element("err_code_des").Value;
                        }
                    }
                    else
                    {
                        return_msg = doc.Element("return_msg").Value;
                        ErrorInfo = return_msg;
                    }
                }
                catch (Exception ex)
                {

                    ErrorInfo = "解析HttpPost响应:" + ex.Message;
                }
            }
        }
    }
4、用到的方法:

拼接字符串

public static string FormatBizQueryParaMap(Dictionary<string, string> paraMap)
        {
            string buff = "";
            try
            {
                var result = from pair in paraMap orderby pair.Key select pair;
                foreach (KeyValuePair<string, string> pair in result)
                {
                    if (pair.Key != "")
                    {
                        string key = pair.Key;
                        string val = pair.Value;
                        buff += key + "=" + val + "&";
                    }
                }
                if (buff.Length != 0)
                {
                    buff = buff.Substring(0, (buff.Length - 1));
                }
            }
            catch (Exception e)
            {
            }
            return buff;
        }

MD5加密签名

public static String Sign(String content, String key)
        {
            String signStr = content + "&key=" + key;
            return MD5Util.MD5(signStr).ToUpper();
        }

转换为xml格式

public static string ArrayToXml(Dictionary<string, string> arr)
        {
            String xml = "<xml>";
            foreach (KeyValuePair<string, string> pair in arr)
            {
                String key = pair.Key;
                String val = pair.Value;
                if (IsNumeric(val))
                {
                    xml += "<" + key + ">" + val + "</" + key + ">";
                }
                else
                    xml += "<" + key + "><![CDATA[" + val + "]]></" + key + ">";
            }
            xml += "</xml>";
            return xml;
        }

随机字符串:

public static String CreateNoncestr()
        {
            String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            String res = "";
            Random rd = new Random();
            for (int i = 0; i < 16; i++)
            {
                res += chars[rd.Next(chars.Length - 1)];
            }
            return res;
        }
5、如果下单成功,前端开启微信支付监听WeixinJSBridgeReady
 var json= '{"appId": "",//应用ID
    "package": "",//订单详情扩展字符串
    "timeStamp": "",//时间戳
    "nonceStr": "",//随机字符串
    "signType": "",//签名类型
    "paySign": ""}'; //签名

    function Wxpay() 
    { 
    document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() { 
        WeixinJSBridge.invoke('getBrandWCPayRequest',json,function(res){ 

         WeixinJSBridge.log(res.err_msg); 

         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; 
         } 
        }); 
        }, false); 
    } 

官方文档,微信内H5调起支付:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7

微信统一下单:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

简单整理了一下,如果有错误不足之处请大家多多指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YuanlongWang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值