PC网站支付接口,请参考支付宝官方文档:https://b.alipay.com/signing/productSet.htm?navKey=all

1.需要提供签约账号、商户密钥

2.代码实现:

支付接口(即时到账交易)

1>调用支付宝支付网关

  1. /// <summary>
  2. /// PC网站支付
  3. /// </summary>
  4. /// <param name="postProcessPaymentRequest"></param>
  5. private void AlipayTradePCPayment(订单实体 order)
  6. {
  7. if (order == null)
  8. {
  9. return;
  10. }
  11. Log.Info(this.GetType().ToString(), "AlipayTradePCPayment Start......");
  12. string responseText = string.Empty;
  13. try
  14. {
  15. #region 调用支付宝支付接口
  16.  
  17. string partner = "签约账号";
  18. string sign_type = "MD5";//签名方式:MD5、RSA、DSA
  19. string key = "MD5密钥";//商户密钥
  20. string input_charset = "utf-8";//字符编码格式 目前支持 gbk 或 utf-8
  21. //把请求参数打包成数组
  22. SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
  23. sParaTemp.Add("service", "create_direct_pay_by_user");//调用的接口名,无需修改
  24. sParaTemp.Add("partner", partner);//签约账号
  25. sParaTemp.Add("seller_id", "");//收款支付宝账号
  26. sParaTemp.Add("_input_charset", input_charset.ToLower());//字符编码格式 目前支持 gbk 或 utf-8
  27. sParaTemp.Add("payment_type", "1");//支付类型,无需修改
  28. sParaTemp.Add("notify_url", "http://XXXXXXXX/AliPayment/PaymentNotify");//服务器异步通知页面路径
  29. sParaTemp.Add("return_url", "http://XXXXXXXX/AliPayment/PaymentReturn");//页面跳转同步通知页面路径
  30. sParaTemp.Add("anti_phishing_key", "");//防钓鱼时间戳
  31. sParaTemp.Add("exter_invoke_ip", "");//客户端的IP地址
  32. sParaTemp.Add("out_trade_no", "");//商户订单号,商户网站订单系统中唯一订单号,必填
  33. sParaTemp.Add("subject", "");//订单名称,必填
  34. sParaTemp.Add("total_fee", "");//付款金额,必填 单位为RMB-Yuan。取值范围为[0.01,100000000.00],精确到小数点后两位。
  35. sParaTemp.Add("body", "");//商品描述,可空
  36. //建立请求
  37. Submit submit = new Submit(partner, key, input_charset, sign_type);
  38. responseText = submit.BuildRequest(sParaTemp, "get", "确认");
  39. #endregion
  40. _httpContext.Response.Clear();
  41. _httpContext.Response.Write(responseText.ToString());
  42. _httpContext.Response.End();
  43. }
  44. catch (Exception ex)
  45. {
  46. Log.Error(this.GetType().ToString(), "Exception: " + ex.Message);
  47. }
  48. Log.Info(this.GetType().ToString(), "AlipayTradePCPayment End......");
  49. _logger.Track(string.Format("支付宝PC网站支付跟踪信息。GetForm:{0}", responseText), FoxconnConsts.APPSETTING_KEY_TRACK_INTERFACE);
  50. }

View Code

