微信公众号支付

1.获取用户open_id

/// <summary>
        /// 获取openid 并返回视图
        /// </summary>
        /// <param name="Code"></param>
        /// <param name="OrderGuid"></param>
        /// <returns></returns>
        public ActionResult VisaPay(string Code, Guid OrderGuid)
        {
            try
            {
                var appid = "wxxxxxxxxxxxxxxxxxxxxxxx";
                var secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
                if (string.IsNullOrEmpty(Code))
                {
                    //向微信发送请求 获取code
                    string url1 = UrlEncode("http://wechat.yimalx.com/WeChatSite/WeChatPay/VisaPay?orderGuid=" + OrderGuid);
                    var url = string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect", appid, url1);
                    return Redirect(url);
                }
                else
                {
                    //获取token
                    var client = new System.Net.WebClient();
                    client.Encoding = System.Text.Encoding.UTF8;

                    var url = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code", appid, secret, Code);
                    var data = client.DownloadString(url);
                    var serializer = new JavaScriptSerializer();
                    var obj = serializer.Deserialize<Dictionary<string, string>>(data);
                    string accessToken;
                    if (!obj.TryGetValue("access_token", out accessToken))
                        return Redirect("404");

                    var opentid = obj["openid"];

                    var model = OrderInfoManager.Instance.GetById(OrderGuid);
                    ViewData["PayAmount"] = model.PayAmount;
                    ViewData["OrderGuid"] = OrderGuid;
                    string str = WeChatPayHelper.GoToWeCharJSPay(OrderGuid, opentid);
                    CreateLog.SaveLogs("str==============================" + str + "=================================", 1);
                    var codeId = new XmlDocument();
                    codeId.LoadXml(str);
                    var info = new WeChatInfo();
                    //8.读取xml节点的值
                    info.return_code = codeId.SelectSingleNode("xml/return_code").InnerText;
                    info.return_msg = codeId.SelectSingleNode("xml/return_msg").InnerText;
                    info.appid = codeId.SelectSingleNode("xml/appid").InnerText;
                    info.mch_id = codeId.SelectSingleNode("xml/mch_id").InnerText;
                    info.nonce_str = codeId.SelectSingleNode("xml/nonce_str").InnerText;
                    info.openid = opentid;
                    info.sign = codeId.SelectSingleNode("xml/sign").InnerText;
                    info.result_code = codeId.SelectSingleNode("xml/result_code").InnerText;
                    info.prepay_id = codeId.SelectSingleNode("xml/prepay_id").InnerText;
                    info.trade_type = codeId.SelectSingleNode("xml/trade_type").InnerText;

                    string timestamp = WeChatPayHelper.GetTimeStamp();
                    var res = new Dictionary<string, object>
                    {
                        {"appId", info.appid },
                        {"nonceStr", info.nonce_str},
                        {"timeStamp",timestamp},
                        {"signType","MD5"},
                        {"package","prepay_id="+info.prepay_id}
                    };
                    info.sign = WeChatPayHelper.GetSignString(res);

                    info.timeStamp = timestamp;
                    return View(info);
                }
            }
            catch (Exception e)
            {
                CreateLog.SaveLogs(e.Message, 0);
                return Redirect("WeChatSite/WeChatPay/VisaPay?OrderGuid=" + OrderGuid);
            }

        }
GetOpen_id

2.调用统一下单接口生成预付款单

