支付宝支付

对支付宝支付的二次封装,支持pc端和wap端支付

类图

 

pay(pc):

  •  
    var orderNo = ""; //订单号
  • var subject = ""; //订单名称
  • var fee = 0.ToString("0.##"); //付款金额
  • var notifyUrl = "host/Alipay/NotifyUrl.aspx";
  • var returnUrl = "host/Alipay/ReturnUrl.aspx";
  • var show_url = "host";
  • var alipay = new Alipay.Submit();
  • alipay.Pay(orderNo, subject, fee, body, notify_url, return_url, show_url);

 

pay(wap):

 

var orderNo = ""; //订单号

var title = "在线捐赠(WAP):" + ""; //订单名称

var fee = 0.ToString("0.##"); //付款金额

var notifyUrl = "host/Alipay/NotifyUrl.aspx";

var returnUrl = "host/Alipay/ReturnUrl.aspx";

var show_url = "host";

var alipay = new Alipay.Submit();

alipay.Submit.Pay(orderNo, subject, fee, body, notify_url, return_url, show_url);

  1. return(pc):

public partial class NotifyUrl : Alipay.NotifyPage

{

   protected override void OnNotifyConfirm()

  {

       //todo:业务逻辑处理

  }

}

 

  1. return(wap): 

public partial class NotifyUrl : Alipay.Wap.NotifyPage

{

protected override void OnNotifyConfirm()

{

//todo:业务逻辑处理

}

}

 

  1. PC端的Submit.cs

using System.Text;

 

using System.IO;

 

using System.Net;

 

using System;

 

using System.Collections.Generic;

 

using System.Web;

 

using System.Xml;

 

namespace Alipay

 