验签、建立请求类

  1. /// <summary>
  2. /// 类名:Submit
  3. /// 功能:支付宝各接口请求提交类
  4. /// 详细:构造支付宝各接口表单HTML文本,获取远程HTTP数据
  5. /// 版本:3.3
  6. /// 修改日期:2011-07-05
  7. /// 说明:
  8. /// 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
  9. /// 该代码仅供学习和研究支付宝接口使用,只是提供一个参考
  10. /// </summary>
  11. public class Submit
  12. {
  13. #region 字段
  14. //支付宝网关地址(新)
  15. private static string GATEWAY_NEW = "https://mapi.alipay.com/gateway.do?";
  16. //合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
  17. private static string _partner = "";
  18. //商户的私钥
  19. private static string _key = "";
  20. //编码格式
  21. private static string _input_charset = "";
  22. //签名方式
  23. private static string _sign_type = "";
  24. #endregion
  25.  
  26. public Submit(string partner, string key, string input_charset, string sign_type)
  27. {
  28. _partner = partner;
  29. _key = key;
  30. _input_charset = input_charset.ToLower();
  31. _sign_type = sign_type.ToUpper();
  32. }
  33. /// <summary>
  34. /// 生成请求时的签名
  35. /// </summary>
  36. /// <param name="sPara">请求给支付宝的参数数组</param>
  37. /// <returns>签名结果</returns>
  38. private string BuildRequestMysign(Dictionary<string, string> sPara)
  39. {
  40. //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
  41. string prestr = Core.CreateLinkString(sPara);
  42. //把最终的字符串签名,获得签名结果
  43. string mysign = "";
  44. switch (_sign_type)
  45. {
  46. case "MD5":
  47. mysign = AlipayMD5.Sign(prestr, _key, _input_charset);
  48. break;
  49. case "RSA":
  50. mysign = RSAFromPkcs8.sign(prestr, _key, _input_charset);
  51. break;
  52. default:
  53. mysign = "";
  54. break;
  55. }
  56. return mysign;
  57. }
  58. /// <summary>
  59. /// 生成要请求给支付宝的参数数组
  60. /// </summary>
  61. /// <param name="sParaTemp">请求前的参数数组</param>
  62. /// <returns>要请求的参数数组</returns>
  63. private Dictionary<string, string> BuildRequestPara(SortedDictionary<string, string> sParaTemp)
  64. {
  65. //待签名请求参数数组
  66. Dictionary<string, string> sPara = new Dictionary<string, string>();
  67. //签名结果
  68. string mysign = "";
  69. //过滤签名参数数组
  70. sPara = Core.FilterPara(sParaTemp);
  71. //获得签名结果
  72. mysign = BuildRequestMysign(sPara);
  73. //签名结果与签名方式加入请求提交参数组中
  74. sPara.Add("sign", mysign);
  75. sPara.Add("sign_type", _sign_type);
  76. return sPara;
  77. }
  78. /// <summary>
  79. /// 生成要请求给支付宝的参数数组
  80. /// </summary>
  81. /// <param name="sParaTemp">请求前的参数数组</param>
  82. /// <param name="code">字符编码</param>
  83. /// <returns>要请求的参数数组字符串</returns>
  84. private string BuildRequestParaToString(SortedDictionary<string, string> sParaTemp, Encoding code)
  85. {
  86. //待签名请求参数数组
  87. Dictionary<string, string> sPara = new Dictionary<string, string>();
  88. sPara = BuildRequestPara(sParaTemp);
  89. //把参数组中所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对参数值做urlencode
  90. string strRequestData = Core.CreateLinkStringUrlencode(sPara, code);
  91. return strRequestData;
  92. }
  93. /// <summary>
  94. /// 建立请求,以表单HTML形式构造(默认)
  95. /// </summary>
  96. /// <param name="sParaTemp">请求参数数组</param>
  97. /// <param name="strMethod">提交方式。两个值可选:post、get</param>
  98. /// <param name="strButtonValue">确认按钮显示文字</param>
  99. /// <returns>提交表单HTML文本</returns>
  100. public string BuildRequest(SortedDictionary<string, string> sParaTemp, string strMethod, string strButtonValue)
  101. {
  102. //待请求参数数组
  103. Dictionary<string, string> dicPara = new Dictionary<string, string>();
  104. dicPara = BuildRequestPara(sParaTemp);
  105. StringBuilder sbHtml = new StringBuilder();
  106. sbHtml.Append("<form id=\'alipaysubmit\' name=\'alipaysubmit\' action=\'" + GATEWAY_NEW + "_input_charset=" + _input_charset + "\' method=\'" + strMethod.ToLower().Trim() + "\'>");
  107. foreach (KeyValuePair<string, string> temp in dicPara)
  108. {
  109. sbHtml.Append("<input type=\'hidden\' name=\'" + temp.Key + "\' value=\'" + temp.Value + "\'/>");
  110. }
  111. //submit按钮控件请不要含有name属性
  112. sbHtml.Append("<input type=\'submit\' value=\'" + strButtonValue + "\' style=\'display:none;\'></form>");
  113. sbHtml.Append("<script>document.forms[\'alipaysubmit\'].submit();</script>");
  114. return sbHtml.ToString();
  115. }
  116. /// <summary>
  117. /// 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果
  118. /// </summary>
  119. /// <param name="sParaTemp">请求参数数组</param>
  120. /// <returns>支付宝处理结果</returns>
  121. public string BuildRequest(SortedDictionary<string, string> sParaTemp)
  122. {
  123. Encoding code = Encoding.GetEncoding(_input_charset);
  124. //待请求参数数组字符串
  125. string strRequestData = BuildRequestParaToString(sParaTemp, code);
  126. //把数组转换成流中所需字节数组类型
  127. byte[] bytesRequestData = code.GetBytes(strRequestData);
  128. //构造请求地址
  129. string strUrl = GATEWAY_NEW + "_input_charset=" + _input_charset;
  130. //请求远程HTTP
  131. string strResult = "";
  132. try
  133. {
  134. //设置HttpWebRequest基本信息
  135. HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(strUrl);
  136. myReq.Method = "post";
  137. myReq.ContentType = "application/x-www-form-urlencoded";
  138. //填充POST数据
  139. myReq.ContentLength = bytesRequestData.Length;
  140. Stream requestStream = myReq.GetRequestStream();
  141. requestStream.Write(bytesRequestData, 0, bytesRequestData.Length);
  142. requestStream.Close();
  143. //发送POST数据请求服务器
  144. HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();
  145. Stream myStream = HttpWResp.GetResponseStream();
  146. //获取服务器返回信息
  147. StreamReader reader = new StreamReader(myStream, code);
  148. StringBuilder responseData = new StringBuilder();
  149. String line;
  150. while ((line = reader.ReadLine()) != null)
  151. {
  152. responseData.Append(line);
  153. }
  154. //释放
  155. myStream.Close();
  156. strResult = responseData.ToString();
  157. }
  158. catch (Exception exp)
  159. {
  160. strResult = "报错:" + exp.Message;
  161. }
  162. return strResult;
  163. }
  164. /// <summary>
  165. /// 用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数
  166. /// 注意:远程解析XML出错,与IIS服务器配置有关
  167. /// </summary>
  168. /// <returns>时间戳字符串</returns>
  169. public string Query_timestamp()
  170. {
  171. string url = GATEWAY_NEW + "service=query_timestamp&partner=" + _partner + "&_input_charset=" + _input_charset;
  172. string encrypt_key = "";
  173. XmlTextReader Reader = new XmlTextReader(url);
  174. XmlDocument xmlDoc = new XmlDocument();
  175. xmlDoc.Load(Reader);
  176. encrypt_key = xmlDoc.SelectSingleNode("/alipay/response/timestamp/encrypt_key").InnerText;
  177. return encrypt_key;
  178. }
  179. }

