You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
7.2 KiB

  1. using System.Web;
  2. using System.Text;
  3. using System.IO;
  4. using System.Net;
  5. using System;
  6. using System.Collections.Generic;
  7. namespace Com.Alipay
  8. {
  9. /// <summary>
  10. /// 类名:Notify
  11. /// 功能:支付宝通知处理类
  12. /// 详细:处理支付宝各接口通知返回
  13. /// 版本:3.3
  14. /// 修改日期:2011-07-05
  15. /// '说明:
  16. /// 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
  17. /// 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
  18. ///
  19. /// //////////////////////注意/////////////////////////////
  20. /// 调试通知返回时,可查看或改写log日志的写入TXT里的数据,来检查通知返回是否正常
  21. /// </summary>
  22. public class Notify
  23. {
  24. #region 字段
  25. private string _partner = ""; //合作身份者ID
  26. private string _key = ""; //商户的私钥
  27. private string _input_charset = ""; //编码格式
  28. private string _sign_type = ""; //签名方式
  29. //支付宝消息验证地址
  30. private string Https_veryfy_url = "https://mapi.alipay.com/gateway.do?service=notify_verify&";
  31. #endregion
  32. /// <summary>
  33. /// 构造函数
  34. /// 从配置文件中初始化变量
  35. /// </summary>
  36. /// <param name="inputPara">通知返回参数数组</param>
  37. /// <param name="notify_id">通知验证ID</param>
  38. public Notify()
  39. {
  40. Basic.BLL.siteconfig bll = new Basic.BLL.siteconfig();
  41. Basic.Model.siteconfig model = bll.loadConfig(Basic.Tools.Utils.GetXmlMapPath(Basic.Keys.FILE_SITE_XML_CONFING));
  42. //初始化基础配置信息
  43. _partner = model.Alipay_partner;
  44. _key = model.Alipay_key;
  45. _input_charset = Config.Input_charset.Trim().ToLower();
  46. _sign_type = Config.Sign_type.Trim().ToUpper();
  47. }
  48. /// <summary>
  49. /// 验证消息是否是支付宝发出的合法消息
  50. /// </summary>
  51. /// <param name="inputPara">通知返回参数数组</param>
  52. /// <param name="notify_id">通知验证ID</param>
  53. /// <param name="sign">支付宝生成的签名结果</param>
  54. /// <returns>验证结果</returns>
  55. public bool Verify(SortedDictionary<string, string> inputPara, string notify_id, string sign)
  56. {
  57. //获取返回时的签名验证结果
  58. bool isSign = GetSignVeryfy(inputPara, sign);
  59. //获取是否是支付宝服务器发来的请求的验证结果
  60. string responseTxt = "true";
  61. if (notify_id != null && notify_id != "") { responseTxt = GetResponseTxt(notify_id); }
  62. //写日志记录(若要调试,请取消下面两行注释)
  63. //string sWord = "responseTxt=" + responseTxt + "\n isSign=" + isSign.ToString() + "\n 返回回来的参数:" + GetPreSignStr(inputPara) + "\n ";
  64. //Core.LogResult(sWord);
  65. //判断responsetTxt是否为true,isSign是否为true
  66. //responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关
  67. //isSign不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
  68. if (responseTxt == "true" && isSign)//验证成功
  69. {
  70. return true;
  71. }
  72. else//验证失败
  73. {
  74. return false;
  75. }
  76. }
  77. /// <summary>
  78. /// 获取待签名字符串(调试用)
  79. /// </summary>
  80. /// <param name="inputPara">通知返回参数数组</param>
  81. /// <returns>待签名字符串</returns>
  82. private string GetPreSignStr(SortedDictionary<string, string> inputPara)
  83. {
  84. Dictionary<string, string> sPara = new Dictionary<string, string>();
  85. //过滤空值、sign与sign_type参数
  86. sPara = Core.FilterPara(inputPara);
  87. //获取待签名字符串
  88. string preSignStr = Core.CreateLinkString(sPara);
  89. return preSignStr;
  90. }
  91. /// <summary>
  92. /// 获取返回时的签名验证结果
  93. /// </summary>
  94. /// <param name="inputPara">通知返回参数数组</param>
  95. /// <param name="sign">对比的签名结果</param>
  96. /// <returns>签名验证结果</returns>
  97. private bool GetSignVeryfy(SortedDictionary<string, string> inputPara, string sign)
  98. {
  99. Dictionary<string, string> sPara = new Dictionary<string, string>();
  100. //过滤空值、sign与sign_type参数
  101. sPara = Core.FilterPara(inputPara);
  102. //获取待签名字符串
  103. string preSignStr = Core.CreateLinkString(sPara);
  104. //获得签名验证结果
  105. bool isSgin = false;
  106. if (sign != null && sign != "")
  107. {
  108. switch (_sign_type)
  109. {
  110. case "MD5":
  111. isSgin = AlipayMD5.Verify(preSignStr, sign, _key, _input_charset);
  112. break;
  113. default:
  114. break;
  115. }
  116. }
  117. return isSgin;
  118. }
  119. /// <summary>
  120. /// 获取是否是支付宝服务器发来的请求的验证结果
  121. /// </summary>
  122. /// <param name="notify_id">通知验证ID</param>
  123. /// <returns>验证结果</returns>
  124. private string GetResponseTxt(string notify_id)
  125. {
  126. string veryfy_url = Https_veryfy_url + "partner=" + _partner + "&notify_id=" + notify_id;
  127. //获取远程服务器ATN结果,验证是否是支付宝服务器发来的请求
  128. string responseTxt = Get_Http(veryfy_url, 120000);
  129. return responseTxt;
  130. }
  131. /// <summary>
  132. /// 获取远程服务器ATN结果
  133. /// </summary>
  134. /// <param name="strUrl">指定URL路径地址</param>
  135. /// <param name="timeout">超时时间设置</param>
  136. /// <returns>服务器ATN结果</returns>
  137. private string Get_Http(string strUrl, int timeout)
  138. {
  139. string strResult;
  140. try
  141. {
  142. HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(strUrl);
  143. myReq.Timeout = timeout;
  144. HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();
  145. Stream myStream = HttpWResp.GetResponseStream();
  146. StreamReader sr = new StreamReader(myStream, Encoding.Default);
  147. StringBuilder strBuilder = new StringBuilder();
  148. while (-1 != sr.Peek())
  149. {
  150. strBuilder.Append(sr.ReadLine());
  151. }
  152. strResult = strBuilder.ToString();
  153. }
  154. catch (Exception exp)
  155. {
  156. strResult = "错误:" + exp.Message;
  157. }
  158. return strResult;
  159. }
  160. }
  161. }