/// <summary>
        /// 微信客户端内部提交支付申请
        /// </summary>
        /// <param name="orderGuid"></param>
        /// <returns></returns>
        [HttpGet]
        public static  string GoToWeCharJSPay(Guid orderGuid, string token)
        {
            var weCharUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            var model = OrderInfoManager.Instance.GetById(orderGuid);
            unifiedorder unOrder = new unifiedorder();
            unOrder.appid = ConfigurationManager.AppSettings["wx_appid"];
            unOrder.mch_id = ConfigurationManager.AppSettings["wx_mch_id"];
            unOrder.nonce_str = Guid.NewGuid().ToString().Replace("-", "");
            unOrder.sign = "";
            unOrder.body = model.ProductName;
            unOrder.out_trade_no = model.OrderCode;
            //payAmountmodel.PayAmount
            unOrder.total_fee = Convert.ToInt32(model.PayAmount * 100);
            unOrder.spbill_create_ip = GetWebClientIp();
            unOrder.notify_url = ConfigurationManager.AppSettings["wechatUrl"] + "WeChatSite/WeChatPay/ProcessingCallback";
            unOrder.trade_type = "JSAPI";
            unOrder.openid = token;
            unOrder.device_info = "WEB";
            var dc = new Dictionary<string, object>()
            {
                {"appid",unOrder.appid},
                {"mch_id",unOrder.mch_id},
                {"total_fee",unOrder.total_fee}, 
                {"out_trade_no",unOrder.out_trade_no},
                {"body",unOrder.body},
                {"notify_url",unOrder.notify_url},
                {"trade_type",unOrder.trade_type},
                {"nonce_str",unOrder.nonce_str},
                {"spbill_create_ip",unOrder.spbill_create_ip},
                {"openid",unOrder.openid},
                //{"scene_info","h5_info"}
            };
            dc.Add("sign", GetSignString(dc));//签名
            //2.将参数转换为xml格式
            var sb = new StringBuilder();
            sb.Append("<xml>");
            foreach (var d in dc)
            {

                sb.Append("<" + d.Key + ">" + d.Value + "</" + d.Key + ">");

            }
            sb.Append("</xml>");
            //应用场景信息
            //1.创建请求连接
            var request = (HttpWebRequest)WebRequest.Create(weCharUrl);
            //2.设置参数

            var data = Encoding.UTF8.GetBytes(sb.ToString());
            //4.设置属性
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = data.Length;
            //5.将转换后的参数以文件流的形式写入到请求中
            using (var stream = request.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }
            //6.声明变量,获取响应
            var response = (HttpWebResponse)request.GetResponse();
            //7.以文件流的方式读取响应结果
            var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
            //
            return responseString;
        }
GoToWeCharJSPay

3.回调

  1).同步回调:前端拉起微信支付界面,判断支付结果

 <script>
        function onBridgeReady() {
            WeixinJSBridge.invoke(
                'getBrandWCPayRequest', {
                    "appId": "@Model.appid",     //公众号名称,由商户传入
                    "timeStamp": "@Model.timeStamp",         //时间戳,自1970年以来的秒数
                    "nonceStr": "@Model.nonce_str", //随机串
                    "package": "prepay_id=@Model.prepay_id",
                    "signType": "MD5",         //微信签名方式:
                    "paySign": "@Model.sign" //微信签名
                },
                function (res) {
                    // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。
                    if (res.err_msg == "get_brand_wcpay_request:ok") {
                        alert("支付成功");
                        window.location.href = "/WeChatSite/Home/Index";
                    } else if (res.err_msg == "get_brand_wcpay_request:cancel") {
                        alert("支付过程中用户取消");
                    } else if (res.err_msg == "get_brand_wcpay_request:fail") {
                        alert("支付失败");
                    }

                }
            );
        }
        $(".immediate_payment").click(function () {
            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();
            }
        });
    </script>