View Code

2>接收支付宝同步通知(get)

  1. /// <summary>
  2. /// 支付宝支付同步通知
  3. /// </summary>
  4. /// <returns></returns>
  5. [HttpGet]
  6. public ActionResult PaymentReturn()
  7. {
  8. string result = string.Empty;
  9. Log.Info(this.GetType().ToString(), "PaymentReturn End......");
  10. try
  11. {
  12. SortedDictionary<string, string> sPara = GetRequestGet();
  13. if (sPara.Count > 0)//判断是否有带返回参数
  14. {
  15. bool verifyResult = Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"]);
  16. if (verifyResult)//验证成功
  17. {
  18. //商户订单号
  19. string out_trade_no = Request.QueryString["out_trade_no"];
  20. //支付宝交易号
  21. string trade_no = Request.QueryString["trade_no"];
  22. //交易状态
  23. string trade_status = Request.QueryString["trade_status"];
  24. if (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS")
  25. {
  26. //判断该笔订单是否在商户网站中已经做过处理
  27. //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
  28. //如果有做过处理,不执行商户的业务程序
  29. }
  30. else
  31. {
  32. result = "trade_status=" + Request.QueryString["trade_status"];
  33. }
  34. //打印页面
  35. result = "验证成功";
  36. }
  37. else//验证失败
  38. {
  39. result = "验证失败";
  40. }
  41. }
  42. else
  43. {
  44. result = "无返回参数";
  45. }
  46. Log.Info(this.GetType().ToString(), "result:" + result);
  47. }
  48. catch (Exception ex)
  49. {
  50. Log.Info(this.GetType().ToString(), "Exception:" + ex.Message);
  51. _logger.Track(string.Format("支付宝支付同步通知跟踪信息。结果:{0}", ex.Message), FoxconnConsts.APPSETTING_KEY_TRACK_INTERFACE);
  52. }
  53. Log.Info(this.GetType().ToString(), "PaymentReturn End......");
  54. return Redirect(Url.RouteUrl("CustomerOrders"));
  55. }

View Code 

  1. /// <summary>
  2. /// 获取支付宝GET过来通知消息,并以“参数名=参数值”的形式组成数组
  3. /// </summary>
  4. /// <returns>request回来的信息组成的数组</returns>
  5. public SortedDictionary<string, string> GetRequestGet()
  6. {
  7. int i = 0;
  8. SortedDictionary<string, string> sArray = new SortedDictionary<string, string>();
  9. NameValueCollection coll;
  10. //Load Form variables into NameValueCollection variable.
  11. coll = Request.QueryString;
  12. // Get names of all forms into a string array.
  13. String[] requestItem = coll.AllKeys;
  14. for (i = 0; i < requestItem.Length; i++)
  15. {
  16. sArray.Add(requestItem[i], Request.QueryString[requestItem[i]]);
  17. }
  18. return sArray;
  19. }

View Code 

支付宝通知处理类

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

View Code

3>接收支付宝异步通知(post)

  1. /// <summary>
  2. /// 支付宝支付异步通知
  3. /// </summary>
  4. /// <returns></returns>
  5. [ValidateInput(false)]
  6. public ActionResult PaymentNotify()
  7. {
  8. string result = string.Empty;
  9. try
  10. {
  11. Log.Info(this.GetType().ToString(), "PaymentNotify Start......");
  12. SortedDictionary<string, string> sPara = GetRequestPost();
  13. if (sPara.Count > 0)//判断是否有带返回参数
  14. {
  15. bool verifyResult = Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]);
  16. Log.Debug(this.GetType().ToString(), "verifyResult:" + verifyResult);
  17. if (verifyResult)//验证成功
  18. {
  19. //商户订单号
  20. string out_trade_no = Request.Form["out_trade_no"];
  21. //支付宝交易号
  22. string trade_no = Request.Form["trade_no"];
  23. //交易状态
  24. string trade_status = Request.Form["trade_status"];
  25. if (string.IsNullOrEmpty(out_trade_no))
  26. {
  27. throw new Exception("商户订单号不能为空");
  28. }
  29. Log.Debug(this.GetType().ToString(), string.Format("out_trade_no:【{0}】-trade_no:【{1}】-trade_status:【{2}】", out_trade_no, trade_no, trade_status));
  30. if (trade_status == "TRADE_FINISHED")
  31. {
  32. //判断该笔订单是否在商户网站中已经做过处理
  33. //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
  34. //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
  35. //如果有做过处理,不执行商户的业务程序
  36. //处理业务逻辑
  37. //_orderProcessingService.BathMarkOrderAsPaid(out_trade_no);
  38. //注意:
  39. //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
  40. }
  41. else if (trade_status == "TRADE_SUCCESS")
  42. {
  43. //判断该笔订单是否在商户网站中已经做过处理
  44. //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
  45. //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
  46. //如果有做过处理,不执行商户的业务程序
  47. //处理业务逻辑
  48. Log.Info(this.GetType().ToString(), "订单状态更新成功");
  49. //注意:
  50. //付款完成后,支付宝系统发送该交易状态通知
  51. }
  52. else
  53. {
  54. }
  55. //——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
  56. Response.Write("success"); //请不要修改或删除
  57. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  58. }
  59. else//验证失败
  60. {
  61. Response.Write("fail");
  62. }
  63. }
  64. else
  65. {
  66. Response.Write("无通知参数");
  67. Log.Info(this.GetType().ToString(), "result:无通知参数");
  68. }
  69. }
  70. catch (Exception ex)
  71. {
  72. Response.Write("fail");
  73. Log.Info(this.GetType().ToString(), "Exception:" + ex.Message);
  74. _logger.Track(string.Format("支付宝支付异步通知跟踪信息。结果:{0}", ex.Message), FoxconnConsts.APPSETTING_KEY_TRACK_INTERFACE);
  75. }
  76. Response.End();
  77. Log.Info(this.GetType().ToString(), "PaymentNotify End......");
  78. return Content("fail");
  79. }

