微信小程序支付功能的开发的时候坑比较多,不过对于钱的事谨慎也是好事。网上关于小程序支付的实例很多,但是大多多少有些问题,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>
- <%@ 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);
- }
- }
退款:
- <%@ WebHandler Language="C#" Class="jiesuan" %>
- 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 jiesuan : IHttpHandler
- {
- public void ProcessRequest(HttpContext context)
- {
- context.Response.ContentType = "text/plain";
- // string openid = context.Request.Params["openid"];
- // string ordertime = context.Request.Params["ordertime"];
- string orderid = context.Request.Params["order_id"];
- 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);
- DateTime timestart;
- int totalhour;
- float totalfee;
- float pay_price;
- float refund_fee;
- string out_refund_no;
- int roomid;
- string openid;
- //string totalfee = context.Request.Params["totalfee"];
- string output = "";
- string signapp;
- DataSet orderhistory;
- if ((context.Request.Params["order_id"] != null) && (context.Request.Params["order_id"] != ""))
- {
- Maticsoft.BLL.order_history oh = new Maticsoft.BLL.order_history();
- orderhistory = oh.GetList(" order_id=" + orderid + "");
- pay_price = Convert.ToSingle(orderhistory.Tables[0].Rows[0]["pay_price"]);
- roomid = Convert.ToInt32(orderhistory.Tables[0].Rows[0]["room_id"]);
- openid = orderhistory.Tables[0].Rows[0]["openid"].ToString();
- System.Random Random = new System.Random();
- timestart = Convert.ToDateTime(orderhistory.Tables[0].Rows[0]["order_timestart"]);//订单开始时间
- TimeSpan ts = DateTime.Now - timestart; //时间差的绝对值
- totalhour = Convert.ToInt32(ts.Hours);//间隔小时数
- totalfee = totalhour * Convert.ToSingle(orderhistory.Tables[0].Rows[0]["price"]);
- out_refund_no = roomid + DateTime.Now.ToString("yyyyMMddHHmmssfff") + Random.Next(999).ToString();
- refund_fee = totalfee - pay_price;
- var dic = new Dictionary<string, string>
- {
- {"appid", appid},
- {"mch_id", mch_id},
- {"nonce_str", GetRandomString(20)/*Random.Next().ToString()*/},
- {"op_user_id",mch_id},
- {"out_refund_no",out_refund_no},//商户退款号
- {"out_trade_no",orderhistory.Tables[0].Rows[0]["out_trade_no"].ToString()},//商户自己的订单号码
- {"refund_fee",/*refund_fee.ToString()*/"1"},//退款金额
- {"total_fee",orderhistory.Tables[0].Rows[0]["pay_price"].ToString()},//订单金额
- };
- //加入签名
- 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/secapi/pay/refund", 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();
- string return_mesage = ds.Tables[0].Rows[0]["return_msg"].ToString();
- if (return_code.ToUpper() == "SUCCESS")
- {
- //通信成功
- string result_code = ds.Tables[0].Rows[0]["result_code"].ToString();//业务结果
- if (result_code.ToUpper() == "SUCCESS")
- {
- if ((context.Request.Params["order_id"] != null) && (context.Request.Params["order_id"] != ""))
- {
- //更新订单信息
- Maticsoft.Model.pokerrooms model = new Maticsoft.Model.pokerrooms();
- Maticsoft.Model.order_history oh1 = new Maticsoft.Model.order_history();
- Maticsoft.BLL.pokerrooms b = new Maticsoft.BLL.pokerrooms();
- Maticsoft.BLL.order_history bll = new Maticsoft.BLL.order_history();
- model = b.GetModel(roomid);
- oh1 = bll.GetModel(Convert.ToInt32(orderid));
- oh1.order_timeend = DateTime.Now;
- oh1.out_refund_no = out_refund_no;
- oh1.refund_fee = Convert.ToDecimal(refund_fee);
- bll.Update(oh1);
- model.attribute1 = "0";//0空闲 1 使用中
- model.room_id =Convert.ToInt32(oh1.room_id);
- b.Update(model);//更新棋牌室使用状态
- var res = new Dictionary<string, string>
- {
- {"out_refund_no", out_refund_no},
- {"return_mesage", return_mesage},
- {"return_code", return_code},
- {"refund_fee",refund_fee.ToString() },
- {"order_timeend", oh1.order_timeend.ToString() },
- {"order_id", oh1.order_id.ToString() }
- };
- signapp = JsonConvert.SerializeObject(res);
- 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)
- {
- // string cert = @"C:\apiclient_cert.p12";
- string cert =System.Web.HttpContext.Current.Server.MapPath("/apiclient_cert.p12"); //证书已上传到网站根目录,注意安全性问题
- string password = ConfigurationManager.AppSettings["mch_id"];
- // X509Certificate cer = new X509Certificate(cert, password);//经过测试,这个发布到IIS后,发起微信退款时会引起<span style="color:rgb(255,0,0);font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;font-size:13px;">"基础连接已经关闭: 连接被意外关闭"</span>
- X509Certificate2 cer = new X509Certificate2(cert, password, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);
- HttpWebRequest request = null;
- //HTTPSQ请求
- ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
- request = WebRequest.Create(url) as HttpWebRequest;
- request.ProtocolVersion = HttpVersion.Version10;
- request.ClientCertificates.Add(cer);//add by sui 20170505
- 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();
- }
- }