zoukankan      html  css  js  c++  java
  • 微信小程序支付功能 C# .NET开发

    微信小程序支付功能的开发的时候坑比较多,不过对于钱的事谨慎也是好事。网上关于小程序支付的实例很多,但是大多多少有些问题,C#开发的更少。此篇文档的目的是讲开发过程中遇到的问题做一个备注,也方便其他开发的同学作为参考!

     

           1、首先建议把官方文档支付部分看上三遍,每个细节都不要放过,因为任何一个点和微信要求不符都会导致支付不成功。https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=3_1

          2、经过验证的微信支付功能,会需要一些商户号、支付秘钥等,不要搞混。

         3、经常遇到的是“签名错误”,请仔细看需要传送的xml参数及取值规则是否符合微信规则。微信有个验证工具可以验证发送的xml字段是否合法。

     

    下面上代码:

     

    web.config

     

        <add key="ConnectionString" value="server=127.0.0.1;database=;uid=sa;pwd="/>
        <add key="ConnectionString2" value="server=127.0.0.1;database=codematic2;uid=sa;pwd=1"/>
        <add key="appid" value=""/>//appid
        <add key="secret" value=""/>//小程序秘钥
        <add key="mch_id" value=""/>//商户号
        <add key="key" value=""/>//支付秘钥
        <add key="ip" value=""/>//服务器IP
        <add key="PayResulturl" value=""/>//微信返回接收信息的url地址
      </appSettings>

    支付后台xiadan.ashx

     

     

    <%@ WebHandler Language="C#" Class="xiadan" %>
    
    using System;
    using System.Web;
    using System.Net;
    using System.IO;
    using System.Configuration;
    using Maticsoft.Model;
    using Maticsoft.BLL;
    using System.Security.Cryptography;
    using System.Text;
    using System.Xml.Serialization;
    using System.Xml;
    using System.Collections.Generic;
    using System.Data;
    using System.Net.Security;
    using System.Security.Cryptography.X509Certificates;
    using System.Linq;
    using Newtonsoft.Json;
    
    public class xiadan : IHttpHandler
    {
    
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            string openid = context.Request.Params["openid"];
            string ordertime = context.Request.Params["ordertime"];
    
            string appid = ConfigurationManager.AppSettings["appid"];
            string secret = ConfigurationManager.AppSettings["secret"];
            string key = ConfigurationManager.AppSettings["key"];
            string mch_id = ConfigurationManager.AppSettings["mch_id"];
            string ip = ConfigurationManager.AppSettings["ip"];
            string PayResulturl = ConfigurationManager.AppSettings["PayResulturl"];
            string roomid = context.Request.Params["roomid"];
            string aa = "-押金";////商品描述交易字段格式根据不同的应用场景按照以下格式:APP——需传入应用市场上的APP名字-实际商品名称,天天爱消除-游戏充值。
    
            string strcode = aa;
            byte[] buffer = Encoding.UTF8.GetBytes(strcode);
            string body = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
            string totalfee = context.Request.Params["totalfee"];
            string output = "";
            if ((context.Request.Params["openid"] != null) && (context.Request.Params["openid"] != ""))
            {
                //OrderInfo order = new OrderInfo();
    
                //order.appid = appid;
    
                System.Random Random = new System.Random();
    
    
    
                var dic = new Dictionary<string, string>
    {
        {"appid", appid},
        {"mch_id", mch_id},
        {"nonce_str", GetRandomString(20)/*Random.Next().ToString()*/},
        {"body",body},
        {"out_trade_no",roomid + DateTime.Now.ToString("yyyyMMddHHmmssfff") + Random.Next(999).ToString()},//商户自己的订单号码
        {"total_fee",totalfee},
        {"spbill_create_ip",ip},//服务器的IP地址
        {"notify_url",PayResulturl},//异步通知的地址,不能带参数
        {"trade_type","JSAPI" },
        {"openid",openid}
    };
          //加入签名
                dic.Add("sign", GetSignString(dic));
    
                var sb = new StringBuilder();
                sb.Append("<xml>");
    
    
                foreach (var d in dic)
                {
                    sb.Append("<" + d.Key + ">" + d.Value + "</" + d.Key + ">");
                }
                sb.Append("</xml>");
                var xml = new XmlDocument();
                //  xml.LoadXml(GetPostString("https://api.mch.weixin.qq.com/pay/unifiedorder", sb.ToString()));
                CookieCollection coo = new CookieCollection();
                Encoding en = Encoding.GetEncoding("UTF-8");
    
                HttpWebResponse response = CreatePostHttpResponse("https://api.mch.weixin.qq.com/pay/unifiedorder", sb.ToString(), en);
                //打印返回值
                Stream stream = response.GetResponseStream();   //获取响应的字符串流
                StreamReader sr = new StreamReader(stream); //创建一个stream读取流
                string html = sr.ReadToEnd();   //从头读到尾,放到字符串html
                                                //Console.WriteLine(html);
                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();
                if (return_code.ToUpper() == "SUCCESS")
                {
                    //通信成功
                    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);
                        if ((context.Request.Params["openid"] != null) && (context.Request.Params["openid"] != ""))
                        { 
                        //存储订单信息
                        Maticsoft.Model.order_history oh = new Maticsoft.Model.order_history();
                        //oh.shop_id =
                        oh.room_id = Convert.ToInt32(roomid);
                        oh.pay_price = Convert.ToDecimal(totalfee);
                        oh.out_trade_no = dic["out_trade_no"];
                        oh.order_timestart = Convert.ToDateTime(ordertime);
                        oh.openid = openid;
                        oh.creating_date = DateTime.Now;
    
                        Maticsoft.BLL.order_history bll = new Maticsoft.BLL.order_history();
                        bll.Add(oh);
    
                    }
                    context.Response.Write(signapp);
                }
            }
    
    
    
    
        }
        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;
    }
    
    
    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();
    }
    
    }




     

          微信返回信息接收后台页面notify_url.ashx

     

    <%@ WebHandler Language="C#" Class="notify_url" %>
    
    using System;
    using System.Web;
    using System.Collections.Generic;
    using System.Data;
    using System.IO;
    using System.Text;
    using System.Xml;
    using System.Net;
    public class notify_url : IHttpHandler
    {
        public string return_result = "";
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            context.Response.Write("Hello World");
    
    
            String xmlData = getPostStr();//获取请求数据
            if (xmlData == "")
            {
    
            }
            else
            {
                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;
                        }
                    }
    
                    #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())
                    {
                        //签名正确   处理订单操作逻辑
    
    
                    }
                    else
                    {
                        //追加备注信息
    
                    }
    
                }
                else
                {
                    // 返回信息,如非空,为错误原因  签名失败 参数格式校验错误
                    string return_msg = ds.Tables[0].Rows[0]["return_msg"].ToString();
    
                }
    
    
                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);
        }
    }
  • 相关阅读:
    jquery在表格中的全选、不选,下面全选,全选勾选中,下面一项没有选,全选勾未选中,并且带出请求值。
    比较好的插件
    js预加载loading的canvas写法
    div居中方法
    WEB14-未完
    WEB13
    WEB12
    WEB11-黑客入侵 后门问题
    WEB-10 头等舱
    WEB9-神奇的超全局变量-文件包含
  • 原文地址:https://www.cnblogs.com/ws-yizhiduxiu/p/11320994.html
Copyright © 2011-2022 走看看