View Code

  1. /// <summary>
  2. /// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组
  3. /// </summary>
  4. /// <returns>request回来的信息组成的数组</returns>
  5. public SortedDictionary<string, string> GetRequestPost()
  6. {
  7. int i = 0;
  8. SortedDictionary<string, string> sArray = new SortedDictionary<string, string>();
  9. NameValueCollection coll;
  10. //Load Form variables into NameValueCollection variable.
  11. coll = Request.Form;
  12. // Get names of all forms into a string array.
  13. String[] requestItem = coll.AllKeys;
  14. for (i = 0; i < requestItem.Length; i++)
  15. {
  16. sArray.Add(requestItem[i], Request.Form[requestItem[i]]);
  17. }
  18. return sArray;
  19. }

View Code

退款接口(即时到账有密退款接口):

1>调用支付宝支付网关

  1. /// <summary>
  2. /// 退款
  3. /// </summary>
  4. /// <param name="refundPaymentRequest"></param>
  5. /// <returns></returns>
  6. private bool AlipayTradePCRefund(退款实体 refundModel)
  7. {
  8. var result = false;
  9. if (refundModel == null)
  10. {
  11. Log.Error(this.GetType().ToString(), "退款数据不能为空");
  12. return result;
  13. }
  14. string responseText = string.Empty;
  15. try
  16. {
  17. #region 调用支付宝退款接口
  18.  
  19. string partner = "签约账号";
  20. string sign_type = "MD5";//签名方式:MD5、RSA、DSA
  21. string key = "MD5密钥";//商户密钥
  22. string input_charset = "utf-8";//字符编码格式 目前支持 gbk 或 utf-8
  23. //服务器异步通知页面路径
  24. string notify_url = "http://XXXXXXXX/AliPayment/RefundNotify";
  25. Log.Debug(this.GetType().ToString(), "notify_url:" + notify_url);
  26. //退款当天日期
  27. string refund_date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
  28. //必填,格式:年[4位]-月[2位]-日[2位] 小时[2位 24小时制]:分[2位]:秒[2位],如:2007-10-01 13:13:13
  29. //批次号
  30. string batch_no = DateTime.UtcNow.ToString("yyyyMMdd") + refundModel.RefundNumber;//?
  31. //必填,格式:当天日期[8位]+序列号[3至24位],如:201008010000001
  32. Log.Debug(this.GetType().ToString(), "batch_no:" + batch_no);
  33. //退款笔数
  34. string batch_num = "1";
  35. //必填,参数detail_data的值中,“#”字符出现的数量加1,最大支持1000笔(即“#”字符出现的数量999个)
  36. //退款详细数据
  37. string detail_data = "";
  38. //必填,具体格式请参见接口技术文档
  39. StringBuilder sb = new StringBuilder();
  40. Log.Debug(this.GetType().ToString(), "batch_num:" + batch_num);
  41. foreach (var item in 集合)
  42. {
  43. sb.AppendFormat("{0}^{1}^{2}#", "交易号", "退款金额", "退款原因");
  44. }
  45. if (sb.Length > 0)
  46. {
  47. detail_data = sb.ToString().Substring(0, sb.ToString().Length - 1);
  48. }
  49. Log.Debug(this.GetType().ToString(), "detail_data:" + detail_data);
  50. //把请求参数打包成数组
  51. SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
  52. sParaTemp.Add("service", "refund_fastpay_by_platform_pwd");//调用的接口名,无需修改
  53. sParaTemp.Add("partner", partner);//签约账号
  54. sParaTemp.Add("_input_charset", _alipayPaymentSettings.InputCharset.ToLower());//字符编码格式 目前支持 gbk 或 utf-8
  55. sParaTemp.Add("notify_url", notify_url);//服务器异步通知页面路径
  56. sParaTemp.Add("seller_user_id", _alipayPaymentSettings.SellerId);//收款支付宝账号
  57. sParaTemp.Add("refund_date", refund_date);//退款日期
  58. sParaTemp.Add("batch_no", batch_no);//批次号
  59. sParaTemp.Add("batch_num", batch_num);//退款笔数
  60. sParaTemp.Add("detail_data", detail_data);//退款详细数据
  61. //建立请求
  62. Submit submit = new Submit(partner, key, input_charset, sign_type);
  63. responseText = submit.BuildRequest(sParaTemp, "get", "确认");
  64. #endregion
  65. _httpContext.Response.Clear();
  66. _httpContext.Response.Write(responseText);
  67. _httpContext.Response.End();
  68. result = true;
  69. }
  70. catch (Exception ex)
  71. {
  72. responseText = ex.Message;
  73. Log.Error(this.GetType().ToString(), "Exception: " + ex.Message);
  74. }
  75. Log.Debug(this.GetType().ToString(), string.Format("支付宝退款跟踪信息。GetForm:{0}", responseText));
  76. Log.Info(this.GetType().ToString(), "Refund End......");
  77. return result;
  78. }

