微信公众号支付.net版
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Xml; 6 7 namespace Common 8 { 9 public class TenpayUtil 10 { 11 /// <summary> 12 /// 统一支付接口 13 /// </summary> 14 const string UnifiedPayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; 15 16 /// <summary> 17 /// 网页授权接口 18 /// </summary> 19 const string access_tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token"; 20 21 /// <summary> 22 /// 微信订单查询接口 23 /// </summary> 24 const string OrderQueryUrl = "https://api.mch.weixin.qq.com/pay/orderquery"; 25 26 /// <summary> 27 /// 随机串 28 /// </summary> 29 public static string getNoncestr() 30 { 31 Random random = new Random(); 32 return MD5Util.GetMD5(random.Next(1000).ToString(), "GBK").ToLower().Replace("s", "S"); 33 } 34 35 /// <summary> 36 /// 时间截,自1970年以来的秒数 37 /// </summary> 38 public static string getTimestamp() 39 { 40 TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); 41 return Convert.ToInt64(ts.TotalSeconds).ToString(); 42 } 43 44 /// <summary> 45 /// 网页授权接口 46 /// </summary> 47 public static string getAccess_tokenUrl() 48 { 49 return access_tokenUrl; 50 } 51 52 /// <summary> 53 /// 获取微信签名 54 /// </summary> 55 /// <param name="sParams"></param> 56 /// <returns></returns> 57 public string getsign(SortedDictionary<string, string> sParams, string key) 58 { 59 int i = 0; 60 string sign = string.Empty; 61 StringBuilder sb = new StringBuilder(); 62 foreach (KeyValuePair<string, string> temp in sParams.Reverse().Reverse()) 63 { 64 if (temp.Value == "" || temp.Value == null || temp.Key.ToLower() == "sign") 65 { 66 continue; 67 } 68 i++; 69 sb.Append(temp.Key.Trim() + "=" + temp.Value.Trim() + "&"); 70 } 71 sb.Append("key=" + key.Trim() + ""); 72 string signkey = sb.ToString(); 73 74 Logger.WriteAppLog("signkey:" + signkey); 75 sign = MD5Util.GetMD5(signkey, "utf-8").ToUpper(); 76 77 78 return sign; 79 } 80 81 82 /// <summary> 83 /// 获取微信签名 84 /// </summary> 85 /// <param name="sParams"></param> 86 /// <returns></returns> 87 public string getpaySign(SortedDictionary<string, string> sParams, string key) 88 { 89 int i = 0; 90 string sign = string.Empty; 91 StringBuilder sb = new StringBuilder(); 92 foreach (KeyValuePair<string, string> temp in sParams.Reverse().Reverse()) 93 { 94 if (temp.Value == "" || temp.Value == null || temp.Key.ToLower() == "paySign") 95 { 96 continue; 97 } 98 i++; 99 sb.Append(temp.Key.Trim() + "=" + temp.Value.Trim() + "&"); 100 } 101 sb.Append("key=" + key.Trim() + ""); 102 string signkey = sb.ToString(); 103 104 Logger.WriteAppLog("paySign:" + signkey); 105 sign = MD5Util.GetMD5(signkey, "utf-8").ToUpper(); 106 107 108 return sign; 109 } 110 111 /// <summary> 112 /// post数据到指定接口并返回数据 113 /// </summary> 114 public string PostXmlToUrl(string url, string postData) 115 { 116 string returnmsg = ""; 117 118 Logger.WriteAppLog("postData:" + postData); 119 using (System.Net.WebClient wc = new System.Net.WebClient()) 120 { 121 wc.Encoding = System.Text.Encoding.UTF8;//定义对象语言 122 returnmsg = wc.UploadString(url, "POST", postData); 123 } 124 return returnmsg; 125 } 126 127 /// <summary> 128 /// 获取prepay_id 129 /// </summary> 130 public string getPrepay_id(UnifiedOrder order, string key) 131 { 132 string prepay_id = ""; 133 string post_data = getUnifiedOrderXml(order, key); 134 string request_data = PostXmlToUrl(UnifiedPayUrl, post_data); 135 136 137 Logger.WriteAppLog("getPrepay_id :" + request_data); 138 SortedDictionary<string, string> requestXML = GetInfoFromXml(request_data); 139 foreach (KeyValuePair<string, string> k in requestXML) 140 { 141 if (k.Key == "prepay_id") 142 { 143 prepay_id = k.Value; 144 break; 145 } 146 } 147 return prepay_id; 148 } 149 150 /// <summary> 151 /// 获取微信订单明细 152 /// </summary> 153 public OrderDetail getOrderDetail(QueryOrder queryorder, string key) 154 { 155 string post_data = getQueryOrderXml(queryorder, key); 156 string request_data = PostXmlToUrl(OrderQueryUrl, post_data); 157 OrderDetail orderdetail = new OrderDetail(); 158 SortedDictionary<string, string> requestXML = GetInfoFromXml(request_data); 159 foreach (KeyValuePair<string, string> k in requestXML) 160 { 161 switch (k.Key) 162 { 163 case "retuen_code": 164 orderdetail.result_code = k.Value; 165 break; 166 case "return_msg": 167 orderdetail.return_msg = k.Value; 168 break; 169 case "appid": 170 orderdetail.appid = k.Value; 171 break; 172 case "mch_id": 173 orderdetail.mch_id = k.Value; 174 break; 175 case "nonce_str": 176 orderdetail.nonce_str = k.Value; 177 break; 178 case "sign": 179 orderdetail.sign = k.Value; 180 break; 181 case "result_code": 182 orderdetail.result_code = k.Value; 183 break; 184 case "err_code": 185 orderdetail.err_code = k.Value; 186 break; 187 case "err_code_des": 188 orderdetail.err_code_des = k.Value; 189 break; 190 case "trade_state": 191 orderdetail.trade_state = k.Value; 192 break; 193 case "device_info": 194 orderdetail.device_info = k.Value; 195 break; 196 case "openid": 197 orderdetail.openid = k.Value; 198 break; 199 case "is_subscribe": 200 orderdetail.is_subscribe = k.Value; 201 break; 202 case "trade_type": 203 orderdetail.trade_type = k.Value; 204 break; 205 case "bank_type": 206 orderdetail.bank_type = k.Value; 207 break; 208 case "total_fee": 209 orderdetail.total_fee = k.Value; 210 break; 211 case "coupon_fee": 212 orderdetail.coupon_fee = k.Value; 213 break; 214 case "fee_type": 215 orderdetail.fee_type = k.Value; 216 break; 217 case "transaction_id": 218 orderdetail.transaction_id = k.Value; 219 break; 220 case "out_trade_no": 221 orderdetail.out_trade_no = k.Value; 222 break; 223 case "attach": 224 orderdetail.attach = k.Value; 225 break; 226 case "time_end": 227 orderdetail.time_end = k.Value; 228 break; 229 default: 230 break; 231 } 232 } 233 return orderdetail; 234 } 235 236 /// <summary> 237 /// 把XML数据转换为SortedDictionary<string, string>集合 238 /// </summary> 239 /// <param name="strxml"></param> 240 /// <returns></returns> 241 protected SortedDictionary<string, string> GetInfoFromXml(string xmlstring) 242 { 243 SortedDictionary<string, string> sParams = new SortedDictionary<string, string>(); 244 try 245 { 246 XmlDocument doc = new XmlDocument(); 247 doc.LoadXml(xmlstring); 248 XmlElement root = doc.DocumentElement; 249 int len = root.ChildNodes.Count; 250 for (int i = 0; i < len; i++) 251 { 252 string name = root.ChildNodes[i].Name; 253 if (!sParams.ContainsKey(name)) 254 { 255 sParams.Add(name.Trim(), root.ChildNodes[i].InnerText.Trim()); 256 } 257 } 258 } 259 catch { } 260 return sParams; 261 } 262 263 /// <summary> 264 /// 微信统一下单接口xml参数整理 265 /// </summary> 266 /// <param name="order">微信支付参数实例</param> 267 /// <param name="key">密钥</param> 268 /// <returns></returns> 269 protected string getUnifiedOrderXml(UnifiedOrder order, string key) 270 { 271 string return_string = string.Empty; 272 SortedDictionary<string, string> sParams = new SortedDictionary<string, string>(); 273 sParams.Add("appid", order.appid); 274 sParams.Add("mch_id", order.mch_id); 275 sParams.Add("nonce_str", order.nonce_str); 276 277 //SortedDictionary<string, string> singparams = new SortedDictionary<string, string>(); 278 //singparams.Add("appid", order.appid); 279 //singparams.Add("body", order.body); 280 //singparams.Add("device_info", order.device_info); 281 //singparams.Add("mch_id", order.mch_id); 282 //singparams.Add("nonce_str", order.nonce_str); 283 284 285 286 287 288 // sParams.Add("sign", order.sign); 289 sParams.Add("body", order.body); 290 sParams.Add("out_trade_no", order.out_trade_no); 291 sParams.Add("total_fee", order.total_fee.ToString()); 292 sParams.Add("spbill_create_ip", order.spbill_create_ip); 293 sParams.Add("notify_url", order.notify_url); 294 sParams.Add("trade_type", order.trade_type); 295 sParams.Add("openid", order.openid); 296 sParams.Add("device_info", order.device_info); 297 298 299 // sParams.Add("attach", order.attach); 300 301 //sParams.Add("device_info", order.device_info); 302 303 //sParams.Add("nonce_str", order.nonce_str); 304 305 306 307 string sign = getsign(sParams, key); 308 309 Logger.WriteAppLog("签名:" + sign); 310 311 order.sign = sign; 312 313 314 sParams.Add("sign", order.sign); 315 316 317 318 //拼接成XML请求数据 319 StringBuilder sbPay = new StringBuilder(); 320 321 foreach (KeyValuePair<string, string> k in sParams.Reverse().Reverse()) 322 { 323 //if (k.Key == "attach" || k.Key == "body" || k.Key == "sign") 324 //{ 325 // sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">"); 326 //} 327 //else 328 //{ 329 // sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">"); 330 // } 331 332 333 if (k.Key == "sign") 334 { 335 sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">"); 336 } 337 else 338 { 339 sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">"); 340 } 341 } 342 return_string = string.Format("<xml>{0}</xml>", sbPay.ToString()); 343 byte[] byteArray = Encoding.UTF8.GetBytes(return_string); 344 return_string = Encoding.GetEncoding("UTF-8").GetString(byteArray); 345 346 Logger.WriteAppLog("拼接成XML请求数据:" + return_string); 347 return return_string; 348 349 } 350 351 /// <summary> 352 /// 微信订单查询接口XML参数整理 353 /// </summary> 354 /// <param name="queryorder">微信订单查询参数实例</param> 355 /// <param name="key">密钥</param> 356 /// <returns></returns> 357 protected string getQueryOrderXml(QueryOrder queryorder, string key) 358 { 359 string return_string = string.Empty; 360 SortedDictionary<string, string> sParams = new SortedDictionary<string, string>(); 361 sParams.Add("appid", queryorder.appid); 362 sParams.Add("mch_id", queryorder.mch_id); 363 sParams.Add("transaction_id", queryorder.transaction_id); 364 sParams.Add("out_trade_no", queryorder.out_trade_no); 365 sParams.Add("nonce_str", queryorder.nonce_str); 366 queryorder.sign = getsign(sParams, key); 367 sParams.Add("sign", queryorder.sign); 368 369 //拼接成XML请求数据 370 StringBuilder sbPay = new StringBuilder(); 371 foreach (KeyValuePair<string, string> k in sParams) 372 { 373 if (k.Key == "attach" || k.Key == "body" || k.Key == "sign") 374 { 375 sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">"); 376 } 377 else 378 { 379 sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">"); 380 } 381 } 382 return_string = string.Format("<xml>{0}</xml>", sbPay.ToString().TrimEnd(',')); 383 return return_string; 384 } 385 } 386 }