.Net 小程序实现微信支付后台代码

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_39585172/article/details/81095883

首先我们先了解微信支付的几种方式:https://pay.weixin.qq.com/wiki/doc/api/index.html

然后打开相应开发文档查看请求参数:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

 

注:此文章用的是 公众号支付

 

 

 

    /// <summary>

    /// PostPay 的摘要说明

    /// </summary>

    public class PostPay1 : IHttpHandler

    {

        Log log = new Log();//记录日志

        public void ProcessRequest(HttpContext context)

        {

            context.Response.ContentType = "text/plain";

            string openid = context.Request.Params["openid"];//小程序传参

            string totalfee =context.Request.Params["totalfee"];//订单金额

            string body = context.Request.Params["body"];   //小程序传参

            string transaction_id = context.Request.Params["pay_id"];//微信订单ID

            string appid = ConfigurationManager.AppSettings["appid"];

            string secret = ConfigurationManager.AppSettings["secret"];//小程序秘钥

            log.write("openid:" + openid);

            string key = ConfigurationManager.AppSettings["key"];//支付秘钥

            string mch_id = ConfigurationManager.AppSettings["mch_id"];//商户号

            string ip = ConfigurationManager.AppSettings["ip"];//服务器IP

            string PayResulturl = ConfigurationManager.AppSettings["PayResulturl"];//微信返回接收信息的url地址

            string output = "";

            if ((openid != null) && (openid != ""))

            {

                double dubamount;

                double.TryParse(totalfee, out dubamount);

                string nonce_str = GetRandomString(20);

                //新增订单信息  

                Random Random = new Random();

                var dic = new Dictionary<string, string>

                {

                    {"appid", appid},

                    {"mch_id", mch_id},

                    {"nonce_str",nonce_str /*Random.Next().ToString()*/},

                    {"body",body},

                    {"out_trade_no","M"+DateTime.Now.ToString("yyyyMMddHHmmssfff") + Random.Next(999).ToString()},//订单号码  

                    {"total_fee",(dubamount).ToString()},//订单金额

                    {"spbill_create_ip",ip},//服务器的IP地址  

                    {"notify_url",PayResulturl},//异步通知的地址,不能带参数  

                    {"trade_type","JSAPI" },

                    {"openid",openid},

                    {"fee_type", "CNY"}

                };

                //加入签名  

                string sign = GetSignString(dic);

                dic.Add("sign", sign);

                log.write("sign");

                var sb = new StringBuilder();

                sb.Append("<xml>");

                foreach (var d in dic)

                {

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

                }

                sb.Append("</xml>");

                CookieCollection coo = new CookieCollection();

                Encoding en = Encoding.GetEncoding("UTF-8");

                HttpWebResponse response = CreatePostHttpResponse("https://api.mch.weixin.qq.com/pay/unifiedorder", sb.ToString(), en);

                var xml = new XmlDocument();

                //打印返回值  

                Stream stream = response.GetResponseStream();   //获取响应的字符串流  

                StreamReader sr = new StreamReader(stream); //创建一个stream读取流  

                string html = sr.ReadToEnd();   //从头读到尾,放到字符串html  

                log.write("html:" + html);

                //Json转换字符串

                xml.LoadXml(html);

                //对请求返回值 进行处理  

                var root = xml.DocumentElement;

                DataSet ds = new DataSet();

                StringReader stram = new StringReader(html);

                XmlTextReader reader = new XmlTextReader(stram);

                ds.ReadXml(reader);

                string return_code = ds.Tables[0].Rows[0]["return_code"].ToString();

                string return_msg = ds.Tables[0].Rows[0]["return_msg"].ToString();

                if (return_code.ToUpper() == "SUCCESS")

                {

                    log.write("result_code:" + ds.Tables[0].Rows[0]["result_code"].ToString());

                    //通信成功  

                    string result_code = ds.Tables[0].Rows[0]["result_code"].ToString();//业务结果  

                    if (result_code.ToUpper() == "SUCCESS")

                    {

                        var res = new Dictionary<string, string>

                        {

                            {"appId", appid},

                            {"timeStamp", GetTimeStamp()},

                            {"nonceStr", dic["nonce_str"]},

                            {"package",  "prepay_id="+ds.Tables[0].Rows[0]["prepay_id"].ToString()},

                            {"signType", "MD5"}

                        };

                        //在服务器上签名  

                        res.Add("paySign", GetSignString(res));

                        // string signapp = res.ToString();  

                        string signapp = JsonConvert.SerializeObject(res);

                        log.write("signapp:" + signapp);

                      

                        context.Response.Write(signapp);

                    }

                }

                else

                {

                    log.write(this.GetType().ToString()+"UnifiedOrder respone error");

                    throw new Exception("UnifiedOrder respone error");

                }

            }

            log.write("output:" + output);

            context.Response.Write(output);

        }

        public bool IsReusable

        {

            get

            {

                return false;

            }

        }

        public string GetMd5Hash(String input)

        {

            if (input == null)

            {

                return null;

            }

            MD5 md5Hash = MD5.Create();

            // 将输入字符串转换为字节数组并计算哈希数据    

            byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

            // 创建一个 Stringbuilder 来收集字节并创建字符串    

            StringBuilder sBuilder = new StringBuilder();

            // 循环遍历哈希数据的每一个字节并格式化为十六进制字符串    

            for (int i = 0; i < data.Length; i++)

            {

                sBuilder.Append(data[i].ToString());

            }

            // 返回十六进制字符串    

            return sBuilder.ToString();

        }

        /// <summary>    

        /// 对象序列化成 XML String    

        /// </summary>    

        public static string XmlSerialize<T>(T obj)

        {

            string xmlString = string.Empty;

            XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

            using (MemoryStream ms = new MemoryStream())

            {

                xmlSerializer.Serialize(ms, obj);

                xmlString = Encoding.UTF8.GetString(ms.ToArray());

            }

            return xmlString;

        }

        /// <summary>  

        /// 从字符串里随机得到,规定个数的字符串.  

        /// </summary>  

        /// <param name="allChar"></param>  

        /// <param name="CodeCount"></param>  

        /// <returns></returns>  

        public static string GetRandomString(int CodeCount)

        {

            string allChar = "1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,i,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z";

            string[] allCharArray = allChar.Split(',');

            string RandomCode = "";

            int temp = -1;

            Random rand = new Random();

            for (int i = 0; i < CodeCount; i++)

            {

                if (temp != -1)

                {

                    rand = new Random(temp * i * ((int)DateTime.Now.Ticks));

                }

                int t = rand.Next(allCharArray.Length - 1);

                while (temp == t)

                {

                    t = rand.Next(allCharArray.Length - 1);

                }

                temp = t;

                RandomCode += allCharArray[t];

            }

            return RandomCode;

        }

 

        public static string GetWebClientIp()

        {

            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;

        }

 

        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)

        {

            return true;    

        }

        public static HttpWebResponse CreatePostHttpResponse(string url, string datas, Encoding charset)

        {

            HttpWebRequest request = null;

            //HTTPSQ请求  

            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);

            request = WebRequest.Create(url) as HttpWebRequest;

            request.ProtocolVersion = HttpVersion.Version10;

            request.Method = "POST";

            request.ContentType = "application/x-www-form-urlencoded";

            //如果需要POST数据     

            //if (!(parameters == null || parameters.Count == 0))  

            //{  

            StringBuilder buffer = new StringBuilder();

            //int i = 0;  

            //foreach (string key in parameters.Keys)  

            //{  

            //    if (i > 0)  

            //    {  

            //        buffer.AppendFormat("&{0}={1}", key, parameters[key]);  

            //    }  

            //    else  

            //    {  

            //        buffer.AppendFormat("{0}={1}", key, parameters[key]);  

            //    }  

            //    i++;  

            //}  

            buffer.AppendFormat(datas);

            byte[] data = charset.GetBytes(buffer.ToString());

            using (Stream stream = request.GetRequestStream())

            {

                stream.Write(data, 0, data.Length);

            }

            //}  

            return request.GetResponse() as HttpWebResponse;

        }

        /// <summary>    

        /// 获取签名字符串    

        /// </summary>    

        /// <returns></returns>    

        public string GetSignString(Dictionary<string, string> dic)

        {

            string key = System.Web.Configuration.WebConfigurationManager.AppSettings["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 = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(sign, "MD5").ToUpper();  

            System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();

            sign = BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(sign))).Replace("-", null);

            return sign;

        }

 

        /// <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();

        }

    }

 

 

 

 /// <summary>
    /// notify_url 的摘要说明
    /// </summary>
    public class notify_url : IHttpHandler
    {
        public string return_result = "";
        Log log = new Log();
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            log.write("notify_url");


            String xmlData = getPostStr();//获取请求数据  
            if (xmlData == "")
            {
            }
            else
            {

                log.write("xmlData:" + xmlData);
                var dic = new Dictionary<string, string>
                {
                    {"return_code", "SUCCESS"},
                    {"return_msg","OK"}
                };
                var sb = new StringBuilder();
                sb.Append("<xml>");


                foreach (var d in dic)
                {
                    sb.Append("<" + d.Key + ">" + d.Value + "</" + d.Key + ">");
                }
                sb.Append("</xml>");
                

                //把数据重新返回给客户端  
                DataSet ds = new DataSet();
                StringReader stram = new StringReader(xmlData);
                XmlTextReader datareader = new XmlTextReader(stram);
                ds.ReadXml(datareader);
                if (ds.Tables[0].Rows[0]["return_code"].ToString() == "SUCCESS")
                {
                    string wx_appid = "";//微信开放平台审核通过的应用APPID  
                    string wx_mch_id ="";//微信支付分配的商户号  

                    string wx_nonce_str = "";//     随机字符串,不长于32位  
                    string wx_sign = "";//签名,详见签名算法  
                    string wx_result_code = "";//SUCCESS/FAIL  

                    string wx_return_code = "";
                    string wx_openid = "";//用户在商户appid下的唯一标识  
                    string wx_is_subscribe = "";//用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效  
                    string wx_trade_type = "";//    APP  
                    string wx_bank_type = "";//     银行类型,采用字符串类型的银行标识,银行类型见银行列表  
                    string wx_fee_type = "";//  货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型  


                    string wx_transaction_id = "";//微信支付订单号  
                    string wx_out_trade_no = "";//商户系统的订单号,与请求一致。  
                    string wx_time_end = "";//  支付完成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则  
                    int wx_total_fee = -1;//    订单总金额,单位为分  
                    int wx_cash_fee = -1;//现金支付金额订单现金支付金额,详见支付金额  


                    #region  数据解析  
                    //列 是否存在  
                    string signstr = "";//需要前面的字符串  
                                        //wx_appid  
                    if (ds.Tables[0].Columns.Contains("appid"))
                    {
                        wx_appid = ds.Tables[0].Rows[0]["appid"].ToString();
                        if (!string.IsNullOrEmpty(wx_appid))
                        {
                            signstr += "appid=" + wx_appid;
                        }
                    }

                    //wx_bank_type  
                    if (ds.Tables[0].Columns.Contains("bank_type"))
                    {
                        wx_bank_type = ds.Tables[0].Rows[0]["bank_type"].ToString();
                        if (!string.IsNullOrEmpty(wx_bank_type))
                        {
                            signstr += "&bank_type=" + wx_bank_type;
                        }
                    }
                    //wx_cash_fee  
                    if (ds.Tables[0].Columns.Contains("cash_fee"))
                    {
                        wx_cash_fee = Convert.ToInt32(ds.Tables[0].Rows[0]["cash_fee"].ToString());

                        signstr += "&cash_fee=" + wx_cash_fee;
                    }

                    //wx_fee_type  
                    if (ds.Tables[0].Columns.Contains("fee_type"))
                    {
                        wx_fee_type = ds.Tables[0].Rows[0]["fee_type"].ToString();
                        if (!string.IsNullOrEmpty(wx_fee_type))
                        {
                            signstr += "&fee_type=" + wx_fee_type;
                        }
                    }

                    //wx_is_subscribe  
                    if (ds.Tables[0].Columns.Contains("is_subscribe"))
                    {
                        wx_is_subscribe = ds.Tables[0].Rows[0]["is_subscribe"].ToString();
                        if (!string.IsNullOrEmpty(wx_is_subscribe))
                        {
                            signstr += "&is_subscribe=" + wx_is_subscribe;
                        }
                    }

                    //wx_mch_id  
                    if (ds.Tables[0].Columns.Contains("mch_id"))
                    {
                        wx_mch_id = ds.Tables[0].Rows[0]["mch_id"].ToString();
                        if (!string.IsNullOrEmpty(wx_mch_id))
                        {
                            signstr += "&mch_id=" + wx_mch_id;
                        }
                    }

                    //wx_nonce_str  
                    if (ds.Tables[0].Columns.Contains("nonce_str"))
                    {
                        wx_nonce_str = ds.Tables[0].Rows[0]["nonce_str"].ToString();
                        if (!string.IsNullOrEmpty(wx_nonce_str))
                        {
                            signstr += "&nonce_str=" + wx_nonce_str;
                        }
                    }

                    //wx_openid  
                    if (ds.Tables[0].Columns.Contains("openid"))
                    {
                        wx_openid = ds.Tables[0].Rows[0]["openid"].ToString();
                        if (!string.IsNullOrEmpty(wx_openid))
                        {
                            signstr += "&openid=" + wx_openid;
                        }
                    }

                    //wx_out_trade_no  
                    if (ds.Tables[0].Columns.Contains("out_trade_no"))
                    {
                        wx_out_trade_no = ds.Tables[0].Rows[0]["out_trade_no"].ToString();
                        if (!string.IsNullOrEmpty(wx_out_trade_no))
                        {
                            signstr += "&out_trade_no=" + wx_out_trade_no;
                        }
                    }

                    //wx_result_code   
                    if (ds.Tables[0].Columns.Contains("result_code"))
                    {
                        wx_result_code = ds.Tables[0].Rows[0]["result_code"].ToString();
                        if (!string.IsNullOrEmpty(wx_result_code))
                        {
                            signstr += "&result_code=" + wx_result_code;
                        }
                    }

                    //wx_result_code   
                    if (ds.Tables[0].Columns.Contains("return_code"))
                    {
                        wx_return_code = ds.Tables[0].Rows[0]["return_code"].ToString();
                        if (!string.IsNullOrEmpty(wx_return_code))
                        {
                            signstr += "&return_code=" + wx_return_code;
                        }
                    }

                    //wx_sign   
                    if (ds.Tables[0].Columns.Contains("sign"))
                    {
                        wx_sign = ds.Tables[0].Rows[0]["sign"].ToString();
                        //if (!string.IsNullOrEmpty(wx_sign))  
                        //{  
                        //    signstr += "&sign=" + wx_sign;  
                        //}  
                    }

                    //wx_time_end  
                    if (ds.Tables[0].Columns.Contains("time_end"))
                    {
                        wx_time_end = ds.Tables[0].Rows[0]["time_end"].ToString();
                        if (!string.IsNullOrEmpty(wx_time_end))
                        {
                            signstr += "&time_end=" + wx_time_end;
                        }
                    }

                    //wx_total_fee  
                    if (ds.Tables[0].Columns.Contains("total_fee"))
                    {
                        wx_total_fee = Convert.ToInt32(ds.Tables[0].Rows[0]["total_fee"].ToString());

                        signstr += "&total_fee=" + wx_total_fee;
                    }

                    //wx_trade_type  
                    if (ds.Tables[0].Columns.Contains("trade_type"))
                    {
                        wx_trade_type = ds.Tables[0].Rows[0]["trade_type"].ToString();
                        if (!string.IsNullOrEmpty(wx_trade_type))
                        {
                            signstr += "&trade_type=" + wx_trade_type;
                        }
                    }

                    //wx_transaction_id  
                    if (ds.Tables[0].Columns.Contains("transaction_id"))
                    {
                        wx_transaction_id = ds.Tables[0].Rows[0]["transaction_id"].ToString();
                        if (!string.IsNullOrEmpty(wx_transaction_id))
                        {
                            signstr += "&transaction_id=" + wx_transaction_id;
                        }
                    }
                    log.write(signstr);
                    #endregion

                    //追加key 密钥  
                    signstr += "&key=" + System.Web.Configuration.WebConfigurationManager.AppSettings["key"].ToString();
                    //签名正确  
                    string orderStrwhere = "ordernumber='" + wx_out_trade_no + "'";

                    if (wx_sign == System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(signstr, "MD5").ToUpper())
                    {
                        //签名正确   处理订单操作逻辑 
                        using (TransactionScope sc = new TransactionScope())
                        {
                           //逻辑操作
                            }
                            catch (Exception ex)
                            {
                                log.write("retrun_msg:" + ex.Message);
                                context.Response.Write("error:"+ex.Message);
                            }
                        }
                    }
                    else
                    {
                        //追加备注信息  
                        log.write("签名错误 :" + ds.Tables[0].Rows[0]["return_msg"].ToString());
                        context.Response.Write("error:"+ ds.Tables[0].Rows[0]["return_msg"].ToString());
                    }

                }
                else
                {
                    // 返回信息,如非空,为错误原因  签名失败 参数格式校验错误  
                    string return_msg = ds.Tables[0].Rows[0]["return_msg"].ToString();
                    context.Response.Write("error:" + return_msg);

                }


                return_result = sb.ToString();
            }

        }


        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        //获得Post过来的数据  
        public string getPostStr()
        {
            Int32 intLen = Convert.ToInt32(System.Web.HttpContext.Current.Request.InputStream.Length);
            byte[] b = new byte[intLen];
            System.Web.HttpContext.Current.Request.InputStream.Read(b, 0, intLen);
            return System.Text.Encoding.UTF8.GetString(b);
        }
        
    }

展开阅读全文

没有更多推荐了,返回首页