View Code

2>接收支付宝异步通知(post)

  1. /// <summary>
  2. /// 支付宝退款异步通知
  3. /// </summary>
  4. /// <returns></returns>
  5. [ValidateInput(false)]
  6. public ActionResult RefundNotify()
  7. {
  8. string result = string.Empty;
  9. try
  10. {
  11. Log.Info(this.GetType().ToString(), "RefundNotify Start......");
  12. SortedDictionary<string, string> sPara = GetRequestPost();
  13. if (sPara.Count > 0)//判断是否有带返回参数
  14. {
  15. bool verifyResult = Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]);
  16. if (verifyResult)//验证成功
  17. {
  18. //退款批次号
  19. string batch_no = Request.Form["batch_no"];
  20. Log.Debug(this.GetType().ToString(), "batch_no:" + batch_no);
  21. //退款成功总数
  22. string success_num = Request.Form["success_num"];
  23. Log.Debug(this.GetType().ToString(), "success_num:" + success_num);
  24. //退款结果明细
  25. string result_details = Request.Form["result_details"];
  26. Log.Debug(this.GetType().ToString(), "result_details:" + result_details);
  27. //交易状态
  28. //string trade_status = Request.Form["trade_status"];
  29. //Log.Info(this.GetType().ToString(), "trade_status:" + trade_status);
  30. //全额退款情况:trade_status= TRADE_CLOSED,而refund_status=REFUND_SUCCESS
  31. //非全额退款情况:trade_status= TRADE_SUCCESS,而refund_status=REFUND_SUCCESS
  32. Response.Write("success"); //请不要修改或删除
  33. }
  34. else//验证失败
  35. {
  36. Response.Write("fail");
  37. }
  38. }
  39. else
  40. {
  41. Response.Write("无通知参数");
  42. }
  43. }
  44. catch(Exception ex)
  45. {
  46. Log.Info(this.GetType().ToString(), "Exception:" + ex.Message);
  47. _logger.Track(string.Format("支付宝退款跟踪信息。结果:{0}", ex.Message), FoxconnConsts.APPSETTING_KEY_TRACK_INTERFACE);
  48. }
  49. Log.Info(this.GetType().ToString(), "RefundNotify End......");
  50. return Content("fail");
  51. }

