微信支付帮助类

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Web;
  4 using System.Net;
  5 using System.IO;
  6 using System.Text;
  7 using System.Configuration;
  8 
  9 namespace Components.Payment.WxPayAPI
 10 {
 11     public class WxPayApi
 12     {
 13         /**
 14         *    
 15         * 查询订单
 16         * @param WxPayData inputObj 提交给查询订单API的参数
 17         * @param int timeOut 超时时间
 18         * @throws WxPayException
 19         * @return 成功时返回订单查询结果,其他抛异常
 20         */
 21         public static WxPayData OrderQuery(WxPayData inputObj, int timeOut = 6)
 22         {
 23             string url = "https://api.mch.weixin.qq.com/pay/orderquery";
 24             //检测必填参数
 25             if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id"))
 26             {
 27                 throw new WxPayException("订单查询接口中,out_trade_no、transaction_id至少填一个!");
 28             }
 29 
 30             inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号ID
 31             inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
 32             inputObj.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//随机字符串
 33             inputObj.SetValue("sign", inputObj.MakeSign(WxPayConfig.KEY));//签名
 34 
 35             string xml = inputObj.ToXml();
 36 
 37             var start = DateTime.Now;
 38 
 39             string response = HttpService.Post(xml, url, false, timeOut);//调用HTTP通信接口提交数据
 40 
 41             var end = DateTime.Now;
 42             int timeCost = (int)((end - start).TotalMilliseconds);//获得接口耗时
 43 
 44             //将xml格式的数据转化为对象以返回
 45             WxPayData result = new WxPayData();
 46             result.FromXml(response);
 47 
 48             ReportCostTime(url, timeCost, result);//测速上报
 49 
 50             return result;
 51         }
 52 
 53 
 54         /**
 55         * 
 56         * 撤销订单API接口
 57         * @param WxPayData inputObj 提交给撤销订单API接口的参数,out_trade_no和transaction_id必填一个
 58         * @param int timeOut 接口超时时间
 59         * @throws WxPayException
 60         * @return 成功时返回API调用结果,其他抛异常
 61         */
 62         public static WxPayData Reverse(WxPayData inputObj, int timeOut = 6)
 63         {
 64             string url = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
 65             //检测必填参数
 66             if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id"))
 67             {
 68                 throw new WxPayException("撤销订单API接口中,参数out_trade_no和transaction_id必须填写一个!");
 69             }
 70 
 71             inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号ID
 72             inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
 73             inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
 74             inputObj.SetValue("sign", inputObj.MakeSign(WxPayConfig.KEY));//签名
 75             string xml = inputObj.ToXml();
 76 
 77             var start = DateTime.Now;//请求开始时间
 78 
 79 
 80             string response = HttpService.Post(xml, url, true, timeOut);
 81 
 82 
 83             var end = DateTime.Now;
 84             int timeCost = (int)((end - start).TotalMilliseconds);
 85 
 86             WxPayData result = new WxPayData();
 87             result.FromXml(response);
 88 
 89             ReportCostTime(url, timeCost, result);//测速上报
 90 
 91             return result;
 92         }
 93 
 94 
 95         /**
 96         * 
 97         * 申请退款
 98         * @param WxPayData inputObj 提交给申请退款API的参数
 99         * @param int timeOut 超时时间
100         * @throws WxPayException
101         * @return 成功时返回接口调用结果,其他抛异常
102         */
103         public static WxPayData Refund(WxPayData inputObj, int timeOut = 6)
104         {
105             string url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
106             //检测必填参数
107             if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id"))
108             {
109                 throw new WxPayException("退款申请接口中,out_trade_no、transaction_id至少填一个!");
110             }
111             else if (!inputObj.IsSet("out_refund_no"))
112             {
113                 throw new WxPayException("退款申请接口中,缺少必填参数out_refund_no!");
114             }
115             else if (!inputObj.IsSet("total_fee"))
116             {
117                 throw new WxPayException("退款申请接口中,缺少必填参数total_fee!");
118             }
119             else if (!inputObj.IsSet("refund_fee"))
120             {
121                 throw new WxPayException("退款申请接口中,缺少必填参数refund_fee!");
122             }
123             else if (!inputObj.IsSet("op_user_id"))
124             {
125                 throw new WxPayException("退款申请接口中,缺少必填参数op_user_id!");
126             }
127 
128             inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号ID
129             inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
130             inputObj.SetValue("nonce_str", Guid.NewGuid().ToString().Replace("-", ""));//随机字符串
131             inputObj.SetValue("sign", inputObj.MakeSign(WxPayConfig.KEY));//签名
132             
133             string xml = inputObj.ToXml();
134             var start = DateTime.Now;
135 
136             string response = HttpService.Post(xml, url, true, timeOut);//调用HTTP通信接口提交数据到API
137 
138             var end = DateTime.Now;
139             int timeCost = (int)((end - start).TotalMilliseconds);//获得接口耗时
140 
141             //将xml格式的结果转换为对象以返回
142             WxPayData result = new WxPayData();
143             result.FromXml(response);
144 
145             ReportCostTime(url, timeCost, result);//测速上报
146 
147             return result;
148         }
149 
150 
151         /**
152         * 
153         * 查询退款
154         * 提交退款申请后,通过该接口查询退款状态。退款有一定延时,
155         * 用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
156         * out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个
157         * @param WxPayData inputObj 提交给查询退款API的参数
158         * @param int timeOut 接口超时时间
159         * @throws WxPayException
160         * @return 成功时返回,其他抛异常
161         */
162         public static WxPayData RefundQuery(WxPayData inputObj, int timeOut = 6)
163         {
164             string url = "https://api.mch.weixin.qq.com/pay/refundquery";
165             //检测必填参数
166             if(!inputObj.IsSet("out_refund_no") && !inputObj.IsSet("out_trade_no") &&
167                 !inputObj.IsSet("transaction_id") && !inputObj.IsSet("refund_id"))
168             {
169                 throw new WxPayException("退款查询接口中,out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个!");
170             }
171 
172             inputObj.SetValue("appid",WxPayConfig.APPID);//公众账号ID
173             inputObj.SetValue("mch_id",WxPayConfig.MCHID);//商户号
174             inputObj.SetValue("nonce_str",GenerateNonceStr());//随机字符串
175             inputObj.SetValue("sign", inputObj.MakeSign(WxPayConfig.KEY));//签名
176 
177             string xml = inputObj.ToXml();
178         
179             var start = DateTime.Now;//请求开始时间
180 
181             string response = HttpService.Post(xml, url, false, timeOut);//调用HTTP通信接口以提交数据到API
182 
183             var end = DateTime.Now;
184             int timeCost = (int)((end-start).TotalMilliseconds);//获得接口耗时
185 
186             //将xml格式的结果转换为对象以返回
187             WxPayData result = new WxPayData();
188             result.FromXml(response);
189 
190             ReportCostTime(url, timeCost, result);//测速上报
191         
192             return result;
193         }
194 
195 
196         /**
197         * 下载对账单
198         * @param WxPayData inputObj 提交给下载对账单API的参数
199         * @param int timeOut 接口超时时间
200         * @throws WxPayException
201         * @return 成功时返回,其他抛异常
202         */
203         public static WxPayData DownloadBill(WxPayData inputObj, int timeOut = 6)
204         {
205             string url = "https://api.mch.weixin.qq.com/pay/downloadbill";
206             //检测必填参数
207             if (!inputObj.IsSet("bill_date"))
208             {
209                 throw new WxPayException("对账单接口中,缺少必填参数bill_date!");
210             }
211 
212             inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号ID
213             inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
214             inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
215             inputObj.SetValue("sign", inputObj.MakeSign(WxPayConfig.KEY));//签名
216 
217             string xml = inputObj.ToXml();
218 
219             string response = HttpService.Post(xml, url, false, timeOut);//调用HTTP通信接口以提交数据到API
220 
221             WxPayData result = new WxPayData();
222             //若接口调用失败会返回xml格式的结果
223             if (response.Substring(0, 5) == "<xml>")
224             {
225                 result.FromXml(response);
226             }
227             //接口调用成功则返回非xml格式的数据
228             else
229                 result.SetValue("result", response);
230 
231             return result;
232         }
233 
234 
235         /**
236         * 
237         * 转换短链接
238         * 该接口主要用于扫码原生支付模式一中的二维码链接转成短链接(weixin://wxpay/s/XXXXXX),
239         * 减小二维码数据量,提升扫描速度和精确度。
240         * @param WxPayData inputObj 提交给转换短连接API的参数
241         * @param int timeOut 接口超时时间
242         * @throws WxPayException
243         * @return 成功时返回,其他抛异常
244         */
245         public static WxPayData ShortUrl(WxPayData inputObj, int timeOut = 6)
246         {
247             string url = "https://api.mch.weixin.qq.com/tools/shorturl";
248             //检测必填参数
249             if(!inputObj.IsSet("long_url"))
250             {
251                 throw new WxPayException("需要转换的URL,签名用原串,传输需URL encode!");
252             }
253 
254             inputObj.SetValue("appid",WxPayConfig.APPID);//公众账号ID
255             inputObj.SetValue("mch_id",WxPayConfig.MCHID);//商户号
256             inputObj.SetValue("nonce_str",GenerateNonceStr());//随机字符串    
257             inputObj.SetValue("sign", inputObj.MakeSign(WxPayConfig.KEY));//签名
258             string xml = inputObj.ToXml();
259         
260             var start = DateTime.Now;//请求开始时间
261 
262             string response = HttpService.Post(xml, url, false, timeOut);
263 
264             var end = DateTime.Now;
265             int timeCost = (int)((end - start).TotalMilliseconds);
266 
267             WxPayData result = new WxPayData();
268             result.FromXml(response);
269             ReportCostTime(url, timeCost, result);//测速上报
270         
271             return result;
272         }
273 
274 
275         /**
276         * 
277         * 统一下单
278         * @param WxPaydata inputObj 提交给统一下单API的参数
279         * @param int timeOut 超时时间
280         * @throws WxPayException
281         * @return 成功时返回,其他抛异常
282         */
283         public static WxPayData UnifiedOrder(WxPayData inputObj, string key, int timeOut = 6)
284         {
285             string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
286             //检测必填参数
287             if (!inputObj.IsSet("out_trade_no"))
288             {
289                 throw new WxPayException("缺少统一支付接口必填参数out_trade_no!");
290             }
291             else if (!inputObj.IsSet("body"))
292             {
293                 throw new WxPayException("缺少统一支付接口必填参数body!");
294             }
295             else if (!inputObj.IsSet("total_fee"))
296             {
297                 throw new WxPayException("缺少统一支付接口必填参数total_fee!");
298             }
299             else if (!inputObj.IsSet("trade_type"))
300             {
301                 throw new WxPayException("缺少统一支付接口必填参数trade_type!");
302             }
303 
304             //关联参数
305             if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid"))
306             {
307                 throw new WxPayException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
308             }
309             if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id"))
310             {
311                 throw new WxPayException("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
312             }
313 
314             ////异步通知url未设置,则使用配置文件中的url
315             //if (!inputObj.IsSet("notify_url"))
316             //{
317             //    inputObj.SetValue("notify_url",  ConfigurationManager.AppSettings["Domain"]  + WxPayConfig.NOTIFY_URL);//异步通知url
318             //}
319 
320             //inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号ID
321             //inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
322             //inputObj.SetValue("spbill_create_ip", WxPayConfig.IP);//终端ip              
323             inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
324 
325             //签名
326             inputObj.SetValue("sign", inputObj.MakeSign(key));
327             string xml = inputObj.ToXml();
328 
329             var start = DateTime.Now;
330             //Functions.Write("当前请求的XML为:"+xml);
331             string response = HttpService.Post(xml, url, false, timeOut);
332             Functions.Write("response:" + response);
333             var end = DateTime.Now;
334             int timeCost = (int)((end - start).TotalMilliseconds);
335 
336             WxPayData result = new WxPayData(key);
337             result.FromXml(response);
338 
339             ReportCostTime(url, timeCost, result);//测速上报
340 
341             return result;
342         }
343 
344         /**
345               * 
346               * 统一下单
347               * @param WxPaydata inputObj 提交给统一下单API的参数
348               * @param int timeOut 超时时间
349               * @throws WxPayException
350               * @return 成功时返回,其他抛异常
351               */
352         public static SortedDictionary<string, object> UnifiedOrderStr(WxPayData inputObj, int timeOut = 6)
353         {
354             string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
355             //检测必填参数
356             if (!inputObj.IsSet("out_trade_no"))
357             {
358                 throw new WxPayException("缺少统一支付接口必填参数out_trade_no!");
359             }
360             else if (!inputObj.IsSet("body"))
361             {
362                 throw new WxPayException("缺少统一支付接口必填参数body!");
363             }
364             else if (!inputObj.IsSet("total_fee"))
365             {
366                 throw new WxPayException("缺少统一支付接口必填参数total_fee!");
367             }
368             else if (!inputObj.IsSet("trade_type"))
369             {
370                 throw new WxPayException("缺少统一支付接口必填参数trade_type!");
371             }
372 
373             //关联参数
374             if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid"))
375             {
376                 throw new WxPayException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
377             }
378             if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id"))
379             {
380                 throw new WxPayException("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
381             }
382 
383             //异步通知url未设置,则使用配置文件中的url
384             if (!inputObj.IsSet("notify_url"))
385             {
386                 inputObj.SetValue("notify_url", WxPayConfig.NOTIFY_URL);//异步通知url
387             }
388 
389             //inputObj.SetValue("appid", WxPayConfig.APPID);//公众账号ID
390             //inputObj.SetValue("mch_id", WxPayConfig.MCHID);//商户号
391             //inputObj.SetValue("spbill_create_ip", WxPayConfig.IP);//终端ip              
392             inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
393 
394             //签名
395             inputObj.SetValue("sign", inputObj.MakeSign(WxPayConfig.KEY));
396             string xml = inputObj.ToXml();
397 
398             var start = DateTime.Now;
399             string response = HttpService.Post(xml, url, false, timeOut);
400             Functions.Write("response:" + response);
401             var end = DateTime.Now;
402             int timeCost = (int)((end - start).TotalMilliseconds);
403 
404             WxPayData result = new WxPayData();
405             var reslutStr = result.FromXml(response);
406             reslutStr.Add("paySign", inputObj.MakeSign(WxPayConfig.KEY));
407             ReportCostTime(url, timeCost, result);//测速上报
408             return reslutStr;
409         }
410         /**
411         * 
412         * 关闭订单
413         * @param WxPayData inputObj 提交给关闭订单API的参数
414         * @param int timeOut 接口超时时间
415         * @throws WxPayException
416         * @return 成功时返回,其他抛异常
417         */
418         public static WxPayData CloseOrder(WxPayData inputObj, int timeOut = 6)
419         {
420             string url = "https://api.mch.weixin.qq.com/pay/closeorder";
421             //检测必填参数
422             if(!inputObj.IsSet("out_trade_no"))
423             {
424                 throw new WxPayException("关闭订单接口中,out_trade_no必填!");
425             }
426 
427             inputObj.SetValue("appid",WxPayConfig.APPID);//公众账号ID
428             inputObj.SetValue("mch_id",WxPayConfig.MCHID);//商户号
429             inputObj.SetValue("nonce_str",GenerateNonceStr());//随机字符串        
430             inputObj.SetValue("sign", inputObj.MakeSign(WxPayConfig.KEY));//签名
431             string xml = inputObj.ToXml();
432         
433             var start = DateTime.Now;//请求开始时间
434 
435             string response = HttpService.Post(xml, url, false, timeOut);
436 
437             var end = DateTime.Now;
438             int timeCost = (int)((end - start).TotalMilliseconds);
439 
440             WxPayData result = new WxPayData();
441             result.FromXml(response);
442 
443             ReportCostTime(url, timeCost, result);//测速上报
444         
445             return result;
446         }
447 
448 
449         /**
450         * 
451         * 测速上报
452         * @param string interface_url 接口URL
453         * @param int timeCost 接口耗时
454         * @param WxPayData inputObj参数数组
455         */
456         private static void ReportCostTime(string interface_url, int timeCost, WxPayData inputObj)
457         {
458             //如果不需要进行上报
459             if(WxPayConfig.REPORT_LEVENL == 0)
460             {
461                 return;
462             } 
463 
464             //如果仅失败上报
465             if(WxPayConfig.REPORT_LEVENL == 1 && inputObj.IsSet("return_code") && inputObj.GetValue("return_code").ToString() == "SUCCESS" &&
466              inputObj.IsSet("result_code") && inputObj.GetValue("result_code").ToString() == "SUCCESS")
467             {
468                  return;
469             }
470          
471             //上报逻辑
472             WxPayData data = new WxPayData();
473             data.SetValue("interface_url",interface_url);
474             data.SetValue("execute_time_",timeCost);
475             //返回状态码
476             if(inputObj.IsSet("return_code"))
477             {
478                 data.SetValue("return_code",inputObj.GetValue("return_code"));
479             }
480             //返回信息
481             if(inputObj.IsSet("return_msg"))
482             {
483                 data.SetValue("return_msg",inputObj.GetValue("return_msg"));
484             }
485             //业务结果
486             if(inputObj.IsSet("result_code"))
487             {
488                 data.SetValue("result_code",inputObj.GetValue("result_code"));
489             }
490             //错误代码
491             if(inputObj.IsSet("err_code"))
492             {
493                 data.SetValue("err_code",inputObj.GetValue("err_code"));
494             }
495             //错误代码描述
496             if(inputObj.IsSet("err_code_des"))
497             {
498                 data.SetValue("err_code_des",inputObj.GetValue("err_code_des"));
499             }
500             //商户订单号
501             if(inputObj.IsSet("out_trade_no"))
502             {
503                 data.SetValue("out_trade_no",inputObj.GetValue("out_trade_no"));
504             }
505             //设备号
506             if(inputObj.IsSet("device_info"))
507             {
508                 data.SetValue("device_info",inputObj.GetValue("device_info"));
509             }
510         
511             try
512             {
513                 Report(data);
514             }
515             catch (WxPayException ex)
516             {
517                 //不做任何处理
518             }
519         }
520 
521 
522         /**
523         * 
524         * 测速上报接口实现
525         * @param WxPayData inputObj 提交给测速上报接口的参数
526         * @param int timeOut 测速上报接口超时时间
527         * @throws WxPayException
528         * @return 成功时返回测速上报接口返回的结果,其他抛异常
529         */
530         public static WxPayData Report(WxPayData inputObj, int timeOut = 1)
531         {
532             string url = "https://api.mch.weixin.qq.com/payitil/report";
533             //检测必填参数
534             if(!inputObj.IsSet("interface_url"))
535             {
536                 throw new WxPayException("接口URL,缺少必填参数interface_url!");
537             } 
538             if(!inputObj.IsSet("return_code"))
539             {
540                 throw new WxPayException("返回状态码,缺少必填参数return_code!");
541             } 
542             if(!inputObj.IsSet("result_code"))
543             {
544                 throw new WxPayException("业务结果,缺少必填参数result_code!");
545             } 
546             if(!inputObj.IsSet("user_ip"))
547             {
548                 throw new WxPayException("访问接口IP,缺少必填参数user_ip!");
549             } 
550             if(!inputObj.IsSet("execute_time_"))
551             {
552                 throw new WxPayException("接口耗时,缺少必填参数execute_time_!");
553             }
554 
555             inputObj.SetValue("appid",WxPayConfig.APPID);//公众账号ID
556             inputObj.SetValue("mch_id",WxPayConfig.MCHID);//商户号
557             inputObj.SetValue("user_ip",WxPayConfig.IP);//终端ip
558             inputObj.SetValue("time",DateTime.Now.ToString("yyyyMMddHHmmss"));//商户上报时间     
559             inputObj.SetValue("nonce_str",GenerateNonceStr());//随机字符串
560             inputObj.SetValue("sign", inputObj.MakeSign(WxPayConfig.KEY));//签名
561             string xml = inputObj.ToXml();
562 
563 
564             string response = HttpService.Post(xml, url, false, timeOut);
565 
566 
567             WxPayData result = new WxPayData();
568             result.FromXml(response);
569             return result;
570         }
571 
572         /**
573         * 根据当前系统时间加随机序列来生成订单号
574          * @return 订单号
575         */
576         public static string GenerateOutTradeNo()
577         {
578             var ran = new Random();
579             return string.Format("{0}{1}{2}", WxPayConfig.MCHID, DateTime.Now.ToString("yyyyMMddHHmmss"), ran.Next(999));
580         }
581 
582         /**
583         * 生成时间戳,标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数
584          * @return 时间戳
585         */
586         public static string GenerateTimeStamp()
587         {
588             TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
589             return Convert.ToInt64(ts.TotalSeconds).ToString();
590         }
591 
592         /**
593         * 生成随机串,随机串包含字母或数字
594         * @return 随机串
595         */
596         public static string GenerateNonceStr()
597         {
598             return Guid.NewGuid().ToString().Replace("-", "");
599         }
600     }
601 }
微信支付类
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Web;
  4 using System.Web.UI;
  5 using System.Web.UI.WebControls;
  6 using System.Runtime.Serialization;
  7 using System.IO;
  8 using System.Text;
  9 using System.Net;
 10 using System.Web.Security;
 11 using LitJson;
 12 
 13 namespace Components.Payment.WxPayAPI
 14 {
 15     public class JsApiPay
 16     {
 17         /// <summary>
 18         /// 保存页面对象,因为要在类的方法中使用Page的Request对象
 19         /// </summary>
 20         //private Page page {get;set;}
 21 
 22         /// <summary>
 23         /// openid用于调用统一下单接口
 24         /// </summary>
 25         public string openid { get; set; }
 26 
 27         /// <summary>
 28         /// access_token用于获取收货地址js函数入口参数
 29         /// </summary>
 30         public string access_token { get; set; }
 31 
 32         /// <summary>
 33         /// 商品金额,用于统一下单
 34         /// </summary>
 35         public int total_fee { get; set; }
 36 
 37         public string out_trade_no { get; set; }
 38         public string body { get; set; }
 39         public string notify_url { get; set; }
 40         public string appid { get; set; }
 41         public string mch_id { get; set; }
 42         public string key { get; set; }
 43         public string APPSECRET { get; set; }
 44         /// <summary>
 45         /// 统一下单接口返回结果
 46         /// </summary>
 47         public WxPayData unifiedOrderResult { get; set; }
 48 
 49         public JsApiPay()
 50         {
 51 
 52         }
 53 
 54         public JsApiPay(string notify_url, string appid, string mch_id, string key, string APPSECRET)
 55         {
 56              this.notify_url = notify_url;
 57              this.appid = appid;
 58              this.mch_id = mch_id;
 59              this.key = key;
 60              this.APPSECRET = APPSECRET;
 61         }
 62 
 63 
 64         /**
 65         * 
 66         * 网页授权获取用户基本信息的全部过程
 67         * 详情请参看网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
 68         * 第一步:利用url跳转获取code
 69         * 第二步:利用code去获取openid和access_token
 70         * 
 71         */
 72         public void GetOpenidAndAccessToken()
 73         {
 74             var page = HttpContext.Current;
 75             if (!string.IsNullOrEmpty(page.Request.QueryString["code"]))
 76             {
 77                 //获取code码,以获取openid和access_token
 78                 string code = page.Request.QueryString["code"];
 79                 GetOpenidAndAccessTokenFromCode(code);
 80                 Functions.Write("第二次执行");
 81             }
 82             else
 83             {
 84                 //构造网页授权获取code的URL
 85                 string host = page.Request.Url.Host;
 86                 string path = page.Request.Path;
 87                 string redirect_uri = HttpUtility.UrlEncode("http://" + host + path);
 88                 WxPayData data = new WxPayData();
 89                 data.SetValue("appid", WxPayConfig.APPID);
 90                 data.SetValue("redirect_uri", redirect_uri);
 91                 data.SetValue("response_type", "code");
 92                 data.SetValue("scope", "snsapi_base");
 93                 data.SetValue("state", "STATE" + "#wechat_redirect");
 94                 string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl();
 95                 try
 96                 {
 97                     //触发微信返回code码         
 98                     page.Response.Redirect(url);//Redirect函数会抛出ThreadAbortException异常,不用处理这个异常
 99                     
100                 }
101                 catch(System.Threading.ThreadAbortException ex)
102                 {
103                     Functions.Write("GetOpenidAndAccessToken()方法异常" + ex.Message);
104                 }
105             }
106         }
107 
108         /**
109         * 
110         * 网页授权获取用户基本信息的全部过程
111         * 详情请参看网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
112         * 
113         */
114         public JsonData GetUserInfoByOpenidAndAccessToken(string token, string openid)
115         {
116             WxPayData data = new WxPayData();
117             data.SetValue("access_token", token);
118             data.SetValue("openid", openid);
119             data.SetValue("lang", "zh_CN");
120             string url = "https://api.weixin.qq.com/sns/userinfo?" + data.ToUrl();
121             try
122             {
123                 //请求url以获取数据
124                 string result = HttpService.Get(url);
125                 JsonData jd = JsonMapper.ToObject(result);
126                 return jd;
127             }
128             catch (System.Threading.ThreadAbortException ex)
129             {
130                 Functions.Write("GetUserInfoByOpenidAndAccessToken()方法异常" + ex.Message);
131                 return null;
132             }
133         }
134 
135         /**
136         * 
137         * 通过code换取网页授权access_token和openid的返回数据,正确时返回的JSON数据包如下:
138         * {
139         *  "access_token":"ACCESS_TOKEN",
140         *  "expires_in":7200,
141         *  "refresh_token":"REFRESH_TOKEN",
142         *  "openid":"OPENID",
143         *  "scope":"SCOPE",
144         *  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
145         * }
146         * 其中access_token可用于获取共享收货地址
147         * openid是微信支付jsapi支付接口统一下单时必须的参数
148         * 更详细的说明请参考网页授权获取用户基本信息:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
149         * @失败时抛异常WxPayException
150         */
151         public void GetOpenidAndAccessTokenFromCode(string code)
152         {
153             try
154             {
155                 //构造获取openid及access_token的url
156                 WxPayData data = new WxPayData();
157                 data.SetValue("appid", this.appid);
158                 data.SetValue("secret", this.APPSECRET);
159                 data.SetValue("code", code);
160                 data.SetValue("grant_type", "authorization_code");
161                 string url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + data.ToUrl();
162 
163                 //请求url以获取数据
164                 string result = HttpService.Get(url);
165                 //保存access_token,用于收货地址获取
166                 JsonData jd = JsonMapper.ToObject(result);
167                 access_token = (string)jd["access_token"];
168 
169                 //获取用户openid
170                 openid = (string)jd["openid"];
171             }
172             catch (Exception ex)
173             {
174                 Functions.Write("GetOpenidAndAccessTokenFromCode()方法异常" + ex.Message);
175             }
176         }
177 
178         /**
179          * 调用统一下单,获得下单结果
180          * @return 统一下单结果
181          * @失败时抛异常WxPayException
182          */
183         public WxPayData GetUnifiedOrderResult()
184         {
185             //统一下单
186             WxPayData data = new WxPayData();
187             data.SetValue("body", body);
188             //data.SetValue("attach", "test");
189             data.SetValue("out_trade_no", out_trade_no);
190             data.SetValue("total_fee", total_fee);
191             data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));
192             data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));
193             data.SetValue("goods_tag", "test");
194             data.SetValue("trade_type", "JSAPI");
195             data.SetValue("openid", openid);
196             data.SetValue("appid", WxPayConfig.APPID);//公众账号ID
197             data.SetValue("mch_id", WxPayConfig.MCHID);//商户号
198             data.SetValue("spbill_create_ip",Functions.GetIP());//终端ip      
199             data.SetValue("notify_url", notify_url);
200             WxPayData result = WxPayApi.UnifiedOrder(data,this.key);
201             if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "")
202             {
203                 throw new WxPayException("UnifiedOrder response error!");
204             }
205 
206             unifiedOrderResult = result;
207             return result;
208         }
209 
210         /**
211         *  
212         * 从统一下单成功返回的数据中获取微信浏览器调起jsapi支付所需的参数,
213         * 微信浏览器调起JSAPI时的输入参数格式如下:
214         * {
215         *   "appId" : "wx2421b1c4370ec43b",     //公众号名称,由商户传入     
216         *   "timeStamp":" 1395712654",         //时间戳,自1970年以来的秒数     
217         *   "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串     
218         *   "package" : "prepay_id=u802345jgfjsdfgsdg888",     
219         *   "signType" : "MD5",         //微信签名方式:    
220         *   "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 
221         * }
222         * @return string 微信浏览器调起JSAPI时的输入参数,json格式可以直接做参数用
223         * 更详细的说明请参考网页端调起支付API:http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7
224         * 
225         */
226         public string GetJsApiParameters()
227         {
228 
229             WxPayData jsApiParam = new WxPayData();
230             jsApiParam.SetValue("appId", unifiedOrderResult.GetValue("appid"));
231             jsApiParam.SetValue("timeStamp", WxPayApi.GenerateTimeStamp());
232             jsApiParam.SetValue("nonceStr", WxPayApi.GenerateNonceStr());
233             jsApiParam.SetValue("package", "prepay_id=" + unifiedOrderResult.GetValue("prepay_id"));
234             jsApiParam.SetValue("signType", "MD5");
235             jsApiParam.SetValue("paySign", jsApiParam.MakeSign(this.key));
236             jsApiParam.SetValue("openid", this.openid);
237             string parameters = jsApiParam.ToJson();
238 
239             return parameters;
240         }
241 
242         public string GetJsApiParameters(string openid)
243         {
244 
245             WxPayData jsApiParam = new WxPayData();
246             jsApiParam.SetValue("appId", unifiedOrderResult.GetValue("appid"));
247             jsApiParam.SetValue("timeStamp", WxPayApi.GenerateTimeStamp());
248             jsApiParam.SetValue("nonceStr", WxPayApi.GenerateNonceStr());
249             jsApiParam.SetValue("package", "prepay_id=" + unifiedOrderResult.GetValue("prepay_id"));
250             jsApiParam.SetValue("signType", "MD5");
251             jsApiParam.SetValue("paySign", jsApiParam.MakeSign(this.key));
252             jsApiParam.SetValue("openid", openid);
253             string parameters = jsApiParam.ToJson();
254 
255             return parameters;
256         }
257         /**
258         * 
259         * 获取收货地址js函数入口参数,详情请参考收货地址共享接口:http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_9
260         * @return string 共享收货地址js函数需要的参数,json格式可以直接做参数使用
261         */
262         public string GetEditAddressParameters()
263         {
264             var page = HttpContext.Current;
265             string parameter = "";
266             try
267             {
268                 string host = page.Request.Url.Host;
269                 string path = page.Request.Path;
270                 string queryString = page.Request.Url.Query;
271                 //这个地方要注意,参与签名的是网页授权获取用户信息时微信后台回传的完整url
272                 string url = "http://" + host + path + queryString;
273 
274                 //构造需要用SHA1算法加密的数据
275                 WxPayData signData = new WxPayData();
276                 signData.SetValue("appid", WxPayConfig.APPID);
277                 signData.SetValue("url", url);
278                 signData.SetValue("timestamp",WxPayApi.GenerateTimeStamp());
279                 signData.SetValue("noncestr",WxPayApi.GenerateNonceStr());
280                 signData.SetValue("accesstoken",access_token);
281                 string param = signData.ToUrl();
282 
283                 //SHA1加密
284                 string addrSign = FormsAuthentication.HashPasswordForStoringInConfigFile(param, "SHA1");
285 
286                 //获取收货地址js函数入口参数
287                 WxPayData afterData = new WxPayData();
288                 afterData.SetValue("appId", WxPayConfig.APPID);
289                 afterData.SetValue("scope","jsapi_address");
290                 afterData.SetValue("signType","sha1");
291                 afterData.SetValue("addrSign",addrSign);
292                 afterData.SetValue("timeStamp",signData.GetValue("timestamp"));
293                 afterData.SetValue("nonceStr",signData.GetValue("noncestr"));
294 
295                 //转为json格式
296                 parameter = afterData.IObjectToJSON();
297             }
298             catch (Exception ex)
299             {
300                 //throw new WxPayException(ex.ToString());
301             }
302 
303             return parameter;
304         }
305     }
306 }
jsApi
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Web;
  4 using System.Net;
  5 using System.IO;
  6 using System.Text;
  7 using System.Net.Security;    
  8 using System.Security.Authentication;
  9 using System.Security.Cryptography.X509Certificates;
 10 
 11 namespace Components.Payment.WxPayAPI
 12 {
 13     /// <summary>
 14     /// http连接基础类,负责底层的http通信
 15     /// </summary>
 16     public class HttpService
 17     {
 18 
 19         public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
 20         {
 21             //直接确认,否则打不开    
 22             return true;
 23         }
 24 
 25         public static string Post(string xml, string url, bool isUseCert, int timeout)
 26         {
 27             System.GC.Collect();//垃圾回收,回收没有正常关闭的http连接
 28 
 29             string result = "";//返回结果
 30 
 31             HttpWebRequest request = null;
 32             HttpWebResponse response = null;
 33             Stream reqStream = null;
 34 
 35             try
 36             {
 37                 //设置最大连接数
 38                 ServicePointManager.DefaultConnectionLimit = 200;
 39                 //设置https验证方式
 40                 if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
 41                 {
 42                     ServicePointManager.ServerCertificateValidationCallback =
 43                             new RemoteCertificateValidationCallback(CheckValidationResult);
 44                 }
 45 
 46                 /***************************************************************
 47                 * 下面设置HttpWebRequest的相关属性
 48                 * ************************************************************/
 49                 request = (HttpWebRequest)WebRequest.Create(url);
 50 
 51                 request.Method = "POST";
 52                 request.Timeout = timeout * 1000;
 53 
 54                 //设置代理服务器
 55                 //WebProxy proxy = new WebProxy();                          //定义一个网关对象
 56                 //proxy.Address = new Uri(WxPayConfig.PROXY_URL);              //网关服务器端口:端口
 57                 //request.Proxy = proxy;
 58 
 59                 //设置POST的数据类型和长度
 60                 request.ContentType = "text/xml";
 61                 byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
 62                 request.ContentLength = data.Length;
 63 
 64                 //是否使用证书
 65                 if (isUseCert)
 66                 {
 67                     string path = HttpContext.Current.Request.PhysicalApplicationPath;
 68                     X509Certificate2 cert = new X509Certificate2(path + WxPayConfig.SSLCERT_PATH, WxPayConfig.SSLCERT_PASSWORD);
 69                     request.ClientCertificates.Add(cert);
 70                 }
 71 
 72                 //往服务器写入数据
 73                 reqStream = request.GetRequestStream();
 74                 reqStream.Write(data, 0, data.Length);
 75                 reqStream.Close();
 76 
 77                 //获取服务端返回
 78                 response = (HttpWebResponse)request.GetResponse();
 79 
 80                 //获取服务端返回数据
 81                 StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
 82                 result = sr.ReadToEnd().Trim();
 83                 sr.Close();
 84             }
 85             catch (System.Threading.ThreadAbortException e)
 86             {
 87                 System.Threading.Thread.ResetAbort();
 88             }
 89             catch (WebException e)
 90             {
 91                 if (e.Status == WebExceptionStatus.ProtocolError)
 92                 {
 93                 }
 94                 throw new WxPayException(e.ToString());
 95             }
 96             catch (Exception e)
 97             {
 98                 throw new WxPayException(e.ToString());
 99             }
100             finally
101             {
102                 //关闭连接和流
103                 if (response != null)
104                 {
105                     response.Close();
106                 }
107                 if(request != null)
108                 {
109                     request.Abort();
110                 }
111             }
112             return result;
113         }
114 
115         /// <summary>
116         /// 处理http GET请求,返回数据
117         /// </summary>
118         /// <param name="url">请求的url地址</param>
119         /// <returns>http GET成功后返回的数据,失败抛WebException异常</returns>
120         public static string Get(string url)
121         {
122             System.GC.Collect();
123             string result = "";
124 
125             HttpWebRequest request = null;
126             HttpWebResponse response = null;
127 
128             //请求url以获取数据
129             try
130             {
131                 //设置最大连接数
132                 ServicePointManager.DefaultConnectionLimit = 200;
133                 //设置https验证方式
134                 if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
135                 {
136                     ServicePointManager.ServerCertificateValidationCallback =
137                             new RemoteCertificateValidationCallback(CheckValidationResult);
138                 }
139 
140                 /***************************************************************
141                 * 下面设置HttpWebRequest的相关属性
142                 * ************************************************************/
143                 request = (HttpWebRequest)WebRequest.Create(url);
144 
145                 request.Method = "GET";
146 
147                 //设置代理
148                 //WebProxy proxy = new WebProxy();
149                 //proxy.Address = new Uri(WxPayConfig.PROXY_URL);
150                 //request.Proxy = proxy;
151 
152                 //获取服务器返回
153                 response = (HttpWebResponse)request.GetResponse();
154 
155                 //获取HTTP返回数据
156                 StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
157                 result = sr.ReadToEnd().Trim();
158                 sr.Close();
159             }
160             catch (System.Threading.ThreadAbortException e)
161             {
162                 System.Threading.Thread.ResetAbort();
163             }
164             catch (WebException e)
165             {
166                 if (e.Status == WebExceptionStatus.ProtocolError)
167                 {
168                 }
169                 throw new WxPayException(e.ToString());
170             }
171             catch (Exception e)
172             {
173                 throw new WxPayException(e.ToString());
174             }
175             finally
176             {
177                 //关闭连接和流
178                 if (response != null)
179                 {
180                     response.Close();
181                 }
182                 if (request != null)
183                 {
184                     request.Abort();
185                 }
186             }
187             return result;
188         }
189     }
190 }
httpService
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Web;
  4 using System.Xml;
  5 using System.Security.Cryptography;
  6 using System.Text;
  7 using LitJson;
  8 
  9 
 10 namespace Components.Payment.WxPayAPI
 11 {
 12     /// <summary>
 13     /// 微信支付协议接口数据类,所有的API接口通信都依赖这个数据结构,
 14     /// 在调用接口之前先填充各个字段的值,然后进行接口通信,
 15     /// 这样设计的好处是可扩展性强,用户可随意对协议进行更改而不用重新设计数据结构,
 16     /// 还可以随意组合出不同的协议数据包,不用为每个协议设计一个数据包结构
 17     /// </summary>
 18     public class WxPayData
 19     {
 20         public WxPayData()
 21         {
 22 
 23         }
 24         public string key { get; set; }
 25         public WxPayData(string key)
 26         {
 27             this.key = key;
 28         }
 29         //采用排序的Dictionary的好处是方便对数据包进行签名,不用再签名之前再做一次排序
 30         private SortedDictionary<string, object> m_values = new SortedDictionary<string, object>();
 31 
 32         /**
 33         * 设置某个字段的值
 34         * @param key 字段名
 35          * @param value 字段值
 36         */
 37         public void SetValue(string key, object value)
 38         {
 39             m_values[key] = value;
 40         }
 41 
 42         /**
 43         * 根据字段名获取某个字段的值
 44         * @param key 字段名
 45          * @return key对应的字段值
 46         */
 47         public object GetValue(string key)
 48         {
 49             object o = null;
 50             m_values.TryGetValue(key, out o);
 51             return o;
 52         }
 53 
 54         /**
 55          * 判断某个字段是否已设置
 56          * @param key 字段名
 57          * @return 若字段key已被设置,则返回true,否则返回false
 58          */
 59         public bool IsSet(string key)
 60         {
 61             object o = null;
 62             m_values.TryGetValue(key, out o);
 63             if (null != o)
 64                 return true;
 65             else
 66                 return false;
 67         }
 68 
 69         /**
 70         * @将Dictionary转成xml
 71         * @return 经转换得到的xml串
 72         * @throws WxPayException
 73         **/
 74         public string ToXml()
 75         {
 76             //数据为空时不能转化为xml格式
 77             if (0 == m_values.Count)
 78             {
 79                 throw new WxPayException("WxPayData数据为空!");
 80             }
 81 
 82             string xml = "<xml>";
 83             foreach (KeyValuePair<string, object> pair in m_values)
 84             {
 85                 //字段值不能为null,会影响后续流程
 86                 if (pair.Value == null)
 87                 {
 88                     throw new WxPayException("WxPayData内部含有值为null的字段!");
 89                 }
 90 
 91                 if (pair.Value.GetType() == typeof(int))
 92                 {
 93                     xml += "<" + pair.Key + ">" + pair.Value + "</" + pair.Key + ">";
 94                 }
 95                 else if (pair.Value.GetType() == typeof(string))
 96                 {
 97                     xml += "<" + pair.Key + ">" + pair.Value + "</" + pair.Key + ">";
 98                     //xml += "<" + pair.Key + ">" + "<![CDATA[" + pair.Value + "]]></" + pair.Key + ">";
 99                 }
100                 else//除了string和int类型不能含有其他数据类型
101                 {
102                     throw new WxPayException("WxPayData字段数据类型错误!");
103                 }
104             }
105             xml += "</xml>";
106             return xml;
107         }
108 
109         /**
110         * @将xml转为WxPayData对象并返回对象内部的数据
111         * @param string 待转换的xml串
112         * @return 经转换得到的Dictionary
113         * @throws WxPayException
114         */
115         public SortedDictionary<string, object> FromXml(string xml)
116         {
117             if (string.IsNullOrEmpty(xml))
118             {
119                 throw new WxPayException("将空的xml串转换为WxPayData不合法!");
120             }
121 
122             XmlDocument xmlDoc = new XmlDocument();
123             xmlDoc.LoadXml(xml);
124             XmlNode xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
125             XmlNodeList nodes = xmlNode.ChildNodes;
126             foreach (XmlNode xn in nodes)
127             {
128                 XmlElement xe = (XmlElement)xn;
129                 m_values[xe.Name] = xe.InnerText;//获取xml的键值对到WxPayData内部的数据中
130             }
131             try
132             {
133                 CheckSign(this.key);//验证签名,不通过会抛异常
134             }
135             catch(WxPayException ex)
136             {
137                 throw new WxPayException(ex.Message);
138             }
139 
140             return m_values;
141         }
142 
143         /**
144         * @Dictionary格式转化成url参数格式
145         * @ return url格式串, 该串不包含sign字段值
146         */
147         public string ToUrl()
148         {
149             string buff = "";
150             foreach (KeyValuePair<string, object> pair in m_values)
151             {
152                 if (pair.Value == null)
153                 {
154                     throw new WxPayException("WxPayData内部含有值为null的字段!");
155                 }
156 
157                 if (pair.Key != "sign" && pair.Value.ToString() != "")
158                 {
159                     buff += pair.Key + "=" + pair.Value + "&";
160                 }
161             }
162             buff = buff.Trim('&');
163             return buff;
164         }
165 
166 
167         public string ToJson()
168         {
169             string jsonStr = JsonMapper.ToJson(m_values);
170             return jsonStr;
171         }
172 
173         /**
174         * @values格式化成能在Web页面上显示的结果(因为web页面上不能直接输出xml格式的字符串)
175         */
176         public string ToPrintStr()
177         {
178             string str = "";
179             foreach (KeyValuePair<string, object> pair in m_values)
180             {
181                 if (pair.Value == null)
182                 {
183                     throw new WxPayException("WxPayData内部含有值为null的字段!");
184                 }
185 
186                 str += string.Format("{0}={1}<br>", pair.Key, pair.Value.ToString());
187             }
188             return str;
189         }
190 
191         /**
192         * @生成签名,详见签名生成算法
193         * @return 签名, sign字段不参加签名
194         */
195         public string MakeSign(string key)
196         {
197             //转url格式
198             string str = ToUrl();
199             //Functions.Write("转url格式str" + str);
200             //在string后加入API KEY
201             str += "&key=" + key;
202             //MD5加密
203             var md5 = MD5.Create();
204             var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
205             var sb = new StringBuilder();
206             foreach (byte b in bs)
207             {
208                 sb.Append(b.ToString("x2"));
209             }
210             //所有字符转为大写
211             return sb.ToString().ToUpper();
212         }
213 
214         /**
215         * 
216         * 检测签名是否正确
217         * 正确返回true,错误抛异常
218         */
219         public bool CheckSign(string key)
220         {
221             //如果没有设置签名,则跳过检测
222             if (!IsSet("sign"))
223             {
224                 return true;
225             }
226             //如果设置了签名但是签名为空,则抛异常
227             else if(GetValue("sign") == null || GetValue("sign").ToString() == "")
228             {
229                 throw new WxPayException("WxPayData签名存在但不合法!");
230             }
231 
232             //获取接收到的签名
233             string return_sign = GetValue("sign").ToString();
234 
235             //在本地计算新的签名
236             string cal_sign = MakeSign(key);
237 
238             if (cal_sign == return_sign)
239             {
240                 return true;
241             }
242 
243             throw new WxPayException("WxPayData签名验证错误!");
244         }
245 
246         /**
247         * @获取Dictionary
248         */
249         public SortedDictionary<string, object> GetValues()
250         {
251             return m_values;
252         }
253     }
254 }
Data
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Configuration;
 4 using System.Web;
 5 
 6 namespace Components.Payment.WxPayAPI
 7 {
 8     /**
 9     *     配置账号信息
10     */
11     public class WxPayConfig
12     {
13 
14         //=======【基本信息设置】=====================================
15         /* 微信公众号信息配置
16         * APPID:绑定支付的APPID(必须配置)
17         * MCHID:商户号(必须配置)
18         * KEY:商户支付密钥,参考开户邮件设置(必须配置)
19         * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置)
20         */
21         public const string APPID = "wx7db8888888888888";
22         public const string MCHID = "1234567890";
23         public const string KEY = "";
24         public const string APPSECRET = "";
25 
26         //=======【证书路径设置】===================================== 
27         /* 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要)
28         */
29         public const string SSLCERT_PATH = "cert/apiclient_cert.p12";
30         public const string SSLCERT_PASSWORD = "1234567890";
31 
32 
33 
34         //=======【支付结果通知url】===================================== 
35         /* 支付结果通知回调url,用于商户接收支付结果
36         */
37         public const string NOTIFY_URL = "/Mobile/WXPay/WXPayNotify";
38 
39         //=======【商户系统后台机器IP】===================================== 
40         /* 此参数可手动配置也可在程序中自动获取
41         */
42         public const string IP = "8.8.8.8";
43 
44 
45         //=======【代理服务器设置】===================================
46         /* 默认IP和端口号分别为0.0.0.0和0,此时不开启代理(如有需要才设置)
47         */
48         public const string PROXY_URL = "http://10.152.18.220:8080";
49 
50         //=======【上报信息配置】===================================
51         /* 测速上报等级,0.关闭上报; 1.仅错误时上报; 2.全量上报
52         */
53         public const int REPORT_LEVENL = 1;
54 
55         //=======【日志级别】===================================
56         /* 日志等级,0.不输出日志;1.只输出错误信息; 2.输出错误和正常信息; 3.输出错误信息、正常信息和调试信息
57         */
58         public const int LOG_LEVENL = 0;
59     }
60 }
参数配置

