asp.net 5.0微信支付
(原文出自:http://lib.csdn.net/article/wechat/46329)
微信支付官方坑太多,我们来精简
我把官方的代码,打包成了 an.wxapi.dll。
里面主要替换了下注释。呵呵。然后修改了几个地方。
namespace an.wxapi { public class WxPayConfig { public static string AppKey(string key) { return System.Configuration.ConfigurationManager.AppSettings[key]; } /// <summary> /// APPID:绑定支付的APPID(必须配置) /// </summary> public static string APPID { get { return AppKey("wx_appid"); } } /// <summary> /// KEY:商户支付密钥,参考开户邮件设置(必须配置) /// </summary> public static string KEY { get { return AppKey("wx_key"); } } /// <summary> /// 商户号(必须配置) /// </summary> public static string MCHID { get { return AppKey("wx_mchid"); } } /// <summary> /// APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置) /// </summary> public static string APPSECRET { get { return AppKey("wx_appsecret"); } } /// <summary> /// 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要) /// </summary> public static string SSLCERT_PATH { get { return AppKey("wx_sslcert_path"); } } /// <summary> /// 证书密码,默认商户号为密码 /// </summary> public static string SSLCERT_PASSWORD { get { return AppKey("wx_sslcert_password"); } } /// <summary> /// 支付结果通知回调url,用于商户接收支付结果 /// </summary> public static string NOTIFY_URL { get { return AppKey("wx_notify_url"); } } /// <summary> /// 商户系统后台机器IP,此参数可手动配置也可在程序中自动获取 /// </summary> public static string IP = "8.8.8.8"; /// <summary> /// 代理服务器设置,默认IP和端口号分别为0.0.0.0和0,此时不开启代理(如有需要才设置) /// </summary> public static string PROXY_URL = "http://10.152.18.220:8080"; /// <summary> ///上报信息配置,测速上报等级,0.关闭上报; 1.仅错误时上报; 2.全量上报 /// </summary> public static int REPORT_LEVENL = 1; /// <summary> /// 日志等级,0.不输出日志;1.只输出错误信息; 2.输出错误和正常信息; 3.输出错误信息、正常信息和调试信息 /// </summary> public static int LOG_LEVENL { get { string log_levenl = "0"; if(AppKey("log_leven")!="") { log_levenl = AppKey("log_leven"); } return Convert.ToInt32(log_levenl); } } } }
只是把静态的替换成可以从web.config里面调用的。
namespace an.wxapi { /// <summary> /// http连接基础类,负责底层的http通信 /// </summary> public class HttpService { public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { //直接确认,否则打不开 return true; } public static string Post(string xml, string url, bool isUseCert, int timeout) { System.GC.Collect();//垃圾回收,回收没有正常关闭的http连接 string result = "";//返回结果 HttpWebRequest request = null; HttpWebResponse response = null; Stream reqStream = null; try { //设置最大连接数 ServicePointManager.DefaultConnectionLimit = 200; //设置https验证方式 if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); } /*************************************************************** * 下面设置HttpWebRequest的相关属性 * ************************************************************/ request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.Timeout = timeout * 1000; //设置代理服务器 //WebProxy proxy = new WebProxy(); //定义一个网关对象 //proxy.Address = new Uri(WxPayConfig.PROXY_URL); //网关服务器端口:端口 //request.Proxy = proxy; //设置POST的数据类型和长度 request.ContentType = "text/xml"; byte[] data = System.Text.Encoding.UTF8.GetBytes(xml); request.ContentLength = data.Length; //是否使用证书 if (isUseCert) { string path = HttpContext.Current.Request.PhysicalApplicationPath; X509Certificate2 cert = new X509Certificate2(path + WxPayConfig.SSLCERT_PATH, WxPayConfig.SSLCERT_PASSWORD); request.ClientCertificates.Add(cert); Log.Debug("WxPayApi", "PostXml used cert"); } //往服务器写入数据 reqStream = request.GetRequestStream(); reqStream.Write(data, 0, data.Length); reqStream.Close(); //获取服务端返回 response = (HttpWebResponse)request.GetResponse(); //获取服务端返回数据 StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8); result = sr.ReadToEnd().Trim(); sr.Close(); } catch (System.Threading.ThreadAbortException e) { Log.Error("HttpService", "Thread - caught ThreadAbortException - resetting."); Log.Error("Exception message: {0}", e.Message); System.Threading.Thread.ResetAbort(); } catch (WebException e) { Log.Error("HttpService", e.ToString()); if (e.Status == WebExceptionStatus.ProtocolError) { Log.Error("HttpService", "StatusCode : " + ((HttpWebResponse)e.Response).StatusCode); Log.Error("HttpService", "StatusDescription : " + ((HttpWebResponse)e.Response).StatusDescription); } throw new WxPayException(e.ToString()); } catch (Exception e) { Log.Error("HttpService", e.ToString()); throw new WxPayException(e.ToString()); } finally { //关闭连接和流 if (response != null) { response.Close(); } if (request != null) { request.Abort(); } } return result; } /// <summary> /// 处理http GET请求,返回数据 /// </summary> /// <param name="url">请求的url地址</param> /// <returns>http GET成功后返回的数据,失败抛WebException异常</returns> public static string Get(string url) { System.GC.Collect(); string result = ""; HttpWebRequest request = null; HttpWebResponse response = null; //请求url以获取数据 try { //设置最大连接数 ServicePointManager.DefaultConnectionLimit = 200; //设置https验证方式 if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); } /*************************************************************** * 下面设置HttpWebRequest的相关属性 * ************************************************************/ request = (HttpWebRequest)WebRequest.Create(url); request.Method = "GET"; //设置代理 //WebProxy proxy = new WebProxy(); //proxy.Address = new Uri(WxPayConfig.PROXY_URL); //request.Proxy = proxy; //获取服务器返回 response = (HttpWebResponse)request.GetResponse(); //获取HTTP返回数据 StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8); result = sr.ReadToEnd().Trim(); sr.Close(); } catch (System.Threading.ThreadAbortException e) { Log.Error("HttpService", "Thread - caught ThreadAbortException - resetting."); Log.Error("Exception message: {0}", e.Message); System.Threading.Thread.ResetAbort(); } catch (WebException e) { Log.Error("HttpService", e.ToString()); if (e.Status == WebExceptionStatus.ProtocolError) { Log.Error("HttpService", "StatusCode : " + ((HttpWebResponse)e.Response).StatusCode); Log.Error("HttpService", "StatusDescription : " + ((HttpWebResponse)e.Response).StatusDescription); } throw new WxPayException(e.ToString()); } catch (Exception e) { Log.Error("HttpService", e.ToString()); throw new WxPayException(e.ToString()); } finally { //关闭连接和流 if (response != null) { response.Close(); } if (request != null) { request.Abort(); } } return result; } } }
主要注释掉了设置代理服务器,基本上就注释掉这个就可以用了。
因为我只需要做微信里面的网页支付,其他很多功能我都不需要。所以。BIN文件夹,也只需要LitJSON.dll,RestSharp.dll,an.wxapi.dll(我上面打包的)
<%@ Page Language="C#" Inherits="an.web" %> <%@ Import Namespace="an.wxapi" %> <script runat="server"> protected override void OnLoad(EventArgs e) { JsApiPay jsApiPay = new JsApiPay(this); jsApiPay.GetOpenidAndAccessToken(); wx_openid = jsApiPay.openid; } </script> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> </head> <body> <h2>商品一:价格为:1分</h2> <p><a href="JsApiPayPage.aspx?openid=<%=wx_openid %>&total_fee=1&showwxpaytitle=1">去支付</a></p> </body> </html>
我比较懒,所以,我一般不用.cs文件,我喜欢写到一起。呵呵,(这样有个好处,不需要编译,即可运行。) 基本上是拿官方的过来,没怎么修改。
protected void Page_Load(object sender, EventArgs e) { Log.Info(this.GetType().ToString(), "page load"); if (!IsPostBack) { JsApiPay jsApiPay = new JsApiPay(this); try { //调用【网页授权获取用户信息】接口获取用户的openid和access_token jsApiPay.GetOpenidAndAccessToken(); //获取收货地址js函数入口参数 //wxEditAddrParam = jsApiPay.GetEditAddressParameters(); ViewState["openid"] = jsApiPay.openid; } catch (Exception ex) { Response.Write("<span style='color:#FF0000;font-size:20px'>" + "页面加载出错,请重试" +ex.Message +"</span>"); //Button1.Visible = false; //Button2.Visible = false; //Label1.Visible = false; //Label2.Visible = false; } } }
官方用的是ViewState这玩意,会产生庞大的垃圾代码,(反正我也不知道这玩意,有啥子用) 我的做法是:
namespace an { public class web : System.Web.UI.Page { public string wx_openid { get; set; } public string wxJsApiParam { get; set; } } }
直接在an.web里面定义下属性,不完啦。
<%@ Page Language="C#" Inherits="an.web" %> <%@ Import Namespace="an.wxapi" %> <script runat="server"> protected override void OnLoad(EventArgs e) { string openid = Request.QueryString["openid"]; string total_fee = Request.QueryString["total_fee"]; JsApiPay jsApiPay = new JsApiPay(this); jsApiPay.openid = openid; jsApiPay.total_fee = int.Parse(total_fee); WxPayData unifiedOrderResult = jsApiPay.GetUnifiedOrderResult(); wxJsApiParam = jsApiPay.GetJsApiParameters();//获取H5调起JS API参数 } </script> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>微信支付样例-JSAPI支付</title> </head> <script type="text/javascript"> //调用微信JS api 支付 function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', <%=wxJsApiParam%>,//josn串 function (res) { WeixinJSBridge.log(res.err_msg); alert(res.err_code + res.err_desc + res.err_msg); } ); } function callpay() { if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } } else { jsApiCall(); } } </script> <body> <input type="button" onclick="callpay()" value="立刻支付" /> </body> </html>
<%@ Page Language="C#" Inherits="an.web" %> <%@ Import Namespace="an.wxapi" %> <script runat="server"> protected override void OnLoad(EventArgs e) { ResultNotify resultNotify = new ResultNotify(this); resultNotify.ProcessNotify(); } </script> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> </head> <body> </body> </html>