View Code

查询接口:

  1. /// <summary>
  2. /// 查询订单在支付宝的状态
  3. /// </summary>
  4. /// <param name="queryOrderRequest"></param>
  5. /// <returns></returns>
  6. private void AlipayTradePCQuery(订单查询实体 orderQuery)
  7. {
  8. var result = new 订单查询实体();
  9. if (orderQuery == null)
  10. {
  11. //"查询数据不能为空"
  12. return;
  13. }
  14. #region 调用支付宝订单查询接口
  15.  
  16. string partner = "签约账号";
  17. string sign_type = "MD5";//签名方式:MD5、RSA、DSA
  18. string key = "MD5密钥";//商户密钥
  19. string input_charset = "utf-8";//字符编码格式 目前支持 gbk 或 utf-8
  20. //支付宝交易号
  21. string trade_no = "";
  22. //支付宝交易号与商户网站订单号不能同时为空
  23. //商户订单号
  24. string out_trade_no = "";
  25. ////////////////////////////////////////////////////////////////////////////////////////////////
  26.  
  27. //把请求参数打包成数组
  28. SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
  29. sParaTemp.Add("service", "single_trade_query");//调用的接口名,无需修改
  30. sParaTemp.Add("partner", partner);//签约账号
  31. sParaTemp.Add("_input_charset", input_charset.ToLower());//字符编码格式 目前支持 gbk 或 utf-8
  32. sParaTemp.Add("trade_no", trade_no);
  33. sParaTemp.Add("out_trade_no", out_trade_no);//商户订单号,商户网站订单系统中唯一订单号,必填
  34. //建立请求
  35. Submit submit = new Submit(partner, key, input_charset, sign_type);
  36. string sHtmlText = submit.BuildRequest(sParaTemp);
  37. XmlDocument xmlDoc = new XmlDocument();
  38. try
  39. {
  40. xmlDoc.LoadXml(sHtmlText);
  41. string isSuccess = xmlDoc.SelectSingleNode("/alipay/is_success").InnerText;
  42. if (isSuccess == "T")//请求成功
  43. {
  44. #region 根据订单状态处理业务数据
  45.  
  46. string tradeState = xmlDoc.SelectSingleNode("/alipay/response/trade/trade_status").InnerText;
  47. if (tradeState == "TRADE_FINISHED" || tradeState == "TRADE_CLOSED" || tradeState == "TRADE_SUCCESS")//支付成功
  48. {
  49. string transaction_id = xmlDoc.SelectSingleNode("/alipay/response/trade/trade_no").InnerText;
  50. //string buyer_id = xmlDoc.SelectSingleNode("/alipay/response/trade/buyer_id").InnerText;
  51. string buyer_emial = xmlDoc.SelectSingleNode("/alipay/response/trade/buyer_email").InnerText;
  52. //处理订单业务
  53. }
  54. #endregion
  55. }
  56. else
  57. {
  58. string error = xmlDoc.SelectSingleNode("/alipay/error").InnerText;
  59. result.AddError(string.Format("支付宝PC网站接口查询订单失败![接口返回码:{0}]", error));
  60. }
  61. }
  62. catch (Exception ex)
  63. {
  64. Log.Error(this.GetType().ToString(), "Exception:" + ex.Message);
  65. }
  66. #endregion
  67. }

