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) == "") 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 ///18 /// 保存页面对象,因为要在类的方法中使用Page的Request对象 19 /// 20 //private Page page {get;set;} 21 22 /// 23 /// openid用于调用统一下单接口 24 /// 25 public string openid { get; set; } 26 27 /// 28 /// access_token用于获取收货地址js函数入口参数 29 /// 30 public string access_token { get; set; } 31 32 /// 33 /// 商品金额,用于统一下单 34 /// 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 /// 45 /// 统一下单接口返回结果 46 /// 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 }
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 ///14 /// http连接基础类,负责底层的http通信 15 /// 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 /// 116 /// 处理http GET请求,返回数据 117 /// 118 /// 请求的url地址 119 /// http GET成功后返回的数据,失败抛WebException异常 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 }
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 ///13 /// 微信支付协议接口数据类,所有的API接口通信都依赖这个数据结构, 14 /// 在调用接口之前先填充各个字段的值,然后进行接口通信, 15 /// 这样设计的好处是可扩展性强,用户可随意对协议进行更改而不用重新设计数据结构, 16 /// 还可以随意组合出不同的协议数据包,不用为每个协议设计一个数据包结构 17 /// 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 = " "; 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 + ">" + "" + pair.Key + ">"; 99 } 100 else//除了string和int类型不能含有其他数据类型 101 { 102 throw new WxPayException("WxPayData字段数据类型错误!"); 103 } 104 } 105 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;//获取到根节点 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}
", 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 }
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 ///2 /// 支付宝App支付 3 /// 4 /// 5 /// 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 ().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 ().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 ().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 }