{

 

/// <summary>

 

/// 支付宝各接口请求提交类

 

/// 构造支付宝各接口表单HTML文本,获取远程HTTP数据

 

/// </summary>

 

public class Submit

 

{

 

public Submit()

 

{

 

}

 

/// <summary>

 

/// 实例化

 

/// </summary>

 

/// <param name="partner">合作者身份ID</param>

 

/// <param name="key">交易安全校验码</param>

 

/// <param name="sellerMail">卖方(收款方)支付宝账户</param>

 

public Submit(string partner, string key, string sellerMail)

 

{

 

Config.Partner = partner;

 

Config.Key = key;

 

Config.SellerEmail = sellerMail;

 

}

 

/// <summary>

 

/// 提交支付请求,get

 

/// </summary>

 

/// <param name="orderNo">商户订单号</param>

 

/// <param name="fee">付款金额</param>

 

/// <param name="title">订单名称</param>

 

/// <param name="desc">订单描述</param>

 

/// <param name="notifyUrl">服务器异步通知页面路径</param>

 

/// <param name="returnUrl">页面跳转同步通知页面路径</param>

 

/// <param name="showUrl">商品展示地址</param>

 

public void Pay(string orderNo, string fee, string title, string desc, string notifyUrl,

 

string returnUrl, string showUrl)

 

{

 

var para = new SortedDictionary<string, string>

 

{

 

{"partner", Config.Partner},

 

{"_input_charset", Config._Charset.ToLower()},

 

{"service", Config._PayMode},

 

{"payment_type", Config._PayType},

 

{"notify_url", notifyUrl},

 

{"return_url", returnUrl},

 

{"seller_email", Config.SellerEmail},

 

{"out_trade_no", orderNo},

 

{"subject", title},

 

{"total_fee", fee},

 

{"body", desc},

 

{"show_url", showUrl},

 

{"anti_phishing_key", _GetDateTimeString()}

 

};

 

var dicPara = BuildRequestPara(para);

 

var sbHtml = new StringBuilder();

 

sbHtml.AppendFormat(

 

"<form id='alipaysubmit' name='alipaysubmit' action='{0}_input_charset={1}' method='get'>",

 

Config._GateWay, Config._Charset);

 

foreach (var temp in dicPara)

 

{

 

sbHtml.AppendFormat("<input type='hidden' name='{0}' value='{1}'/>", temp.Key, temp.Value);

 

}

 

//submit按钮控件请不要含有name属性

 

sbHtml.Append("<input type='submit' value='支付' style='display:none;'></form>");

 

sbHtml.Append("<script>document.forms['alipaysubmit'].submit();</script>");

 

HttpContext.Current.Response.Write(sbHtml.ToString());

 

}

 

/// <summary>

 

/// 提交支付请求,post

 

/// </summary>

 

/// <param name="notifyUrl">服务器异步通知页面路径</param>

 

/// <param name="returnUrl">页面跳转同步通知页面路径</param>

 

/// <param name="sellerEmail">卖家支付宝帐户</param>

 

/// <param name="orderNo">商户订单号</param>

 

/// <param name="subject">订单名称</param>

 

/// <param name="fee">付款金额</param>

 

/// <param name="title">订单描述</param>

 

/// <param name="showUrl">商品展示地址</param>

 

public void PostPay(string notifyUrl, string returnUrl, string sellerEmail, string orderNo, string subject

 

, string fee, string title, string showUrl)

 

{

 

var para = new SortedDictionary<string, string>

 

{

 

{"partner", Config.Partner},

 

{"_input_charset", Config._Charset.ToLower()},

 

{"service", Config._PayMode},

 

{"payment_type", Config._PayType},

 

{"notify_url", notifyUrl},

 

{"return_url", returnUrl},

 

{"seller_email", sellerEmail},

 

{"out_trade_no", orderNo},

 

{"subject", subject},

 

{"total_fee", fee},

 

{"body", title},

 

{"show_url", showUrl},

 

{"anti_phishing_key", _GetDateTimeString()}

 

};

 

var encoding = Encoding.GetEncoding(Config._Charset);

 

var strRequestData = BuildRequestParaToString(para, encoding);

 

var bytesRequestData = encoding.GetBytes(strRequestData);

 

var strUrl = string.Format("{0}_input_charset={1}", Config._GateWay, Config._Charset);

 

string strResult;

 

try

 

{

 

var myReq = (HttpWebRequest)WebRequest.Create(strUrl);

 

myReq.Method = "post";

 

myReq.ContentType = "application/x-www-form-urlencoded";

 

myReq.ContentLength = bytesRequestData.Length;

 

var requestStream = myReq.GetRequestStream();

 

requestStream.Write(bytesRequestData, 0, bytesRequestData.Length);

 

requestStream.Close();

 

var HttpWResp = (HttpWebResponse)myReq.GetResponse();

 

var myStream = HttpWResp.GetResponseStream();

 

var reader = new StreamReader(myStream, encoding);

 

var responseData = new StringBuilder();

 

string line;

 

while ((line = reader.ReadLine()) != null)

 

{

 

responseData.Append(line);

 

}

 

myStream.Close();

 

strResult = responseData.ToString();

 

}

 

catch (Exception ex)

 

{

 

strResult = "报错:" + ex.Message;

 

}

 

HttpContext.Current.Response.Write(strResult);

 

}

 

/// <summary>

 

/// 生成请求时的签名

 

/// </summary>

 

internal string BuildRequestMysign(Dictionary<string, string> sPara)

 

{

 

return MD5.Sign(Core.CreateLinkString(sPara), Config.Key, Config._Charset);

 

}

 

/// <summary>

 

/// 生成要请求给支付宝的参数数组

 

/// </summary>

 

internal Dictionary<string, string> BuildRequestPara(SortedDictionary<string, string> sParaTemp)

 

{

 

var sPara = Core.FilterPara(sParaTemp);

 

var mysign = BuildRequestMysign(sPara);

 

sPara.Add("sign", mysign);

 

sPara.Add("sign_type", Config._SignType);

 

return sPara;

 

}

 

/// <summary>

 

/// 用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数

 

/// 注意:远程解析XML出错,与IIS服务器配置有关

 

/// </summary>

 

/// <returns>时间戳字符串</returns>

 

private string _GetDateTimeString()

 

{

 

var url = string.Format("{0}service=query_timestamp&partner={1}", Config._GateWay, Config.Partner);

 

var Reader = new XmlTextReader(url);

 

var xmlDoc = new XmlDocument();

 

xmlDoc.Load(Reader);

 

return xmlDoc.SelectSingleNode("/alipay/response/timestamp/encrypt_key").InnerText;

 

}

 

/// <summary>

 

/// 生成要请求给支付宝的参数数组

 

/// </summary>

 

internal string BuildRequestParaToString(SortedDictionary<string, string> sParaTemp, Encoding code)

 

{

 

return Core.CreateLinkStringUrlencode(BuildRequestPara(sParaTemp), code);

 

}

 

/*

 

/// <summary>

 

/// 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果,带文件上传功能

 

/// </summary>

 

/// <param name="sParaTemp">请求参数数组</param>

 

/// <param name="strMethod">提交方式。两个值可选:post、get</param>

 

/// <param name="fileName">文件绝对路径</param>

 

/// <param name="data">文件数据</param>

 

/// <param name="contentType">文件内容类型</param>

 

/// <param name="lengthFile">文件长度</param>

 

/// <returns>支付宝处理结果</returns>

 

internal static string BuildRequest(SortedDictionary<string, string> sParaTemp, string strMethod, string fileName, byte[] data, string contentType, int lengthFile)

 

{

 

//待请求参数数组

 

Dictionary<string, string> dicPara = new Dictionary<string, string>();

 

dicPara = BuildRequestPara(sParaTemp);

 

//构造请求地址

 

string strUrl = Config._GateWay + "_input_charset=" + Config._Charset;

 

//设置HttpWebRequest基本信息

 

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(strUrl);

 

//设置请求方式:get、post

 

request.Method = strMethod;

 

//设置boundaryValue

 

string boundaryValue = DateTime.Now.Ticks.ToString("x");

 

string boundary = "--" + boundaryValue;

 

request.ContentType = "\r\nmultipart/form-data; boundary=" + boundaryValue;

 

//设置KeepAlive

 

request.KeepAlive = true;

 

//设置请求数据,拼接成字符串

 

StringBuilder sbHtml = new StringBuilder();

 

foreach (KeyValuePair<string, string> key in dicPara)

 

{

 

sbHtml.Append(boundary + "\r\nContent-Disposition: form-data; name=\"" + key.Key + "\"\r\n\r\n" + key.Value + "\r\n");

 

}

 

sbHtml.Append(boundary + "\r\nContent-Disposition: form-data; name=\"withhold_file\"; filename=\"");

 

sbHtml.Append(fileName);

 

sbHtml.Append("\"\r\nContent-Type: " + contentType + "\r\n\r\n");

 

string postHeader = sbHtml.ToString();

 

//将请求数据字符串类型根据编码格式转换成字节流

 

Encoding code = Encoding.GetEncoding(Config._Charset);

 

byte[] postHeaderBytes = code.GetBytes(postHeader);

 

byte[] boundayBytes = Encoding.ASCII.GetBytes("\r\n" + boundary + "--\r\n");

 

//设置长度

 

long length = postHeaderBytes.Length + lengthFile + boundayBytes.Length;

 

request.ContentLength = length;

 

//请求远程HTTP

 

Stream requestStream = request.GetRequestStream();

 

Stream myStream;

 

try

 

{

 

//发送数据请求服务器

 

requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);

 

requestStream.Write(data, 0, lengthFile);

 

requestStream.Write(boundayBytes, 0, boundayBytes.Length);

 

HttpWebResponse HttpWResp = (HttpWebResponse)request.GetResponse();

 

myStream = HttpWResp.GetResponseStream();

 

}

 

catch (WebException e)

 

{

 

return e.ToString();

 

}

 

finally

 

{

 

if (requestStream != null)

 

{

 

requestStream.Close();

 

}

 

}

 

//读取支付宝返回处理结果

 

StreamReader reader = new StreamReader(myStream, code);

 

StringBuilder responseData = new StringBuilder();

 

String line;

 

while ((line = reader.ReadLine()) != null)

 

{

 

responseData.Append(line);

 

}

 

myStream.Close();

 

return responseData.ToString();

 

}

 

*/

 

}

 

}