根据以上的帮助类,可以在后台构造APP支付所需要的签名参数,或者生成公众号支付的参数,代码使用示例

 1 /// <summary>
 2         /// 支付宝App支付
 3         /// </summary>
 4         /// <param name="postData"></param>
 5         /// <returns></returns>
 6         public ApiResult AliServicePayMethodToApi(IDictionary<string, string> postData)
 7         {
 8             var res = new ApiResult();
 9             // 从数据库取得部分参数
10             var m_info = GetAliAppPayParamsInfo(true);
11             List<string> ordreNoList = new List<string>();
12             // 参数设置
13             string service = "mobile.securitypay.pay";
14             string out_trade_no = "";
15             string total_fee = "";
16             // 判断是交易号还是订单号
17             if (postData.ContainsKey("out_trade_no"))
18             {
19                 out_trade_no = postData["out_trade_no"];
20                 string orderno = string.Empty;
21                 int order_type = 0;
22                 if (out_trade_no.Contains('_'))
23                 {
24                     orderno = out_trade_no.Split('_')[0].IString();
25                     order_type = out_trade_no.Split('_')[1].IInt();
26                 }
27                 if (order_type == EnumOrderTypeSuffix.交易订单.IInt())
28                 {
29                     OrderTradingModels tradingmodel = UContainer.GetInstanse<IOrderBaseData>().GetOrderTradingInfo(orderno);
30                     if (!tradingmodel.IsEmpty())
31                     {
32                         total_fee = tradingmodel.TotalAmount.IString();
33                     }
34                 }
35                 else if (order_type == EnumOrderTypeSuffix.商品订单.IInt())
36                 {
37                     OrderInfoModels orderModel = UContainer.GetInstanse<IOrderBaseData>().GetOrderInfoByOrderNo(orderno);
38                     if (!orderModel.IsEmpty())
39                     {
40                         total_fee = orderModel.TotalAmount.IString();
41                     }
42                 }
43                 else if (order_type == EnumOrderTypeSuffix.服务订单.IInt())
44                 {
45                     var serviceorderinfo = UContainer.GetInstanse<IServiceOrderBaseData>().GetServiceOrderInfoByOrderNo(orderno);
46                     if (!serviceorderinfo.IsEmpty())
47                     {
48                         total_fee = serviceorderinfo.TotalAmount.IString();
49                     }
50                 }
51             }
52 
53             string notify_url = ConfigurationManager.AppSettings["Domain"] + "/Mobile/Alipay/Notify_Url";
54             string return_url = ConfigurationManager.AppSettings["Domain"] + "/Mobile/Alipay/PaySuccess";
55             string payment_type = "1";
56 
57             Config.Partner = m_info.Partner;
58             Config.Seller_id = m_info.SellerId;
59             Config.Private_key = m_info.RsaPrivate;
60             Config.Public_key = m_info.RsaPublic;
61 
62             //参数签名
63             SortedDictionary<string, string> dicArrayPre = new SortedDictionary<string, string>();
64             dicArrayPre.Add("partner", Config.Partner);
65             dicArrayPre.Add("seller_id", Config.Seller_id);
66             dicArrayPre.Add("out_trade_no", out_trade_no);
67             dicArrayPre.Add("subject", "uyacOrder");
68             dicArrayPre.Add("body", "XXX交易订单");
69             dicArrayPre.Add("total_fee", total_fee);
70             dicArrayPre.Add("notify_url", notify_url);
71             dicArrayPre.Add("service", service);
72             dicArrayPre.Add("payment_type", payment_type);
73             dicArrayPre.Add("_input_charset", Config.Input_charset.ToLower());
74             dicArrayPre.Add("return_url", return_url);
75             dicArrayPre.Add("it_b_pay", "30m");
76 
77             string str = Submit.BuildRequestParaToStringNoEncode(dicArrayPre);
78             if (!str.IsEmpty() && str.ToString() != "")
79             {
80                 res.Result = str;
81                 res.Message = "调用成功";
82                 res.Code = "000";
83             }
84             else
85             {
86                 res.Message = "支付参数有误,请联系商家";
87             }
88             return res;
89         }
APP支付实例
原文地址:https://www.cnblogs.com/HuberyHu/p/5390141.html