zoukankan      html  css  js  c++  java
  • 微信支付帮助类

      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支付实例
  • 相关阅读:
    pwd命令
    python-windows环境安装
    python介绍
    elk安装
    elk介绍
    111
    使用CEF作为用户界面
    使用CEF作为浏览器
    c# 内嵌chrome(Webkit)
    待搞清楚
  • 原文地址:https://www.cnblogs.com/HuberyHu/p/5390141.html
Copyright © 2011-2022 走看看