View Code

3.记录日记类

  1. public class Log
  2. {
  3. //在网站根目录下创建日志目录
  4. public static string path = HttpRuntime.AppDomainAppPath + "logs\\Alipay";
  5. /**
  6. * 向日志文件写入调试信息
  7. * @param className 类名
  8. * @param content 写入内容
  9. */
  10. public static void Debug(string className, string content)
  11. {
  12. WriteLog("DEBUG", className, content);
  13. }
  14. /**
  15. * 向日志文件写入运行时信息
  16. * @param className 类名
  17. * @param content 写入内容
  18. */
  19. public static void Info(string className, string content)
  20. {
  21. WriteLog("INFO", className, content);
  22. }
  23. /**
  24. * 向日志文件写入出错信息
  25. * @param className 类名
  26. * @param content 写入内容
  27. */
  28. public static void Error(string className, string content)
  29. {
  30. WriteLog("ERROR", className, content);
  31. }
  32. /**
  33. * 实际的写日志操作
  34. * @param type 日志记录类型
  35. * @param className 类名
  36. * @param content 写入内容
  37. */
  38. protected static void WriteLog(string type, string className, string content)
  39. {
  40. if (!Directory.Exists(path))//如果日志目录不存在就创建
  41. {
  42. Directory.CreateDirectory(path);
  43. }
  44. string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");//获取当前系统时间
  45. string filename = path + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";//用日期对日志文件命名
  46. //创建或打开日志文件,向日志文件末尾追加记录
  47. StreamWriter mySw = File.AppendText(filename);
  48. //向日志文件写入内容
  49. string write_content = time + " " + type + " " + className + ": " + content;
  50. mySw.WriteLine(write_content);
  51. //关闭日志文件
  52. mySw.Close();
  53. mySw.Dispose();
  54. }
  55. }

View Code 

版权声明:本文为ywblog原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/ywblog/p/6560093.html