View Code

  2)异步:获取微信回台一步返回的结果,(方法地址:请求统一下单API的notify_url字段)

    { 1.获取异步返回的文件流

     2.读取文件流并解析文件流,判断执行结果,如果成功则需要验证签名是否正确,

     3.签名验证成功执行数据操作,更改本地支付信息。

  /// <summary>
        /// 处理回调数据
        /// </summary>
        public ActionResult ProcessingCallback()
        {
            //1.获取微信支付回调信息
            string XmlData = getPostStr();
            //判断数据是否为空
            if (XmlData.IsNotNullOrEmpty())
            {
                DataSet ds = new DataSet();
                StringReader sr = new StringReader(XmlData);
                XmlTextReader dataReader = new XmlTextReader(sr);
                ds.ReadXml(dataReader);
                CreateLog.SaveLogs("--------------------XMLData&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" + XmlData + "&&&&&&&&&&&&&&&&&&&", 1);
                if (ds.Tables[0].Rows[0]["return_code"].ToString() == "SUCCESS")
                {
                    #region 解析ds获取对象
                    //将dataset转换为对象
                    WeChatPaymentReturn wcpr = new WeChatPaymentReturn()
                    {
                        appid = ds.Tables[0].Rows[0]["appid"].ToString(),
                        bank_type = ds.Tables[0].Rows[0]["bank_type"].ToString(),
                        cash_fee = ds.Tables[0].Rows[0]["cash_fee"].ToString(),
                        fee_type = ds.Tables[0].Rows[0]["fee_type"].ToString(),
                        is_subscribe = ds.Tables[0].Rows[0]["is_subscribe"].ToString(),
                        mch_id = ds.Tables[0].Rows[0]["mch_id"].ToString(),
                        nonce_str = ds.Tables[0].Rows[0]["nonce_str"].ToString(),
                        openid = ds.Tables[0].Rows[0]["openid"].ToString(),
                        out_trade_no = ds.Tables[0].Rows[0]["out_trade_no"].ToString(),
                        result_code = ds.Tables[0].Rows[0]["result_code"].ToString(),
                        return_code = ds.Tables[0].Rows[0]["return_code"].ToString(),
                        time_end = ds.Tables[0].Rows[0]["time_end"].ToString(),
                        total_fee = ds.Tables[0].Rows[0]["total_fee"].ToString(),
                        trade_type = ds.Tables[0].Rows[0]["trade_type"].ToString(),
                        transaction_id = ds.Tables[0].Rows[0]["transaction_id"].ToString(),
                        sign = ds.Tables[0].Rows[0]["sign"].ToString(),
                    };

                    #endregion
                    //4.支付成功之后验证Sign
                    var againSign = new Dictionary<string, object>();
                    againSign.Add("appid", wcpr.appid);
                    againSign.Add("bank_type", wcpr.bank_type);
                    againSign.Add("cash_fee", wcpr.cash_fee);
                    againSign.Add("fee_type", wcpr.fee_type);
                    againSign.Add("is_subscribe", wcpr.is_subscribe);
                    againSign.Add("mch_id", wcpr.mch_id);
                    againSign.Add("nonce_str", wcpr.nonce_str);
                    againSign.Add("openid", wcpr.openid);
                    againSign.Add("out_trade_no", wcpr.out_trade_no);
                    againSign.Add("result_code", wcpr.result_code);
                    againSign.Add("return_code", wcpr.return_code);
                    againSign.Add("time_end", wcpr.time_end);
                    againSign.Add("total_fee", wcpr.total_fee);
                    againSign.Add("trade_type", wcpr.trade_type);
                    againSign.Add("transaction_id", wcpr.transaction_id);
                    string againSignStr = WeChatPayHelper.GetSignString(againSign);
                    if (wcpr.sign.ToUpper() == againSignStr.ToUpper())
                    {
                        CreateLog.SaveLogs("####签名验证成功againSignStr######" + againSignStr + "-------sign-------------" + wcpr.sign, 1);

                        #region 处理数据逻辑
                        //更新订单信息
                        //添加支付信息
                        CreateLog.SaveLogs("开始付款", 1);
                        //签名正确   处理订单操作逻辑
                        var oderInfo = OrderInfoManager.Instance.GetByField("OrderCode", wcpr.out_trade_no).FirstOrDefault();
                        if (oderInfo.OrderState != (int)OrderState.代付款)
                        {
                            CreateLog.SaveLogs("支付成功!但是在此发出请求", 1);
                            return null;
                        }
                        if (oderInfo != null)
                        {
                            try
                            {
                                OrderInfoManager.Instance.UpdataStatus(oderInfo.Guid, (int) OrderState.已付款);
                                CreateLog.SaveLogs("状态修改结束", 1);
                                PaymentInfo info = new PaymentInfo()
                                {
                                    OrderGuid = oderInfo.Guid,
                                    PayState = 1,
                                    PayMethod = (int)PayMethod.微信支付,
                                    Guid = Guid.NewGuid(),
                                    Mark = (int)DataMark.正常,
                                    PayDateTime = DateTime.Now,
                                    PayMoney = Convert.ToDecimal(wcpr.total_fee) / 100,
                                    Qid = wcpr.transaction_id
                                };
                                PaymentInfoManager.Instance.Insert(info);
                                CreateLog.SaveLogs("支付信息添加成功", 1);
                            }
                            catch (Exception e)
                            {
                                CreateLog.SaveLogs("-----Exception" + e,1);
                                throw;
                            }

                        }
                        //CreateLog.SaveLogs("状态修改结束", 1);
                        #endregion
                    }
                    else
                    {
                        CreateLog.SaveLogs("####签名验证失败againSignStr######" + againSignStr + "-------sign-------------" + wcpr.sign, 1);
                    }

                }
                else
                {
                    // 返回信息,如非空,为错误原因  签名失败 参数格式校验错误
                    string return_msg = ds.Tables[0].Rows[0]["return_msg"].ToString();
                    CreateLog.SaveLogs("支付失败", 1);

                }
            }
            return View();
        }
        //getPostStr
        /// <summary>
        /// 获取微信支付毁掉的数据;
        /// </summary>
        /// <returns></returns>
        public string getPostStr()
        {
            Int32 intLen = Convert.ToInt32(Request.InputStream.Length);
            byte[] b = new byte[intLen];
            Request.InputStream.Read(b, 0, intLen);
            return System.Text.Encoding.UTF8.GetString(b);
        }
ProcessingCallback

    }

