做微信支付的时候遇到了挺多坑,现在记录下来和大家分享分享。
第一个坑:算签名的时候,总是提示签名失败。用微信提供的计算签名的工具,计算出来的签名是一致的。
原因是:密钥拿错了,我用的是公众平台的app密钥。实际应该拿的是微信支付商户平台设置的API密钥。
第二个坑:使用JSAPI调用支付组件的时候,总是提示AppId无效。
原因:公众平台设置的测试路径和实际测试的路径有一个字母大小写不一样。如:b:B。微信文档里说,大小写必须一致。
关于微信支付的源码以后有时间的时候在贴上。
代码文件:
首先是几个必要文件:
HttpUtil.cs--------用来发送HTTP请求
WeChatConfig.cs---------配置类
ResponseHandler.cs-----接收微信同步回调信息的类
RequestHandler.cs------向微信发送请求时会使用的类
WeChatPayment.cs-----封装好的几个方法,方便在平台的其他地方调用
WeChatParameter.cs----调用接口时使用的一些传递参数的类型
WeChatViewParameter.cs--------这个类型主要传递参数给JSAPI使用
ImageResult.cs -----------------返回给浏览器时使用的Result类型
其他----------------------还有一些辅助函数,分散在项目的其他文件中(如果有园友看到,且需要就密我吧!)
HttpUtil.cs
1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Linq; 5 using System.Net; 6 using System.Text; 7 using System.Web; 8 9 namespace Mimo.Payment.WeChatPay 10 { 11 public class HttpUtil 12 { 13 14 private const string sContentType = "application/x-www-form-urlencoded"; 15 private const string sUserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"; 16 public static string Send(string data, string url) 17 { 18 return Send(Encoding.GetEncoding("UTF-8").GetBytes(data), url); 19 } 20 21 public static string Send(byte[] data, string url) 22 { 23 Stream responseStream; 24 HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; 25 if (request == null) 26 { 27 throw new ApplicationException(string.Format("Invalid url string: {0}", url)); 28 } 29 30 request.ContentType = sContentType; 31 request.UserAgent = sUserAgent; 32 request.Method = "POST"; 33 request.ContentLength = data.Length; 34 Stream requestStream = request.GetRequestStream(); 35 requestStream.Write(data, 0, data.Length); 36 requestStream.Close(); 37 try 38 { 39 responseStream = request.GetResponse().GetResponseStream(); 40 } 41 catch (Exception exception) 42 { 43 throw exception; 44 } 45 string str = string.Empty; 46 using (StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("UTF-8"))) 47 { 48 str = reader.ReadToEnd(); 49 } 50 responseStream.Close(); 51 return str; 52 } 53 } 54 }
WeChatConfig.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Mimo.Payment 8 { 9 /// <summary> 10 /// liuyt 2015.03.16 11 /// 微信支付的配置文件 12 /// </summary> 13 public class WeChatConfig 14 { 15 #region UnifiedOrderUrl 统一下单接口URL 16 private static string unifiedOrderUrl; 17 public static string UnifiedOrderUrl 18 { 19 get { return unifiedOrderUrl; } 20 } 21 #endregion 22 23 #region ApiSecret 微信支付商户平台设置的API密钥 24 private static string apiSecret; 25 public static string ApiSecret 26 { 27 get { return apiSecret; } 28 } 29 #endregion 30 31 #region AppId 应用ID 微信公众平台-->开发者中心-->配置项-->AppID 32 private static string appId; 33 public static string AppId 34 { 35 get { return appId; } 36 } 37 #endregion 38 39 #region Mch_id 商户ID 微信支付的商户号--在微信返回的审核通过的邮件中 40 private static string mch_id; 41 public static string Mch_id 42 { 43 get { return mch_id; } 44 } 45 #endregion 46 47 #region 构造函数 48 static WeChatConfig() 49 { 50 unifiedOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; 51 apiSecret = "填上自己的密钥"; 52 appId = "填上自己的appId"; 53 mch_id = "填上自己的mch_id"; 54 } 55 #endregion 56 } 57 }
RequestHandler.cs
1 using System; 2 using System.Collections; 3 using System.Text; 4 using System.Web; 5 using System.Xml; 6 using System.Security.Cryptography; 7 using System.Collections.Generic; 8 using System.Text.RegularExpressions; 9 using Mimo.Payment.Common; 10 namespace Mimo.Payment.WeChatPay 11 { 12 /** 13 '签名工具类 14 ============================================================================/// <summary> 15 'api说明: 16 'init(); 17 '初始化函数,默认给一些参数赋值。 18 'setKey(key_)'设置商户密钥 19 'createMd5Sign(signParams);字典生成Md5签名 20 'genPackage(packageParams);获取package包 21 'createSHA1Sign(signParams);创建签名SHA1 22 'parseXML();输出xml 23 'getDebugInfo(),获取debug信息 24 * 25 * ============================================================================ 26 */ 27 public class RequestHandler 28 { 29 30 public RequestHandler(HttpContext httpContext) 31 { 32 parameters = new Hashtable(); 33 34 this.httpContext = httpContext; 35 36 } 37 /** 密钥 */ 38 private string key; 39 40 protected HttpContext httpContext; 41 42 /** 请求的参数 */ 43 protected Hashtable parameters; 44 45 /** debug信息 */ 46 private string debugInfo; 47 48 /** 初始化函数 */ 49 public virtual void init() 50 { 51 } 52 /** 获取debug信息 */ 53 public String getDebugInfo() 54 { 55 return debugInfo; 56 } 57 /** 获取密钥 */ 58 public String getKey() 59 { 60 return key; 61 } 62 63 /** 设置密钥 */ 64 public void setKey(string key) 65 { 66 this.key = key; 67 // this.partne = key; 68 } 69 70 /** 设置参数值 */ 71 public void setParameter(string parameter, string parameterValue) 72 { 73 if (parameter != null && parameter != "") 74 { 75 if (parameters.Contains(parameter)) 76 { 77 parameters.Remove(parameter); 78 } 79 80 parameters.Add(parameter, parameterValue); 81 } 82 } 83 84 85 //创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 86 87 protected virtual void createSign() 88 { 89 StringBuilder sb = new StringBuilder(); 90 91 ArrayList akeys=new ArrayList(parameters.Keys); 92 akeys.Sort(); 93 94 foreach(string k in akeys) 95 { 96 string v = (string)parameters[k]; 97 if(null != v && "".CompareTo(v) != 0 98 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) 99 { 100 sb.Append(k + "=" + v + "&"); 101 } 102 } 103 104 sb.Append("key=" + this.getKey()); 105 string sign = AlipayMD5.GetMD5(sb.ToString(), getCharset()).ToUpper(); 106 107 this.setParameter("sign", sign); 108 109 //debug信息 110 this.setDebugInfo(sb.ToString() + " => sign:" + sign); 111 } 112 113 114 //创建package签名 115 public virtual string createMd5Sign() 116 { 117 StringBuilder sb = new StringBuilder(); 118 ArrayList akeys=new ArrayList(parameters.Keys); 119 akeys.Sort(); 120 121 foreach(string k in akeys) 122 { 123 string v = (string)parameters[k]; 124 if(null != v && "".CompareTo(v) != 0 125 && "sign".CompareTo(k) != 0 && "".CompareTo(v) != 0) 126 { 127 sb.Append(k + "=" + v + "&"); 128 } 129 } 130 string sign = AlipayMD5.GetMD5(sb.ToString(), getCharset()).ToLower(); 131 132 this.setParameter("sign", sign); 133 return sign; 134 } 135 136 /// <summary> 137 /// 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名(微信V3 package签名(MD5签名)) 138 /// </summary> 139 /// <param name="key">参数名</param> 140 /// <param name="value">参数值</param> 141 /// key和value通常用于填充最后一组参数 142 /// <returns></returns> 143 public virtual string createMd5Sign(string key, string value) 144 { 145 StringBuilder sb = new StringBuilder(); 146 147 ArrayList akeys = new ArrayList(parameters.Keys); 148 akeys.Sort(); 149 150 foreach (string k in akeys) 151 { 152 string v = (string)parameters[k]; 153 if (null != v && "".CompareTo(v) != 0 154 && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0) 155 { 156 sb.Append(k + "=" + v + "&"); 157 } 158 } 159 160 sb.Append(key + "=" + value); 161 162 string sign = AlipayMD5.GetMD5(sb.ToString(), getCharset()).ToUpper(); 163 164 return sign; 165 } 166 167 168 169 //输出XML 170 public string parseXML() 171 { 172 StringBuilder sb = new StringBuilder(); 173 sb.Append("<xml>"); 174 foreach (string k in parameters.Keys) 175 { 176 string v = (string)parameters[k]; 177 if (Regex.IsMatch(v, @"^[0-9.]$")) 178 { 179 180 sb.Append("<" + k + ">" + v + "</" + k + ">"); 181 } 182 else 183 { 184 sb.Append("<" + k + "><![CDATA[" + v + "]]></" + k + ">"); 185 } 186 187 } 188 sb.Append("</xml>"); 189 return sb.ToString(); 190 } 191 192 193 194 /** 设置debug信息 */ 195 public void setDebugInfo(String debugInfo) 196 { 197 this.debugInfo = debugInfo; 198 } 199 200 public Hashtable getAllParameters() 201 { 202 return this.parameters; 203 } 204 205 protected virtual string getCharset() 206 { 207 208 return this.httpContext.Request.ContentEncoding.BodyName; 209 } 210 } 211 }
ResponseHandler.cs
1 using Mimo.BLL; 2 using Mimo.Model; 3 using Mimo.Payment.Common; 4 using Mimo.Payment.Common.PayPalJSON; 5 using System; 6 using System.Collections; 7 using System.Collections.Specialized; 8 using System.Text; 9 using System.Web; 10 using System.Xml; 11 12 namespace Mimo.Payment.WeChatPay 13 { 14 15 /** 16 '============================================================================ 17 'api说明: 18 'getKey()/setKey(),获取/设置密钥 19 'getParameter()/setParameter(),获取/设置参数值 20 'getAllParameters(),获取所有参数 21 'isTenpaySign(),是否正确的签名,true:是 false:否 22 'isWXsign(),是否正确的签名,true:是 false:否 23 ' * isWXsignfeedback判断微信维权签名 24 ' *getDebugInfo(),获取debug信息 25 '============================================================================ 26 */ 27 28 public class ResponseHandler 29 { 30 // 密钥 31 private string key = WeChatConfig.ApiSecret; 32 33 34 //xmlMap 35 private Hashtable xmlMap; 36 37 // 应答的参数 38 protected Hashtable parameters; 39 40 //debug信息 41 private string debugInfo; 42 43 /// <summary> 44 /// 保存微信支付回调时 xml 45 /// </summary> 46 private string xmlInfo; 47 //原始内容 48 protected string content; 49 50 private string charset = "utf-8"; 51 52 53 protected HttpContext httpContext; 54 55 //初始化函数 56 public virtual void init() 57 { 58 } 59 60 61 //获取页面提交的get和post参数 62 public ResponseHandler(HttpContext httpContext) 63 { 64 parameters = new Hashtable(); 65 xmlMap = new Hashtable(); 66 67 this.httpContext = httpContext; 68 NameValueCollection collection; 69 //post data 70 if (this.httpContext.Request.HttpMethod == "POST") 71 { 72 collection = this.httpContext.Request.Form; 73 foreach (string k in collection) 74 { 75 string v = (string)collection[k]; 76 this.setParameter(k, v); 77 } 78 } 79 //query string 80 collection = this.httpContext.Request.QueryString; 81 foreach (string k in collection) 82 { 83 string v = (string)collection[k]; 84 this.setParameter(k, v); 85 } 86 if (this.httpContext.Request.InputStream.Length > 0) 87 { 88 XmlDocument xmlDoc = new XmlDocument(); 89 xmlDoc.Load(this.httpContext.Request.InputStream); 90 XmlNode root = xmlDoc.SelectSingleNode("xml"); 91 XmlNodeList xnl = root.ChildNodes; 92 foreach (XmlNode xnf in xnl) 93 { 94 xmlMap.Add(xnf.Name, xnf.InnerText); 95 } 96 try 97 { 98 xmlInfo = JSON.Serialize(xmlDoc); 99 } 100 catch 101 { 102 } 103 } 104 } 105 106 107 /** 获取密钥 */ 108 public string getKey() 109 { 110 return key; 111 } 112 113 /** 设置密钥 */ 114 public void setKey(string key) 115 { 116 this.key = key; 117 } 118 119 /** 获取参数值 */ 120 public string getParameter(string parameter) 121 { 122 string s = (string)parameters[parameter]; 123 return (null == s) ? "" : s; 124 } 125 126 /** 获取参数值 */ 127 public string getMpParameter(string parameter) 128 { 129 string s = (string)xmlMap[parameter]; 130 return (null == s) ? "" : s; 131 } 132 133 /** 设置参数值 */ 134 public void setParameter(string parameter, string parameterValue) 135 { 136 if (parameter != null && parameter != "") 137 { 138 if (parameters.Contains(parameter)) 139 { 140 parameters.Remove(parameter); 141 } 142 143 parameters.Add(parameter, parameterValue); 144 } 145 } 146 147 //判断签名 微信安全支付V3 148 public virtual Boolean isWXsign_MD5() 149 { 150 StringBuilder sb = new StringBuilder(); 151 Hashtable signMap = new Hashtable(); 152 foreach (string k in xmlMap.Keys) 153 { 154 if (k != "sign") 155 { 156 signMap.Add(k.ToLower(), xmlMap[k]); 157 } 158 } 159 160 ArrayList akeys = new ArrayList(signMap.Keys); 161 akeys.Sort(); 162 163 foreach (string k in akeys) 164 { 165 string v = (string)signMap[k]; 166 sb.Append(k + "=" + v + "&"); 167 } 168 sb.Append("key=" + this.key); 169 170 string sign = AlipayMD5.GetMD5(sb.ToString(), charset).ToString().ToUpper(); 171 this.setDebugInfo(sb.ToString() + " => sign:" + sign); 172 return sign.Equals(xmlMap["sign"]); 173 174 } 175 176 /** 获取debug信息 */ 177 public string getDebugInfo() 178 { 179 return debugInfo; 180 } 181 /** 获取debug信息 */ 182 public string getXmlInfo() 183 { 184 return xmlInfo; 185 } 186 /** 设置debug信息 */ 187 protected void setDebugInfo(String debugInfo) 188 { 189 this.debugInfo = debugInfo; 190 } 191 192 } 193 }
WeChatPayment.cs
1 using Mimo.Payment.Common; 2 using Mimo.Payment.WeChatPay; 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Text; 7 using System.Threading.Tasks; 8 using System.Xml.Linq; 9 10 namespace Mimo.Payment.Payment 11 { 12 /// <summary> 13 /// liuyt 2015.03.16 add 14 /// 微信支付的公用方法 15 /// </summary> 16 public class WeChatPayment 17 { 18 /// <summary> 19 /// liuyt 2015.03.16 add 20 /// 调用统一下单接口获取预交易订单号或者Code_URL,参数值 取决于trade_type的参数值 21 /// </summary> 22 /// <param name="model"></param> 23 /// <returns></returns> 24 #region 调用统一下单接口获取预交易订单号 25 public static string GetprepayId(WeChatParameter model) 26 { 27 //创建支付应答对象 28 RequestHandler packageReqHandler = new RequestHandler(System.Web.HttpContext.Current); 29 //初始化 30 packageReqHandler.init(); 31 //设置package订单参数 32 packageReqHandler.setParameter("appid", WeChatConfig.AppId); //公众账号ID 33 packageReqHandler.setParameter("mch_id", WeChatConfig.Mch_id); //商户号 34 packageReqHandler.setParameter("nonce_str", PaymentCommon.GetNoncestr()); //随机字符串 35 packageReqHandler.setParameter("body", "test"); //商品描述 128字节以下 36 packageReqHandler.setParameter("out_trade_no", model.out_trade_no.Trim()); //商家订单号 37 packageReqHandler.setParameter("total_fee", (model.total_fee * 100).ToString("F0")); //商品金额,以分为单位(money * 100).ToString() 38 packageReqHandler.setParameter("spbill_create_ip", model.spbill_create_ip); //用户的公网ip,不是商户服务器IP 39 packageReqHandler.setParameter("notify_url", model.notify_url); //接收财付通通知的URL 40 packageReqHandler.setParameter("trade_type", model.trade_type); //交易类型 41 if (model.trade_type.ToLower() == "jsapi") 42 { 43 packageReqHandler.setParameter("openid", model.openid); 44 } //用户的openId 45 string sign = packageReqHandler.createMd5Sign("key", WeChatConfig.ApiSecret);//key 密钥 46 packageReqHandler.setParameter("sign", sign); //签名 47 string data = packageReqHandler.parseXML(); 48 string result = HttpUtil.Send(data, WeChatConfig.UnifiedOrderUrl); 49 var res = XDocument.Parse(result); 50 string rs = string.Empty; 51 if (model.trade_type.ToLower() == "jsapi") 52 { 53 rs = res.Element("xml").Element("prepay_id").Value; //微信V3预支付交易订单号 54 } 55 else if (model.trade_type.ToLower() == "native") 56 { 57 rs = res.Element("xml").Element("code_url").Value; //微信V3预支付交易订单号 58 } 59 return rs; 60 } 61 #endregion 62 63 /// <summary> 64 /// liuyt 2015.03.16 add 65 /// 获取支付密钥 66 /// </summary> 67 /// <param name="prepayId"></param> 68 /// <returns></returns> 69 #region 获取支付密钥 70 public static string GetPaySign(WeChatViewParameter model) 71 { 72 RequestHandler paySignReqHandler = new RequestHandler(System.Web.HttpContext.Current); 73 paySignReqHandler.setParameter("appId", model.AppId); 74 paySignReqHandler.setParameter("timeStamp", model.TimeStamp); 75 paySignReqHandler.setParameter("nonceStr", model.NonceStr); 76 paySignReqHandler.setParameter("package", string.Format("prepay_id={0}", model.Prepay_id)); 77 paySignReqHandler.setParameter("signType", "MD5"); 78 string paySign = paySignReqHandler.createMd5Sign("key", WeChatConfig.ApiSecret);//key 密钥 79 return paySign; 80 } 81 #endregion 82 83 /// <summary> 84 /// liuyt 2015.03.16 add 85 /// 获取扫码支付的二维码图 86 /// </summary> 87 /// <param name="model"></param> 88 /// <returns></returns> 89 #region 获取扫码支付的二维码图 90 public static ImageResult GetNativeImageResult(WeChatParameter model) 91 { 92 string code_url = GetprepayId(model); 93 return PaymentCommon.GetQRCodeImageResult(code_url); 94 } 95 #endregion 96 97 /// <summary> 98 /// liuyt 2015.03.16 add 99 /// 获取微信支付的异步通知的参数 100 /// </summary> 101 /// <returns></returns> 102 #region 获取微信支付的异步通知的参数 103 public static WeChatResultParameter GetNotifyResult() 104 { 105 WeChatResultParameter model = new WeChatResultParameter(); 106 107 ResponseHandler resHandler = new ResponseHandler(System.Web.HttpContext.Current); 108 string debugInfo = resHandler.getDebugInfo(); 109 #region 协议参数===================================== 110 //--------------协议参数-------------------------------------------------------- 111 //SUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查 112 string return_code = resHandler.getMpParameter("return_code"); 113 model.result_code = return_code; 114 //返回信息,如非空,为错误原因签名失败参数格式校验错误 115 string return_msg = resHandler.getMpParameter("return_msg"); 116 model.return_msg = return_msg; 117 //微信分配的公众账号 ID 118 string appid = resHandler.getMpParameter("appid"); 119 model.appid = appid; 120 //以下字段在 return_code 为 SUCCESS 的时候有返回-------------------------------- 121 //微信支付分配的商户号 122 string mch_id = resHandler.getMpParameter("mch_id"); 123 model.mch_id = mch_id; 124 //微信支付分配的终端设备号 125 string device_info = resHandler.getMpParameter("device_info"); 126 model.device_info = device_info; 127 //微信分配的公众账号 ID 128 string nonce_str = resHandler.getMpParameter("nonce_str"); 129 model.nonce_str = nonce_str; 130 //业务结果 SUCCESS/FAIL 131 string result_code = resHandler.getMpParameter("result_code"); 132 model.return_code = result_code; 133 //错误代码 134 string err_code = resHandler.getMpParameter("err_code"); 135 model.err_code = err_code; 136 //结果信息描述 137 string err_code_des = resHandler.getMpParameter("err_code_des"); 138 model.err_code_des = err_code_des; 139 //以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回--------------- 140 //-------------业务参数--------------------------------------------------------- 141 //用户在商户 appid 下的唯一标识 142 string openid = resHandler.getMpParameter("openid"); 143 model.openid = openid; 144 //用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效 145 string is_subscribe = resHandler.getMpParameter("is_subscribe"); 146 model.is_subscribe = is_subscribe; 147 //JSAPI、NATIVE、MICROPAY、APP 148 string trade_type = resHandler.getMpParameter("trade_type"); 149 model.trade_type = trade_type; 150 //银行类型,采用字符串类型的银行标识 151 string bank_type = resHandler.getMpParameter("bank_type"); 152 model.bank_type = bank_type; 153 //订单总金额,单位为分 154 string total_fee = resHandler.getMpParameter("total_fee"); 155 model.total_fee = total_fee; 156 //货币类型,符合 ISO 4217 标准的三位字母代码,默认人民币:CNY 157 string fee_type = resHandler.getMpParameter("fee_type"); 158 model.fee_type = fee_type; 159 //微信支付订单号 160 string transaction_id = resHandler.getMpParameter("transaction_id"); 161 model.transaction_id = transaction_id; 162 //商户系统的订单号,与请求一致。 163 string out_trade_no = resHandler.getMpParameter("out_trade_no"); 164 model.out_trade_no = out_trade_no; 165 //商家数据包,原样返回 166 string attach = resHandler.getMpParameter("attach"); 167 model.attach = attach; 168 //支 付 完 成 时 间 , 格 式 为yyyyMMddhhmmss,如 2009 年12 月27日 9点 10分 10 秒表示为 20091227091010。时区为 GMT+8 beijing。该时间取自微信支付服务器 169 string time_end = resHandler.getMpParameter("time_end"); 170 model.time_end = time_end; 171 #endregion 172 if (resHandler.isWXsign_MD5()) 173 { 174 model.isWXsign_MD5 = true; 175 if (!out_trade_no.Equals("") && return_code.Equals("SUCCESS") && result_code.Equals("SUCCESS")) 176 { 177 model.RsIsSuccess = true; 178 } 179 else 180 { 181 model.RsIsSuccess = false; 182 } 183 } 184 else 185 { 186 model.isWXsign_MD5 = false; 187 model.RsIsSuccess = false; 188 } 189 model.debugInfo = resHandler.getDebugInfo(); 190 model.xmlInfo = resHandler.getXmlInfo(); 191 return model; 192 } 193 #endregion 194 195 /// <summary> 196 /// liuyt 2015.03.16 add 197 /// 设置XML格式的响应数据 198 /// </summary> 199 /// <param name="return_code"></param> 200 /// <param name="return_msg"></param> 201 #region 设置XML格式的响应数据 202 public static void ResponseXML(string return_code, string return_msg) 203 { 204 RequestHandler returnReqHandler = new RequestHandler(System.Web.HttpContext.Current); 205 returnReqHandler.setParameter("return_code", return_code); 206 returnReqHandler.setParameter("return_msg", return_msg); 207 string xmlStr = returnReqHandler.parseXML(); 208 System.Web.HttpContext.Current.Response.ContentType = "text/xml"; 209 System.Web.HttpContext.Current.Response.Clear(); 210 System.Web.HttpContext.Current.Response.Write(xmlStr); 211 System.Web.HttpContext.Current.Response.End(); 212 } 213 #endregion 214 215 } 216 }
WeChatParameter.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Mimo.Payment.Common 8 { 9 /// <summary> 10 /// liuyt 2015.03.16 add 11 /// 微信支付参数类 12 /// </summary> 13 public class WeChatParameter 14 { 15 #region 1.0 属性 16 /// <summary> 17 /// 商品描述 18 /// </summary> 19 public string body { get; set; } 20 21 /// <summary> 22 /// 商户订单号 必须唯一不弄重复 23 /// </summary> 24 public string out_trade_no { get; set; } 25 26 /// <summary> 27 /// 商品总价 单位:元 28 /// </summary> 29 public double total_fee { get; set; } 30 31 /// <summary> 32 /// JSAPI 用户IP,Native 商户服务器IP 注意两者的区别 33 /// </summary> 34 public string spbill_create_ip { get; set; } 35 36 /// <summary> 37 /// 微信支付异步通知的URL 38 /// </summary> 39 public string notify_url { get; set; } 40 41 /// <summary> 42 /// 交易类型 43 /// </summary> 44 public string trade_type { get; set; } 45 46 /// <summary> 47 /// 用户的openid 48 /// </summary> 49 public string openid { get; set; } 50 #endregion 51 52 #region 2.0 构造函数 53 public WeChatParameter() 54 { 55 56 } 57 58 public WeChatParameter(string body, string out_trade_no, double total_fee, string spbill_create_ip, string notify_url, string trade_type, string openid) 59 { 60 61 this.body = body; 62 this.out_trade_no = out_trade_no; 63 this.total_fee = total_fee; 64 this.spbill_create_ip = spbill_create_ip; 65 this.notify_url = notify_url; 66 this.trade_type = trade_type; 67 this.openid = openid; 68 } 69 public WeChatParameter(string body, string out_trade_no, double total_fee, string spbill_create_ip, string notify_url, string trade_type) 70 { 71 this.body = body; 72 this.out_trade_no = out_trade_no; 73 this.total_fee = total_fee; 74 this.spbill_create_ip = spbill_create_ip; 75 this.notify_url = notify_url; 76 this.trade_type = trade_type; 77 } 78 #endregion 79 } 80 }
WeChatViewParameter.cs
1 using Mimo.Payment.Payment; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace Mimo.Payment.Common 9 { 10 /// <summary> 11 /// 给JSAPI使用的参数类 12 /// </summary> 13 public class WeChatViewParameter 14 { 15 16 /// <summary> 17 /// 公众号ID 18 /// </summary> 19 public string AppId 20 { 21 get { return WeChatConfig.AppId; } 22 } 23 24 private string timeStamp = PaymentCommon.GetTimestamp(); 25 26 /// <summary> 27 /// 时间戳 28 /// </summary> 29 public string TimeStamp 30 { 31 get { return timeStamp; } 32 } 33 //WeChatParameter wcp = new WeChatParameter("此订单为用户在 上的商品", out_trade_no, 1, spbill_create_ip, notify_url, trade_type, openid); 34 // string prepayId = WeChatPayment.GetprepayId(wcp); 35 36 /// <summary> 37 /// 随机字符串 38 /// </summary> 39 private string nonceStr = PaymentCommon.GetNoncestr(); 40 public string NonceStr 41 { 42 get { return nonceStr; } 43 } 44 45 /// <summary> 46 /// 获取预交易订单号 47 /// </summary> 48 private string prepay_id; 49 public string Prepay_id 50 { 51 get { return prepay_id; } 52 } 53 54 /// <summary> 55 /// 微信支付签名 56 /// </summary> 57 private string paySign; 58 public string PaySign 59 { 60 get { return paySign; } 61 set { paySign = value; } 62 } 63 public void SetPaySign(string prepay_id) 64 { 65 this.prepay_id = prepay_id; 66 paySign = WeChatPayment.GetPaySign(this); 67 } 68 public void SetPaySign(WeChatParameter model) 69 { 70 string prepayId = WeChatPayment.GetprepayId(model); 71 this.prepay_id = prepayId; 72 paySign = WeChatPayment.GetPaySign(this); 73 } 74 } 75 }
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
一下是一些调用示例:
1 using Mimo.BLL; 2 using Mimo.BLL.Common; 3 using Mimo.Components.Helper; 4 using Mimo.Components.Web; 5 using Mimo.Model; 6 using Mimo.Payment; 7 using Mimo.Payment.Common; 8 using Mimo.Payment.Payment; 9 using System; 10 using System.Linq; 11 using System.Web.Mvc; 12 using System.Xml; 13 14 namespace Mimo.Web.controllers 15 { 16 public class BizWechatController : Controller 17 { /// <summary> 18 /// 测试链接 JSAPI 19 /// </summary> 20 /// <returns></returns> 21 public ActionResult Index() 22 { 23 Random d = new Random(); 24 string out_trade_no = Convert.ToString(d.Next(10000, 100000)); 25 string spbill_create_ip = "119.129.208.90"; //PaymentCommon.ClientIP; 26 string notify_url = "http://*******"; 27 string trade_type = "JSAPI"; 28 string openid = "*******"; 29 30 WeChatParameter wcp = new WeChatParameter("此订单为用户在*****上的商品", out_trade_no, 0.01, spbill_create_ip, notify_url, trade_type, openid); 31 WeChatViewParameter wcPara = new WeChatViewParameter(); 32 wcPara.SetPaySign(wcp); 33 34 ViewBag.WcPara = wcPara; 35 return View(wcPara); 36 } 37 38 /// <summary> 39 /// 测试链接 扫码支付 40 /// </summary> 41 /// <returns></returns> 42 public ActionResult Native() 43 { 44 Random d = new Random(); 45 string out_trade_no = Convert.ToString(d.Next(10000, 100000)); 46 string spbill_create_ip = PaymentCommon.GetServerIP();//服务器Ip 47 string notify_url = "http://********"; 48 string trade_type = "NATIVE"; 49 50 WeChatParameter wcp = new WeChatParameter("此订单为用户在**** 上的商品", out_trade_no, 0.01, spbill_create_ip, notify_url, trade_type); 51 52 ImageResult imgResult = WeChatPayment.GetNativeImageResult(wcp); 53 return imgResult; 54 } 55 } 56 }
Index.cshtml (调用JSAPI的示例)
1 @{ 2 ViewBag.Title = "GGG"; 3 } 4 5 <!DOCTYPE html> 6 7 <html> 8 <head> 9 <meta name="viewport" content="width=device-width" /> 10 <title>Index</title> 11 <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> 12 <script type="text/javascript"> 13 @{ Mimo.Payment.Common.WeChatViewParameter wcPara =@ViewBag.WcPara;} 14 //调用微信JS api 支付 15 function jsApiCall() { 16 var divObj = document.getElementById("msg"); 17 WeixinJSBridge.invoke( 18 19 'getBrandWCPayRequest', { 20 "appId": "@wcPara.AppId", //公众号名称,由商户传入 21 "timeStamp": "@wcPara.TimeStamp", //时间戳,自1970年以来的秒数 22 "nonceStr": "@wcPara.NonceStr", //随机串 23 "package": "prepay_id=@wcPara.Prepay_id", 24 "signType": "MD5", //微信签名方式: 25 "paySign": "@wcPara.PaySign" //微信签名 26 27 }, 28 function (res) { 29 WeixinJSBridge.log(res.err_msg); 30 divObj.innerHTML = JSON.stringify(res); 31 var divObjRs = document.getElementById("rsmsg"); 32 if (res.err_msg == "get_brand_wcpay_request:ok") { 33 34 divObjRs.innerHTML = JSON.stringify(res); 35 } else { 36 divObjRs.innerHTML = "失败了!"; 37 } 38 } 39 ); 40 } 41 function callpay() { 42 if (typeof WeixinJSBridge == "undefined") { 43 if (document.addEventListener) { 44 document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); 45 } else if (document.attachEvent) { 46 document.attachEvent('WeixinJSBridgeReady', jsApiCall); 47 document.attachEvent('onWeixinJSBridgeReady', jsApiCall); 48 } 49 } else { 50 jsApiCall(); 51 } 52 } 53 </script> 54 55 </head> 56 <body> 57 58 <div id="msgasda">@{Mimo.Payment.Common.PayPalJSON.JSON.Serialize(wcPara);}</div> 59 <div id="msg"></div> 60 <div id="rsmsg"></div> 61 </br></br></br></br> 62 <div align="center"> 63 <button style="210px; height:30px; background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer; color:white; font-size:16px;" type="button" onclick="callpay()">我任性</button> 64 </div> 65 </body> 66 </html>
调用扫码支付的示例:
调用扫码支付时,只需要把生成的响应对象放到浏览器就行了,其中生成二维码的组件使用的是ThoughtWorks.QRCode.dll
1 /// <summary> 2 /// 测试链接 扫码支付 3 /// </summary> 4 /// <returns></returns> 5 public ActionResult Native() 6 { 7 Random d = new Random(); 8 string out_trade_no = Convert.ToString(d.Next(10000, 100000)); 9 string spbill_create_ip = PaymentCommon.GetServerIP();//服务器Ip 10 string notify_url = "http://****************"; 11 string trade_type = "NATIVE"; 12 13 WeChatParameter wcp = new WeChatParameter("此订单为用户在******* 上的商品", out_trade_no, 0.01, spbill_create_ip, notify_url, trade_type); 14 15 ImageResult imgResult = WeChatPayment.GetNativeImageResult(wcp); 16 return imgResult; 17 } 18 /// <summary> 19 /// liuyt 2015.01.12 add 20 /// 根据一定数据生成 二维码,返回视图响应数据 21 /// </summary> 22 /// <param name="data"></param> 23 /// <returns></returns> 24 #region 根据一定数据生成 二维码,返回视图响应数据+static ImageResult GetQRCodeImage(string data) 25 public static ImageResult GetQRCodeImageResult(string data) 26 { 27 QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(); 28 qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;//二维码编码格式:ALPHA_NUMERIC,NUMERIC,BYTE 29 qrCodeEncoder.QRCodeScale = 8;//二维码大小,自定义 30 qrCodeEncoder.QRCodeVersion = 0;//二维码版本 31 qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;//有H,L,M,Q可选,错误机制级别 32 Image image = qrCodeEncoder.Encode(data, Encoding.Default);//image 就是生成的二维码图片,可以按照自己的方式去保存,这里直接显示到网页 33 ImageResult imgResult = new ImageResult(image); 34 return imgResult; 35 } 36 #endregion
ImageResult.cs 返回给浏览器时使用的Result类型
1 using System; 2 using System.Collections.Generic; 3 using System.Drawing; 4 using System.Drawing.Imaging; 5 using System.Linq; 6 using System.Text; 7 using System.Threading.Tasks; 8 using System.Web; 9 using System.Web.Mvc; 10 11 namespace Mimo.Payment.Common 12 { 13 /// <summary> 14 /// 构造返回图片的视图 15 /// </summary> 16 public class ImageResult : ActionResult 17 { 18 // 图片 19 public Image imageData; 20 21 22 // 构造器 23 public ImageResult(Image image) 24 { 25 imageData = image; 26 } 27 28 // 主要需要重写的方法 29 public override void ExecuteResult(ControllerContext context) 30 { 31 if (context == null) 32 { 33 throw new ArgumentNullException("context"); 34 } 35 HttpResponseBase response = context.HttpContext.Response; 36 // 设置 HTTP Header 37 response.ContentType = "image/jpeg"; 38 // 将图片数据写入Response 39 imageData.Save(context.HttpContext.Response.OutputStream, ImageFormat.Jpeg); 40 } 41 } 42 }
2015.03.20 以上就是最近完成的微信支付