说一说我和微信支付V3

做微信支付的时候遇到了挺多坑,现在记录下来和大家分享分享。

第一个坑:算签名的时候,总是提示签名失败。用微信提供的计算签名的工具,计算出来的签名是一致的。

原因是:密钥拿错了,我用的是公众平台的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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

 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 }
View Code

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 }
View Code

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 }
View Code

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一下是一些调用示例:

 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 }
View Code

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>
View Code


调用扫码支付的示例:

调用扫码支付时,只需要把生成的响应对象放到浏览器就行了,其中生成二维码的组件使用的是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
View Code

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 }
View Code

2015.03.20 以上就是最近完成的微信支付

原文地址:https://www.cnblogs.com/liuyu7177/p/4353889.html