微信支付辅助方法

        /// <summary>
        /// 获取客户端ip
        /// </summary>
        /// <returns>返回客户端IP地址</returns>
        public static string GetWebClientIp()
        {
            HttpRequest request = HttpContext.Current.Request;
            string result = request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            string a = request.UserHostAddress;
            if (String.IsNullOrEmpty(result))
            {
                result = request.ServerVariables["REMOTE_ADDR"];
            }
            if (String.IsNullOrEmpty(result))
            {
                result = request.UserHostAddress;
            }
            if (String.IsNullOrEmpty(result))
            {
                result = "0.0.0.0";
            }
            return result;



            //string userIP = "IP";

            //try
            //{
            //    if (System.Web.HttpContext.Current == null
            //|| System.Web.HttpContext.Current.Request == null
            //|| System.Web.HttpContext.Current.Request.ServerVariables == null)
            //        return "";

            //    string CustomerIP = "";

            //    //CDN加速后取到的IP   
            //    CustomerIP = System.Web.HttpContext.Current.Request.Headers["Cdn-Src-Ip"];
            //    if (!string.IsNullOrEmpty(CustomerIP))
            //    {
            //        return CustomerIP;
            //    }

            //    CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];


            //    if (!String.IsNullOrEmpty(CustomerIP))
            //        return CustomerIP;

            //    if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
            //    {
            //        CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            //        if (CustomerIP == null)
            //            CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            //    }
            //    else
            //    {
            //        CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

            //    }

            //    if (string.Compare(CustomerIP, "unknown", true) == 0)
            //        return System.Web.HttpContext.Current.Request.UserHostAddress;
            //    return CustomerIP;
            //}
            //catch { }

            //return userIP;
            string user_IP;

            if (HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
            {

                user_IP = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();

            }

            else
            {

                user_IP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString();

            }
            return user_IP;
        }
        /// <summary>
        /// 获取Sign签名
        /// </summary>
        /// <param name="dic">键值对集合</param>
        /// <returns>字符串类型的签名</returns>
        public static string GetSignString(Dictionary<string, object> dic)
        {
            string key = WebConfigurationManager.AppSettings["wx_key"].ToString(); ;//商户平台 API安全里面设置的KEY  32位长度
            //排序
            dic = dic.OrderBy(d => d.Key).ToDictionary(d => d.Key, d => d.Value);
            //连接字段
            var sign = dic.Aggregate("", (current, d) => current + (d.Key + "=" + d.Value + "&"));
            sign += "key=" + key;
            //MD5
            sign = FormsAuthentication.HashPasswordForStoringInConfigFile(sign, "MD5").ToUpper();

            return sign;
        }
        /// <summary>
        /// 时间格式化
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static string Format(DateTime date)
        {
            var dates = "";
            dates += date.Year;
            dates += date.Month;
            dates += date.Date;
            dates += date.Hour;
            dates += date.Minute;
            dates += date.Second;
            return dates;

        }
        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
weChatHelper

微信支付实体类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Travel.WeChat.ViewModel.WeiPay
{
    public class unifiedorder
    {
        /// <summary>
        /// 公众账号ID
        /// </summary>
        public string appid { get; set; } 
        /// <summary>
        /// 商户号
        /// </summary>
        public string mch_id { get; set; }
        /// <summary>
        /// 设备号
        /// </summary>
        public string device_info { get; set; }
        /// <summary>
        /// 随机字符串
        /// </summary>
        public string nonce_str { get; set; }
        /// <summary>
        /// 签名
        /// </summary>
        public string sign { get; set; } 
        public string sign_type { get; set; }
        /// <summary>
        /// 商品描述
        /// </summary>
        public string body { get; set; }
        public string detail { get; set; }
        public string attach { get; set; }
        /// <summary>
        /// 商户订单号
        /// </summary>
        public string out_trade_no { get; set; }
        public string fee_type { get; set; }
        /// <summary>
        /// 总金额
        /// </summary>
        public int    total_fee { get; set; }
        /// <summary>
        /// 终端IP
        /// </summary>
        public string spbill_create_ip { get; set; }
        public string time_start { get; set; }
        public string time_expire { get; set; }
        public string goods_tag { get; set; }
        /// <summary>
        /// 通知地址
        /// </summary>
        public string notify_url { get; set; }
        /// <summary>
        /// 交易类型
        /// </summary>
        public string trade_type { get; set; }
        public string product_id { get; set; }
        public string limit_pay { get; set; }
        public string openid { get; set; }
        public List<h5_info> scene_info { get; set; }
    }
}
1.unifiedorder
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Travel.WeChat.ViewModel.WeiPay
{
    public class WeChatInfo
    {
        //统一下单接口返回值
        public string return_code { get; set; }
        public string return_msg { get; set; }
        public string appid { get; set; }
        public string mch_id { get; set; }
        public string nonce_str { get; set; }
        public string openid { get; set; }
        public string sign { get; set; }
        public string result_code { get; set; }
        public string prepay_id { get; set; }
        public string trade_type { get; set; }
        public string timeStamp { get; set; }
    }
}
2.WeChatInfo
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Travel.WeChat.ViewModel.WeiPay
{
    public class WeChatPaymentReturn
    {
//异步回调的返回信息
        public string appid { get; set; }
        public string bank_type { get; set; }
        public string cash_fee { get; set; }
        public string fee_type { get; set; }
        public string is_subscribe { get; set; }
        public string mch_id { get; set; }
        public string nonce_str { get; set; }
        public string openid{ get; set; }
        public string out_trade_no{ get; set; }
        public string result_code{ get; set; }
        public string return_code{ get; set; }
        public string sign{ get; set; }
        public string time_end{ get; set; }
        public string total_fee{ get; set; }
        public string trade_type{ get; set; }
        public string transaction_id{ get; set; }
    }
}
3.WeChatPaymentReturn
原文地址:https://www.cnblogs.com/JueXiaoQiang/p/7905402.html