wap端的Submit.cs

 

  1.  
    using System.Text;
  2. using System.IO;
  3. using System.Net;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Web;
  7. using System.Xml;
  8. namespace Alipay.Wap
  9. {
  10. /// <summary>
  11. /// 支付宝各接口请求提交类
  12. /// 构造支付宝各接口表单HTML文本,获取远程HTTP数据
  13. /// </summary>
  14. public class Submit
  15. {
  16. public Submit()
  17. {
  18. }
  19. /// <summary>
  20. /// 实例化
  21. /// </summary>
  22. /// <param name="partner">合作者身份ID</param>
  23. /// <param name="key">交易安全校验码</param>
  24. /// <param name="sellerMail">卖方(收款方)支付宝账户</param>
  25. public Submit(string partner, string key, string sellerMail)
  26. {
  27. Config.Partner = partner;
  28. Config.Key = key;
  29. Config.SellerEmail = sellerMail;
  30. }
  31. /// <summary>
  32. /// 提交支付请求,get
  33. /// </summary>
  34. /// <param name="orderNo">商户订单号</param>
  35. /// <param name="fee">付款金额</param>
  36. /// <param name="title">订单名称</param>
  37. /// <param name="desc">订单描述</param>
  38. /// <param name="notifyUrl">服务器异步通知页面路径</param>
  39. /// <param name="returnUrl">页面跳转同步通知页面路径</param>
  40. /// <param name="showUrl">商品展示地址</param>
  41. public void Pay(string orderNo, string fee, string title, string desc, string notifyUrl,
  42. string returnUrl, string showUrl)
  43. {
  44. var req_id = DateTime.Now.ToString("yyyyMMddHHmmssfff"); //请求号,须保证每次请求都是唯一
  45. const string format = "xml";
  46. const string v = "2.0";
  47. if (string.IsNullOrEmpty(fee)) fee = "0";
  48. if (string.IsNullOrEmpty(title)) title = "在线捐赠(WAP)";
  49. if (string.IsNullOrEmpty(orderNo)) orderNo = req_id;
  50. var req_dataToken =
  51. string.Format(
  52. "<direct_trade_create_req><notify_url>{0}</notify_url><call_back_url>{1}</call_back_url><seller_account_name>{2}</seller_account_name><out_trade_no>{3}</out_trade_no><subject>{4}</subject><total_fee>{5}</total_fee><merchant_url>{6}</merchant_url></direct_trade_create_req>",
  53. notifyUrl, returnUrl, Config.SellerEmail, orderNo, title, fee, showUrl);
  54. //创建支付宝交易订单,并获取授权码token,alipay.wap.trade.create.direct
  55. var sParaTempToken = new SortedDictionary<string, string>();
  56. sParaTempToken.Add("partner", Config.Partner);
  57. sParaTempToken.Add("_input_charset", Config._Charset.ToLower());
  58. sParaTempToken.Add("sec_id", Config._SignType.ToUpper());
  59. sParaTempToken.Add("service", "alipay.wap.trade.create.direct");
  60. sParaTempToken.Add("format", format);
  61. sParaTempToken.Add("v", v);
  62. sParaTempToken.Add("req_id", req_id);
  63. sParaTempToken.Add("req_data", req_dataToken);
  64. var sHtmlTextToken = BuildRequest(Config._GateWayWap, sParaTempToken);
  65. var code = Encoding.GetEncoding(Config._Charset);
  66. sHtmlTextToken = HttpUtility.UrlDecode(sHtmlTextToken, code);
  67. var dicHtmlTextToken = ParseResponse(sHtmlTextToken);
  68. var request_token = dicHtmlTextToken["request_token"];
  69. //根据授权码token调用交易接口alipay.wap.auth.authAndExecute
  70. var req_data = string.Format("<auth_and_execute_req><request_token>{0}</request_token></auth_and_execute_req>", request_token);
  71. var sParaTemp = new SortedDictionary<string, string>
  72. {
  73. {"partner", Config.Partner},
  74. {"_input_charset", Config._Charset.ToLower()},
  75. {"sec_id", Config._SignType.ToUpper()},
  76. {"service", "alipay.wap.auth.authAndExecute"},
  77. {"format", format},
  78. {"v", v},
  79. {"req_data", req_data}
  80. };
  81. var sHtmlText = BuildRequest(Config._GateWayWap, sParaTemp, "get", "确认");
  82. HttpContext.Current.Response.Write(sHtmlText);
  83. }
  84. /// <summary>
  85. /// 建立请求,以表单HTML形式构造(默认)
  86. /// </summary>
  87. /// <param name="GATEWAY_NEW">支付宝网关地址</param>
  88. /// <param name="sParaTemp">请求参数数组</param>
  89. /// <param name="strMethod">提交方式。两个值可选:post、get</param>
  90. /// <param name="strButtonValue">确认按钮显示文字</param>
  91. /// <returns>提交表单HTML文本</returns>
  92. private string BuildRequest(string GATEWAY_NEW, SortedDictionary<string, string> sParaTemp, string strMethod, string strButtonValue)
  93. {
  94. var dicPara = BuildRequestPara(sParaTemp);
  95. var sbHtml = new StringBuilder();
  96. sbHtml.Append("<form id='alipaysubmit' name='alipaysubmit' action='" + GATEWAY_NEW + "_input_charset=" + Config._Charset + "' method='" + strMethod.ToLower().Trim() + "'>");
  97. foreach (var temp in dicPara)
  98. {
  99. sbHtml.Append("<input type='hidden' name='" + temp.Key + "' value='" + temp.Value + "'/>");
  100. }
  101. //submit按钮控件请不要含有name属性
  102. sbHtml.Append("<input type='submit' value='" + strButtonValue + "' style='display:none;'></form>");
  103. sbHtml.Append("<script>document.forms['alipaysubmit'].submit();</script>");
  104. return sbHtml.ToString();
  105. }
  106. /// <summary>
  107. /// 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果
  108. /// </summary>
  109. /// <param name="gateWayWap">支付宝网关地址</param>
  110. /// <param name="sParaTemp">请求参数数组</param>
  111. /// <returns>支付宝处理结果</returns>
  112. private string BuildRequest(string gateWayWap, SortedDictionary<string, string> sParaTemp)
  113. {
  114. var code = Encoding.GetEncoding(Config._Charset);
  115. var strRequestData = BuildRequestParaToString(sParaTemp,code);
  116. var bytesRequestData = code.GetBytes(strRequestData);
  117. var strUrl = string.Format("{0}_input_charset={1}", gateWayWap, Config._Charset);
  118. string strResult;
  119. try
  120. {
  121. var myReq = (HttpWebRequest)WebRequest.Create(strUrl);
  122. myReq.Method = "post";
  123. myReq.ContentType = "application/x-www-form-urlencoded";
  124. myReq.ContentLength = bytesRequestData.Length;
  125. var requestStream = myReq.GetRequestStream();
  126. requestStream.Write(bytesRequestData, 0, bytesRequestData.Length);
  127. requestStream.Close();
  128. var HttpWResp = (HttpWebResponse)myReq.GetResponse();
  129. var myStream = HttpWResp.GetResponseStream();
  130. var reader = new StreamReader(myStream, code);
  131. var responseData = new StringBuilder();
  132. string line;
  133. while ((line = reader.ReadLine()) != null)
  134. {
  135. responseData.Append(line);
  136. }
  137. myStream.Close();
  138. strResult = responseData.ToString();
  139. }
  140. catch (Exception exp)
  141. {
  142. strResult = "报错:"+exp.Message;
  143. }
  144. return strResult;
  145. }
  146. /// <summary>
  147. /// 生成要请求给支付宝的参数数组
  148. /// </summary>
  149. private string BuildRequestParaToString(SortedDictionary<string, string> sParaTemp, Encoding code)
  150. {
  151. return Core.CreateLinkStringUrlencode(BuildRequestPara(sParaTemp), code);
  152. }
  153. /// <summary>
  154. /// 生成要请求给支付宝的参数数组
  155. /// </summary>
  156. private Dictionary<string, string> BuildRequestPara(SortedDictionary<string, string> sParaTemp)
  157. {
  158. var sPara = Core.FilterPara(sParaTemp);
  159. var mysign = MD5.Sign(Core.CreateLinkString(sPara), Config.Key, Config._Charset);
  160. sPara.Add("sign", mysign);
  161. if (sPara["service"] != "alipay.wap.trade.create.direct" && sPara["service"] != "alipay.wap.auth.authAndExecute")
  162. {
  163. sPara.Add("sign_type", Config._SignType);
  164. }
  165. return sPara;
  166. }
  167. /// <summary>
  168. /// 解析远程模拟提交后返回的信息
  169. /// </summary>
  170. /// <param name="strText">要解析的字符串</param>
  171. /// <returns>解析结果</returns>
  172. private Dictionary<string, string> ParseResponse(string strText)
  173. {
  174. var strSplitText = strText.Split('&');
  175. var dicText = new Dictionary<string, string>();
  176. foreach (string text in strSplitText)
  177. {
  178. var nPos = text.IndexOf('=');
  179. dicText.Add(text.Substring(0, nPos), text.Substring(nPos + 1, text.Length - nPos - 1));
  180. }
  181. if (dicText["res_data"] != null)
  182. {
  183. //token从res_data中解析出来(也就是说res_data中已经包含token的内容)
  184. var xmlDoc = new XmlDocument();
  185. try
  186. {
  187. xmlDoc.LoadXml(dicText["res_data"]);
  188. var strRequest_token = xmlDoc.SelectSingleNode("/direct_trade_create_res/request_token").InnerText;
  189. dicText.Add("request_token", strRequest_token);
  190. }
  191. catch (Exception exp)
  192. {
  193. dicText.Add("request_token", exp.ToString());
  194. }
  195. }
  196. return dicText;
  197. }
  198. }
  199. }

 

  1. Config.cs

  2. using System.Configuration;
  3. namespace Alipay
  4. {
  5. /// <summary>
  6. /// 账户配置
  7. /// 1.登录支付宝网站(www.alipay.com)
  8. /// 2.点击“商家服务”(https://b.alipay.com/order/myOrder.htm)
  9. /// 3.点击“查询合作者身份(PID)”、“查询安全校验码(Key)”
  10. /// </summary>
  11. public class Config
  12. {
  13. /// <summary>
  14. /// 合作者身份ID
  15. /// </summary>
  16. public static string Partner{ internal get; set; }
  17. /// <summary>
  18. /// 交易安全校验码
  19. /// </summary>
  20. public static string Key { internal get; set; }
  21. /// <summary>
  22. /// 卖方(收款方)支付宝账户
  23. /// </summary>
  24. public static string SellerEmail { internal get; set; }
  25. /// <summary>
  26. /// 字符编码格式:utf-8
  27. /// </summary>
  28. internal static string _Charset { get { return "utf-8"; } }
  29. /// <summary>
  30. /// 签名方式:MD5
  31. /// </summary>
  32. internal static string _SignType { get { return "MD5"; } }
  33. /// <summary>
  34. /// 支付宝网关地址pc
  35. /// </summary>
  36. internal static string _GateWay { get { return "https://mapi.alipay.com/gateway.do?"; } }
  37. /// <summary>
  38. /// 支付宝网关地址wap
  39. /// </summary>
  40. internal static string _GateWayWap { get { return "http://wappaygw.alipay.com/service/rest.htm?"; } }
  41. /// <summary>
  42. /// 支付宝消息验证地址
  43. /// </summary>
  44. internal static string _VeryfyUrl { get { return "https://mapi.alipay.com/gateway.do?service=notify_verify&"; } }
  45. /// <summary>
  46. /// 交易方式:即时到账交易pc
  47. /// </summary>
  48. internal static string _PayMode { get { return "create_direct_pay_by_user"; } }
  49. /// <summary>
  50. /// 支付类型:1
  51. /// </summary>
  52. internal static string _PayType { get { return "1"; } }
  53. /// <summary>
  54. /// 日志路径:/log/Alipay
  55. /// </summary>
  56. internal static string _LogPath { get { return "/log/Alipay"; } }
  57. /// <summary>
  58. /// 商户的私钥,如果签名方式设置为“0001”时,请设置该参数
  59. /// </summary>
  60. internal static string _PrivateKey { get { return ""; } }
  61. /// <summary>
  62. /// 商户的公钥,如果签名方式设置为“0001”时,请设置该参数
  63. /// </summary>
  64. internal static string _PublicKey { get { return ""; } }
  65. static Config()
  66. {
  67. if (string.IsNullOrEmpty(Partner))
  68. Partner = ConfigurationManager.AppSettings["Alipay.Partner"];
  69. if (string.IsNullOrEmpty(Key))
  70. Key = ConfigurationManager.AppSettings["Alipay.Key"];
  71. if (string.IsNullOrEmpty(SellerEmail))
  72. SellerEmail = ConfigurationManager.AppSettings["Alipay.SellerEmail"];
  73. }
  74. }
  75. }

 

  1. Core.cs

  2. using System.Linq;
  3. using System.Web;
  4. using System.Text;
  5. using System.IO;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Globalization;
  9. namespace Alipay
  10. {
  11. internal class Core
  12. {
  13. /// <summary>
  14. /// 除去数组中的空值和签名参数并以字母a到z的顺序排序
  15. /// </summary>
  16. internal static Dictionary<string, string> FilterPara(SortedDictionary<string, string> dicArrayPre)
  17. {
  18. return
  19. dicArrayPre.Where(
  20. temp =>
  21. temp.Key.ToLower() != "sign" && temp.Key.ToLower() != "sign_type" &&
  22. !string.IsNullOrEmpty(temp.Value)).ToDictionary(temp => temp.Key, temp => temp.Value);
  23. }
  24. /// <summary>
  25. /// 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
  26. /// </summary>
  27. internal static string CreateLinkString(Dictionary<string, string> dicArray)
  28. {
  29. var prestr = new StringBuilder();
  30. foreach (var temp in dicArray)
  31. {
  32. prestr.Append(temp.Key + "=" + temp.Value + "&");
  33. }
  34. prestr.Remove(prestr.Length - 1, 1);
  35. return prestr.ToString();
  36. }
  37. /// <summary>
  38. /// 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对参数值做urlencode
  39. /// </summary>
  40. internal static string CreateLinkStringUrlencode(Dictionary<string, string> dicArray, Encoding code)
  41. {
  42. var prestr = new StringBuilder();
  43. foreach (var temp in dicArray)
  44. {
  45. prestr.AppendFormat("{0}={1}&", temp.Key, HttpUtility.UrlEncode(temp.Value, code));
  46. }
  47. prestr.Remove(prestr.Length - 1, 1);
  48. return prestr.ToString();
  49. }
  50. /// <summary>
  51. /// 写日志
  52. /// </summary>
  53. internal static void LogResult(string text)
  54. {
  55. var strPath = HttpContext.Current.Server.MapPath(Config._LogPath);
  56. var dateFloderName = DateTime.Now.ToString("yyyyMM");
  57. strPath = string.Format("{0}/{1}", strPath, dateFloderName);
  58. if (!Directory.Exists(strPath))
  59. {
  60. Directory.CreateDirectory(strPath);
  61. }
  62. strPath = strPath + "\\" + DateTime.Now.ToString("yyyyMMddHHmmssffff", DateTimeFormatInfo.InvariantInfo) + ".txt";
  63. var fs = new StreamWriter(strPath, true, Encoding.Default);
  64. fs.Write(text);
  65. fs.Close();
  66. }
  67. /// <summary>
  68. /// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组
  69. /// </summary>
  70. internal static SortedDictionary<string, string> GetRequestPost()
  71. {
  72. int i;
  73. var sArray = new SortedDictionary<string, string>();
  74. var coll = HttpContext.Current.Request.Form;
  75. var requestItem = coll.AllKeys;
  76. for (i = 0; i < requestItem.Length; i++)
  77. sArray.Add(requestItem[i], HttpContext.Current.Request.Form[requestItem[i]]);
  78. return sArray;
  79. }
  80. /*
  81. /// <summary>
  82. /// 获取文件的md5摘要
  83. /// </summary>
  84. /// <param name="sFile">文件流</param>
  85. /// <returns>MD5摘要结果</returns>
  86. internal static string GetAbstractToMD5(Stream sFile)
  87. {
  88. System.Security.Cryptography.MD5 md5 = new MD5CryptoServiceProvider();
  89. byte[] result = md5.ComputeHash(sFile);
  90. StringBuilder sb = new StringBuilder(32);
  91. for (int i = 0; i < result.Length; i++)
  92. {
  93. sb.Append(result[i].ToString("x").PadLeft(2, '0'));
  94. }
  95. return sb.ToString();
  96. }
  97. /// <summary>
  98. /// 获取文件的md5摘要
  99. /// </summary>
  100. /// <param name="dataFile">文件流</param>
  101. /// <returns>MD5摘要结果</returns>
  102. internal static string GetAbstractToMD5(byte[] dataFile)
  103. {
  104. System.Security.Cryptography.MD5 md5 = new MD5CryptoServiceProvider();
  105. byte[] result = md5.ComputeHash(dataFile);
  106. StringBuilder sb = new StringBuilder(32);
  107. for (int i = 0; i < result.Length; i++)
  108. {
  109. sb.Append(result[i].ToString("x").PadLeft(2, '0'));
  110. }
  111. return sb.ToString();
  112. }
  113. */
  114. }
  115. }

 

  1. MD5.cs

  2. using System.Text;
  3. using System.Security.Cryptography;
  4. namespace Alipay
  5. {
  6. internal sealed class MD5
  7. {
  8. /// <summary>
  9. /// 签名字符串
  10. /// </summary>
  11. /// <param name="str">需要签名的字符串</param>
  12. /// <param name="key">密钥</param>
  13. /// <param name="charset">编码格式</param>
  14. /// <returns>签名结果</returns>
  15. internal static string Sign(string str, string key, string charset)
  16. {
  17. var sb = new StringBuilder(32);
  18. str += key;
  19. var md5 = new MD5CryptoServiceProvider();
  20. var t = md5.ComputeHash(Encoding.GetEncoding(charset).GetBytes(str));
  21. for (var i = 0; i < t.Length; i++)
  22. sb.Append(t[i].ToString("x").PadLeft(2, '0'));
  23. return sb.ToString();
  24. }
  25. /// <summary>
  26. /// 验证签名
  27. /// </summary>
  28. /// <param name="prestr">需要签名的字符串</param>
  29. /// <param name="sign">签名结果</param>
  30. /// <param name="key">密钥</param>
  31. /// <param name="charset">编码格式</param>
  32. /// <returns>验证结果</returns>
  33. internal static bool Verify(string prestr, string sign, string key, string charset)
  34. {
  35. var mysign = Sign(prestr, key, charset);
  36. return mysign == sign;
  37. }
  38. }
  39. }

 

  1. Notify.cs

  2. Notify.cs
  3. using System.Text;
  4. using System.IO;
  5. using System.Net;
  6. using System;
  7. using System.Collections.Generic;
  8. namespace Alipay
  9. {
  10. /// <summary>
  11. /// 处理支付宝各接口通知返回
  12. /// </summary>
  13. internal class Notify
  14. {
  15. /// <summary>
  16. /// 验证消息是否是支付宝发出的合法消息
  17. /// </summary>
  18. /// <param name="inputPara">通知返回参数数组</param>
  19. /// <param name="notifyId">通知验证ID</param>
  20. /// <param name="sign">支付宝生成的签名结果</param>
  21. /// <returns>验证结果</returns>
  22. internal bool Verify(SortedDictionary<string, string> inputPara, string notifyId, string sign)
  23. {
  24. var isSign = GetSignVeryfy(inputPara, sign);
  25. var responseTxt = "true";
  26. if (!string.IsNullOrEmpty(notifyId)) { responseTxt = GetResponseTxt(notifyId); }
  27. //判断responsetTxt是否为true,isSign是否为true
  28. //responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关
  29. //isSign不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
  30. return responseTxt == "true" && isSign;
  31. }
  32. /// <summary>
  33. /// 获取返回时的签名验证结果
  34. /// </summary>
  35. /// <param name="inputPara">通知返回参数数组</param>
  36. /// <param name="sign">对比的签名结果</param>
  37. /// <returns>签名验证结果</returns>
  38. private bool GetSignVeryfy(SortedDictionary<string, string> inputPara, string sign)
  39. {
  40. var sPara = Core.FilterPara(inputPara); //过滤空值、sign与sign_type参数
  41. var preSignStr = Core.CreateLinkString(sPara); //获取待签名字符串
  42. return MD5.Verify(preSignStr, sign, Config.Key, Config._Charset);
  43. }
  44. /// <summary>
  45. /// 获取是否是支付宝服务器发来的请求的验证结果
  46. /// </summary>
  47. /// <param name="notifyId">通知验证ID</param>
  48. /// <returns>验证结果</returns>
  49. private string GetResponseTxt(string notifyId)
  50. {
  51. var veryfyUrl = string.Format("{0}partner={1}¬ify_id={2}", Config._VeryfyUrl, Config.Partner, notifyId);
  52. //获取远程服务器ATN结果,验证是否是支付宝服务器发来的请求
  53. try
  54. {
  55. var myReq = (HttpWebRequest)WebRequest.Create(veryfyUrl);
  56. myReq.Timeout = 120000;
  57. var HttpWResp = (HttpWebResponse)myReq.GetResponse();
  58. var myStream = HttpWResp.GetResponseStream();
  59. var sr = new StreamReader(myStream, Encoding.Default);
  60. var strBuilder = new StringBuilder();
  61. while (-1 != sr.Peek())
  62. {
  63. strBuilder.Append(sr.ReadLine());
  64. }
  65. return strBuilder.ToString();
  66. }
  67. catch (Exception exp)
  68. {
  69. return string.Format("错误:{0}", exp.Message);
  70. }
  71. }
  72. }
  73. }

 

  1. PC端的NotifyPage.cs

  2. PC端的NotifyPage.cs
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. namespace Alipay
  7. {
  8. /// <summary>
  9. /// pc网页支付接口接入页
  10. /// </summary>
  11. public abstract class NotifyPage : System.Web.UI.Page
  12. {
  13. /// <summary>
  14. /// 商户订单号
  15. /// </summary>
  16. protected string OrderNo { get; private set; }
  17. /// <summary>
  18. /// 支付宝交易号
  19. /// </summary>
  20. protected string TradeNo { get; private set; }
  21. /// <summary>
  22. /// 交易状态
  23. /// </summary>
  24. protected string TradeStatus { get; private set; }
  25. /// <summary>
  26. /// 业务逻辑处理
  27. /// </summary>
  28. protected abstract void OnNotifyConfirm();
  29. protected void Page_Load(object sender, EventArgs e)
  30. {
  31. if (IsPostBack) return;
  32. var sPara = GetRequestPost();
  33. Core.LogResult(Request.Url.ToString());
  34. if (sPara.Count > 0) //判断是否有带返回参数
  35. {
  36. var formString = Request.Form.Keys.Cast<string>()
  37. .Aggregate("", (current, key) =>
  38. current + string.Format("{0} = {1}\r\n", key.PadLeft(30, ' '),
  39. Request.Form[key]));
  40. Core.LogResult(formString);
  41. var aliNotify = new Notify();
  42. var verifyResult = aliNotify.Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]);
  43. if (verifyResult)//验证成功
  44. {
  45. OrderNo = Request.Form["out_trade_no"];
  46. TradeNo = Request.Form["trade_no"];
  47. TradeStatus = Request.Form["trade_status"];
  48. //该种交易状态只在一种情况下出现——开通了高级即时到账,买家付款成功后。
  49. if (TradeStatus == "TRADE_FINISHED" || TradeStatus == "TRADE_SUCCESS")
  50. {
  51. OnNotifyConfirm(); //业务逻辑处理
  52. Core.LogResult(string.Format("业务逻辑处理,OrderNo:{0},TradeNo:{1},TradeStatus:{2}", OrderNo, TradeNo, TradeStatus));
  53. }
  54. Response.Write("success");
  55. }
  56. else
  57. {
  58. using System;
  59. using System.Linq;
  60. using System.Xml;
  61. namespace Alipay.Wap
  62. {
  63. /// <summary>
  64. /// 手机网页支付接口接入页
  65. /// </summary>
  66. public abstract class NotifyPage : System.Web.UI.Page
  67. {
  68. /// <summary>
  69. /// 商户订单号
  70. /// </summary>
  71. protected string OrderNo { get; private set; }
  72. /// <summary>
  73. /// 支付宝交易号
  74. /// </summary>
  75. protected string TradeNo { get; private set; }
  76. /// <summary>
  77. /// 交易状态
  78. /// </summary>
  79. protected string TradeStatus { get; private set; }
  80. /// <summary>
  81. /// 业务逻辑处理
  82. /// </summary>
  83. protected abstract void OnNotifyConfirm();
  84. protected bool PaySucceed = false;
  85. protected string PayMsg = "";
  86. protected void Page_Load(object sender, EventArgs e)
  87. {
  88. if (IsPostBack) return;
  89. var sPara = Core.GetRequestPost();
  90. Core.LogResult(Request.Url.ToString());
  91. if (sPara.Count > 0) //判断是否有带返回参数
  92. {
  93. var formString = Request.Form.Keys.Cast<string>()
  94. .Aggregate("", (current, key) =>
  95. current + string.Format("{0} = {1}\r\n", key.PadLeft(30, ' '),
  96. Request.Form[key]));
  97. Core.LogResult(formString);
  98. var aliNotify = new Alipay.Notify();
  99. var verifyResult = aliNotify.Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]);
  100. if (verifyResult) //验证成功
  101. {
  102. try
  103. {
  104. var xmlDoc = new XmlDocument();
  105. xmlDoc.LoadXml(sPara["notify_data"]);
  106. OrderNo = xmlDoc.SelectSingleNode("/notify/out_trade_no").InnerText; //商户订单号
  107. TradeNo = xmlDoc.SelectSingleNode("/notify/trade_no").InnerText; //支付宝交易号
  108. TradeStatus = xmlDoc.SelectSingleNode("/notify/trade_status").InnerText; //交易状态
  109. //该种交易状态只在两种情况下出现
  110. //1、开通了普通即时到账,买家付款成功后。
  111. //2、开通了高级即时到账,从该笔交易成功时间算起,过了签约时的可退款时限(如:三个月以内可退款、一年以内可退款等)后
  112. if (TradeStatus == "TRADE_FINISHED" || TradeStatus == "TRADE_SUCCESS")
  113. {
  114. try
  115. {
  116. OnNotifyConfirm();
  117. Core.LogResult(string.Format("业务逻辑处理,OrderNo:{0},TradeNo:{1},TradeStatus:{2}", OrderNo, TradeNo, TradeStatus));
  118. Response.Write("success");
  119. }
  120. catch
  121. {
  122. }
  123. }
  124. else
  125. {
  126. Response.Write(TradeStatus);
  127. }
  128. }
  129. catch (Exception exc)
  130. {
  131. Response.Write(exc.ToString());
  132. }
  133. }
  134. else //验证失败
  135. {
  136. Response.Write("fail");
  137. }
  138. }
  139. else
  140. {
  141. Response.Write("无返回参数");
  142. }
  143. }
  144. }
  145. }


Response.Write("fail"); } } else { Response.Write("无返回参数"); } } /// <summary> /// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组 /// </summary> private SortedDictionary<string, string> GetRequestPost() { int i; var sArray = new SortedDictionary<string, string>(); var coll = Request.Form; var requestItem = coll.AllKeys; for (i = 0; i < requestItem.Length; i++) sArray.Add(requestItem[i], Request.Form[requestItem[i]]); return sArray; } }}


  1. wap端的NotifyPage.cs

 

posted @ 2019-07-26 18:49  馨馨妙  阅读(411)  评论(0编辑  收藏  举报