PC网站支付接口,请参考支付宝官方文档:https://b.alipay.com/signing/productSet.htm?navKey=all
1.需要提供签约账号、商户密钥
2.代码实现:
支付接口(即时到账交易):
1>调用支付宝支付网关
/// <summary> /// PC网站支付 /// </summary> /// <param name="postProcessPaymentRequest"></param> private void AlipayTradePCPayment(订单实体 order) { if (order == null) { return; } Log.Info(this.GetType().ToString(), "AlipayTradePCPayment Start......"); string responseText = string.Empty; try { #region 调用支付宝支付接口 string partner = "签约账号"; string sign_type = "MD5";//签名方式:MD5、RSA、DSA string key = "MD5密钥";//商户密钥 string input_charset = "utf-8";//字符编码格式 目前支持 gbk 或 utf-8 //把请求参数打包成数组 SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>(); sParaTemp.Add("service", "create_direct_pay_by_user");//调用的接口名,无需修改 sParaTemp.Add("partner", partner);//签约账号 sParaTemp.Add("seller_id", "");//收款支付宝账号 sParaTemp.Add("_input_charset", input_charset.ToLower());//字符编码格式 目前支持 gbk 或 utf-8 sParaTemp.Add("payment_type", "1");//支付类型,无需修改 sParaTemp.Add("notify_url", "http://XXXXXXXX/AliPayment/PaymentNotify");//服务器异步通知页面路径 sParaTemp.Add("return_url", "http://XXXXXXXX/AliPayment/PaymentReturn");//页面跳转同步通知页面路径 sParaTemp.Add("anti_phishing_key", "");//防钓鱼时间戳 sParaTemp.Add("exter_invoke_ip", "");//客户端的IP地址 sParaTemp.Add("out_trade_no", "");//商户订单号,商户网站订单系统中唯一订单号,必填 sParaTemp.Add("subject", "");//订单名称,必填 sParaTemp.Add("total_fee", "");//付款金额,必填 单位为RMB-Yuan。取值范围为[0.01,100000000.00],精确到小数点后两位。 sParaTemp.Add("body", "");//商品描述,可空 //建立请求 Submit submit = new Submit(partner, key, input_charset, sign_type); responseText = submit.BuildRequest(sParaTemp, "get", "确认"); #endregion _httpContext.Response.Clear(); _httpContext.Response.Write(responseText.ToString()); _httpContext.Response.End(); } catch (Exception ex) { Log.Error(this.GetType().ToString(), "Exception: " + ex.Message); } Log.Info(this.GetType().ToString(), "AlipayTradePCPayment End......"); _logger.Track(string.Format("支付宝PC网站支付跟踪信息。GetForm:{0}", responseText), FoxconnConsts.APPSETTING_KEY_TRACK_INTERFACE); }
验签、建立请求类
/// <summary> /// 类名:Submit /// 功能:支付宝各接口请求提交类 /// 详细:构造支付宝各接口表单HTML文本,获取远程HTTP数据 /// 版本:3.3 /// 修改日期:2011-07-05 /// 说明: /// 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。 /// 该代码仅供学习和研究支付宝接口使用,只是提供一个参考 /// </summary> public class Submit { #region 字段 //支付宝网关地址(新) private static string GATEWAY_NEW = "https://mapi.alipay.com/gateway.do?"; //合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm private static string _partner = ""; //商户的私钥 private static string _key = ""; //编码格式 private static string _input_charset = ""; //签名方式 private static string _sign_type = ""; #endregion public Submit(string partner, string key, string input_charset, string sign_type) { _partner = partner; _key = key; _input_charset = input_charset.ToLower(); _sign_type = sign_type.ToUpper(); } /// <summary> /// 生成请求时的签名 /// </summary> /// <param name="sPara">请求给支付宝的参数数组</param> /// <returns>签名结果</returns> private string BuildRequestMysign(Dictionary<string, string> sPara) { //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 string prestr = Core.CreateLinkString(sPara); //把最终的字符串签名,获得签名结果 string mysign = ""; switch (_sign_type) { case "MD5": mysign = AlipayMD5.Sign(prestr, _key, _input_charset); break; case "RSA": mysign = RSAFromPkcs8.sign(prestr, _key, _input_charset); break; default: mysign = ""; break; } return mysign; } /// <summary> /// 生成要请求给支付宝的参数数组 /// </summary> /// <param name="sParaTemp">请求前的参数数组</param> /// <returns>要请求的参数数组</returns> private Dictionary<string, string> BuildRequestPara(SortedDictionary<string, string> sParaTemp) { //待签名请求参数数组 Dictionary<string, string> sPara = new Dictionary<string, string>(); //签名结果 string mysign = ""; //过滤签名参数数组 sPara = Core.FilterPara(sParaTemp); //获得签名结果 mysign = BuildRequestMysign(sPara); //签名结果与签名方式加入请求提交参数组中 sPara.Add("sign", mysign); sPara.Add("sign_type", _sign_type); return sPara; } /// <summary> /// 生成要请求给支付宝的参数数组 /// </summary> /// <param name="sParaTemp">请求前的参数数组</param> /// <param name="code">字符编码</param> /// <returns>要请求的参数数组字符串</returns> private string BuildRequestParaToString(SortedDictionary<string, string> sParaTemp, Encoding code) { //待签名请求参数数组 Dictionary<string, string> sPara = new Dictionary<string, string>(); sPara = BuildRequestPara(sParaTemp); //把参数组中所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对参数值做urlencode string strRequestData = Core.CreateLinkStringUrlencode(sPara, code); return strRequestData; } /// <summary> /// 建立请求,以表单HTML形式构造(默认) /// </summary> /// <param name="sParaTemp">请求参数数组</param> /// <param name="strMethod">提交方式。两个值可选:post、get</param> /// <param name="strButtonValue">确认按钮显示文字</param> /// <returns>提交表单HTML文本</returns> public string BuildRequest(SortedDictionary<string, string> sParaTemp, string strMethod, string strButtonValue) { //待请求参数数组 Dictionary<string, string> dicPara = new Dictionary<string, string>(); dicPara = BuildRequestPara(sParaTemp); StringBuilder sbHtml = new StringBuilder(); sbHtml.Append("<form id='alipaysubmit' name='alipaysubmit' action='" + GATEWAY_NEW + "_input_charset=" + _input_charset + "' method='" + strMethod.ToLower().Trim() + "'>"); foreach (KeyValuePair<string, string> temp in dicPara) { sbHtml.Append("<input type='hidden' name='" + temp.Key + "' value='" + temp.Value + "'/>"); } //submit按钮控件请不要含有name属性 sbHtml.Append("<input type='submit' value='" + strButtonValue + "' style='display:none;'></form>"); sbHtml.Append("<script>document.forms['alipaysubmit'].submit();</script>"); return sbHtml.ToString(); } /// <summary> /// 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果 /// </summary> /// <param name="sParaTemp">请求参数数组</param> /// <returns>支付宝处理结果</returns> public string BuildRequest(SortedDictionary<string, string> sParaTemp) { Encoding code = Encoding.GetEncoding(_input_charset); //待请求参数数组字符串 string strRequestData = BuildRequestParaToString(sParaTemp, code); //把数组转换成流中所需字节数组类型 byte[] bytesRequestData = code.GetBytes(strRequestData); //构造请求地址 string strUrl = GATEWAY_NEW + "_input_charset=" + _input_charset; //请求远程HTTP string strResult = ""; try { //设置HttpWebRequest基本信息 HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(strUrl); myReq.Method = "post"; myReq.ContentType = "application/x-www-form-urlencoded"; //填充POST数据 myReq.ContentLength = bytesRequestData.Length; Stream requestStream = myReq.GetRequestStream(); requestStream.Write(bytesRequestData, 0, bytesRequestData.Length); requestStream.Close(); //发送POST数据请求服务器 HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse(); Stream myStream = HttpWResp.GetResponseStream(); //获取服务器返回信息 StreamReader reader = new StreamReader(myStream, code); StringBuilder responseData = new StringBuilder(); String line; while ((line = reader.ReadLine()) != null) { responseData.Append(line); } //释放 myStream.Close(); strResult = responseData.ToString(); } catch (Exception exp) { strResult = "报错:" + exp.Message; } return strResult; } /// <summary> /// 用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数 /// 注意:远程解析XML出错,与IIS服务器配置有关 /// </summary> /// <returns>时间戳字符串</returns> public string Query_timestamp() { string url = GATEWAY_NEW + "service=query_timestamp&partner=" + _partner + "&_input_charset=" + _input_charset; string encrypt_key = ""; XmlTextReader Reader = new XmlTextReader(url); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(Reader); encrypt_key = xmlDoc.SelectSingleNode("/alipay/response/timestamp/encrypt_key").InnerText; return encrypt_key; } }
2>接收支付宝同步通知(get)
/// <summary> /// 支付宝支付同步通知 /// </summary> /// <returns></returns> [HttpGet] public ActionResult PaymentReturn() { string result = string.Empty; Log.Info(this.GetType().ToString(), "PaymentReturn End......"); try { SortedDictionary<string, string> sPara = GetRequestGet(); if (sPara.Count > 0)//判断是否有带返回参数 { bool verifyResult = Verify(sPara, Request.QueryString["notify_id"], Request.QueryString["sign"]); if (verifyResult)//验证成功 { //商户订单号 string out_trade_no = Request.QueryString["out_trade_no"]; //支付宝交易号 string trade_no = Request.QueryString["trade_no"]; //交易状态 string trade_status = Request.QueryString["trade_status"]; if (Request.QueryString["trade_status"] == "TRADE_FINISHED" || Request.QueryString["trade_status"] == "TRADE_SUCCESS") { //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 } else { result = "trade_status=" + Request.QueryString["trade_status"]; } //打印页面 result = "验证成功"; } else//验证失败 { result = "验证失败"; } } else { result = "无返回参数"; } Log.Info(this.GetType().ToString(), "result:" + result); } catch (Exception ex) { Log.Info(this.GetType().ToString(), "Exception:" + ex.Message); _logger.Track(string.Format("支付宝支付同步通知跟踪信息。结果:{0}", ex.Message), FoxconnConsts.APPSETTING_KEY_TRACK_INTERFACE); } Log.Info(this.GetType().ToString(), "PaymentReturn End......"); return Redirect(Url.RouteUrl("CustomerOrders")); }
/// <summary> /// 获取支付宝GET过来通知消息,并以“参数名=参数值”的形式组成数组 /// </summary> /// <returns>request回来的信息组成的数组</returns> public SortedDictionary<string, string> GetRequestGet() { int i = 0; SortedDictionary<string, string> sArray = new SortedDictionary<string, string>(); NameValueCollection coll; //Load Form variables into NameValueCollection variable. coll = Request.QueryString; // Get names of all forms into a string array. String[] requestItem = coll.AllKeys; for (i = 0; i < requestItem.Length; i++) { sArray.Add(requestItem[i], Request.QueryString[requestItem[i]]); } return sArray; }
支付宝通知处理类
/// <summary> /// 类名:Notify /// 功能:支付宝通知处理类 /// 详细:处理支付宝各接口通知返回 /// 版本:3.3 /// 修改日期:2011-07-05 /// '说明: /// 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。 /// 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 /// /// //////////////////////注意///////////////////////////// /// 调试通知返回时,可查看或改写log日志的写入TXT里的数据,来检查通知返回是否正常 /// </summary> public class Notify { #region 字段 private string _partner = ""; //合作身份者ID private string _key = ""; //MD5:商户的私钥 RSA:支付宝的公钥 private string _input_charset = ""; //编码格式 private string _sign_type = ""; //签名方式 //支付宝消息验证地址 private string Https_veryfy_url = "https://mapi.alipay.com/gateway.do?service=notify_verify&"; #endregion /// <summary> /// 构造函数 /// 从配置文件中初始化变量 /// </summary> /// <param name="inputPara">通知返回参数数组</param> /// <param name="notify_id">通知验证ID</param> public Notify(string partner, string key, string input_charset, string sign_type) { //初始化基础配置信息 _partner = partner.Trim(); _key = key.Trim(); _input_charset = input_charset.Trim().ToLower(); _sign_type = sign_type.Trim().ToUpper(); } /// <summary> /// 从文件读取公钥转公钥字符串 /// </summary> /// <param name="Path">公钥文件路径</param> public static string getPublicKeyStr(string Path) { StreamReader sr = new StreamReader(Path); string pubkey = sr.ReadToEnd(); sr.Close(); if (pubkey != null) { pubkey = pubkey.Replace("-----BEGIN PUBLIC KEY-----", ""); pubkey = pubkey.Replace("-----END PUBLIC KEY-----", ""); pubkey = pubkey.Replace(" ", ""); pubkey = pubkey.Replace(" ", ""); } return pubkey; } /// <summary> /// 验证消息是否是支付宝发出的合法消息 /// </summary> /// <param name="inputPara">通知返回参数数组</param> /// <param name="notify_id">通知验证ID</param> /// <param name="sign">支付宝生成的签名结果</param> /// <returns>验证结果</returns> public bool Verify(SortedDictionary<string, string> inputPara, string notify_id, string sign) { //获取返回时的签名验证结果 bool isSign = GetSignVeryfy(inputPara, sign); //获取是否是支付宝服务器发来的请求的验证结果 string responseTxt = "false"; if (notify_id != null && notify_id != "") { responseTxt = GetResponseTxt(notify_id); } //写日志记录(若要调试,请取消下面两行注释) //string sWord = "responseTxt=" + responseTxt + " isSign=" + isSign.ToString() + " 返回回来的参数:" + GetPreSignStr(inputPara) + " "; //Core.LogResult(sWord); //判断responsetTxt是否为true,isSign是否为true //responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 //isSign不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 if (responseTxt == "true" && isSign)//验证成功 { return true; } else//验证失败 { return false; } } /// <summary> /// 获取待签名字符串(调试用) /// </summary> /// <param name="inputPara">通知返回参数数组</param> /// <returns>待签名字符串</returns> private string GetPreSignStr(SortedDictionary<string, string> inputPara) { Dictionary<string, string> sPara = new Dictionary<string, string>(); //过滤空值、sign与sign_type参数 sPara = Core.FilterPara(inputPara); //获取待签名字符串 string preSignStr = Core.CreateLinkString(sPara); return preSignStr; } /// <summary> /// 获取返回时的签名验证结果 /// </summary> /// <param name="inputPara">通知返回参数数组</param> /// <param name="sign">对比的签名结果</param> /// <returns>签名验证结果</returns> private bool GetSignVeryfy(SortedDictionary<string, string> inputPara, string sign) { Dictionary<string, string> sPara = new Dictionary<string, string>(); //过滤空值、sign与sign_type参数 sPara = Core.FilterPara(inputPara); //获取待签名字符串 string preSignStr = Core.CreateLinkString(sPara); //获得签名验证结果 bool isSgin = false; if (sign != null && sign != "") { switch (_sign_type) { case "MD5": isSgin = AlipayMD5.Verify(preSignStr, sign, _key, _input_charset); break; case "RSA": isSgin = RSAFromPkcs8.verify(preSignStr, sign, _key, _input_charset); break; default: break; } } return isSgin; } /// <summary> /// 获取是否是支付宝服务器发来的请求的验证结果 /// </summary> /// <param name="notify_id">通知验证ID</param> /// <returns>验证结果</returns> private string GetResponseTxt(string notify_id) { string veryfy_url = Https_veryfy_url + "partner=" + _partner + "¬ify_id=" + notify_id; //获取远程服务器ATN结果,验证是否是支付宝服务器发来的请求 string responseTxt = Get_Http(veryfy_url, 120000); return responseTxt; } /// <summary> /// 获取远程服务器ATN结果 /// </summary> /// <param name="strUrl">指定URL路径地址</param> /// <param name="timeout">超时时间设置</param> /// <returns>服务器ATN结果</returns> private string Get_Http(string strUrl, int timeout) { string strResult; try { HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(strUrl); myReq.Timeout = timeout; HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse(); Stream myStream = HttpWResp.GetResponseStream(); StreamReader sr = new StreamReader(myStream, Encoding.Default); StringBuilder strBuilder = new StringBuilder(); while (-1 != sr.Peek()) { strBuilder.Append(sr.ReadLine()); } strResult = strBuilder.ToString(); } catch (Exception exp) { strResult = "错误:" + exp.Message; } return strResult; } }
3>接收支付宝异步通知(post)
/// <summary> /// 支付宝支付异步通知 /// </summary> /// <returns></returns> [ValidateInput(false)] public ActionResult PaymentNotify() { string result = string.Empty; try { Log.Info(this.GetType().ToString(), "PaymentNotify Start......"); SortedDictionary<string, string> sPara = GetRequestPost(); if (sPara.Count > 0)//判断是否有带返回参数 { bool verifyResult = Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]); Log.Debug(this.GetType().ToString(), "verifyResult:" + verifyResult); if (verifyResult)//验证成功 { //商户订单号 string out_trade_no = Request.Form["out_trade_no"]; //支付宝交易号 string trade_no = Request.Form["trade_no"]; //交易状态 string trade_status = Request.Form["trade_status"]; if (string.IsNullOrEmpty(out_trade_no)) { throw new Exception("商户订单号不能为空"); } Log.Debug(this.GetType().ToString(), string.Format("out_trade_no:【{0}】-trade_no:【{1}】-trade_status:【{2}】", out_trade_no, trade_no, trade_status)); if (trade_status == "TRADE_FINISHED") { //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 //如果有做过处理,不执行商户的业务程序 //处理业务逻辑 //_orderProcessingService.BathMarkOrderAsPaid(out_trade_no); //注意: //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 } else if (trade_status == "TRADE_SUCCESS") { //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 //如果有做过处理,不执行商户的业务程序 //处理业务逻辑 Log.Info(this.GetType().ToString(), "订单状态更新成功"); //注意: //付款完成后,支付宝系统发送该交易状态通知 } else { } //——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— Response.Write("success"); //请不要修改或删除 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// } else//验证失败 { Response.Write("fail"); } } else { Response.Write("无通知参数"); Log.Info(this.GetType().ToString(), "result:无通知参数"); } } catch (Exception ex) { Response.Write("fail"); Log.Info(this.GetType().ToString(), "Exception:" + ex.Message); _logger.Track(string.Format("支付宝支付异步通知跟踪信息。结果:{0}", ex.Message), FoxconnConsts.APPSETTING_KEY_TRACK_INTERFACE); } Response.End(); Log.Info(this.GetType().ToString(), "PaymentNotify End......"); return Content("fail"); }
/// <summary> /// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组 /// </summary> /// <returns>request回来的信息组成的数组</returns> public SortedDictionary<string, string> GetRequestPost() { int i = 0; SortedDictionary<string, string> sArray = new SortedDictionary<string, string>(); NameValueCollection coll; //Load Form variables into NameValueCollection variable. coll = Request.Form; // Get names of all forms into a string array. String[] requestItem = coll.AllKeys; for (i = 0; i < requestItem.Length; i++) { sArray.Add(requestItem[i], Request.Form[requestItem[i]]); } return sArray; }
退款接口(即时到账有密退款接口):
1>调用支付宝支付网关
/// <summary> /// 退款 /// </summary> /// <param name="refundPaymentRequest"></param> /// <returns></returns> private bool AlipayTradePCRefund(退款实体 refundModel) { var result = false; if (refundModel == null) { Log.Error(this.GetType().ToString(), "退款数据不能为空"); return result; } string responseText = string.Empty; try { #region 调用支付宝退款接口 string partner = "签约账号"; string sign_type = "MD5";//签名方式:MD5、RSA、DSA string key = "MD5密钥";//商户密钥 string input_charset = "utf-8";//字符编码格式 目前支持 gbk 或 utf-8 //服务器异步通知页面路径 string notify_url = "http://XXXXXXXX/AliPayment/RefundNotify"; Log.Debug(this.GetType().ToString(), "notify_url:" + notify_url); //退款当天日期 string refund_date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); //必填,格式:年[4位]-月[2位]-日[2位] 小时[2位 24小时制]:分[2位]:秒[2位],如:2007-10-01 13:13:13 //批次号 string batch_no = DateTime.UtcNow.ToString("yyyyMMdd") + refundModel.RefundNumber;//? //必填,格式:当天日期[8位]+序列号[3至24位],如:201008010000001 Log.Debug(this.GetType().ToString(), "batch_no:" + batch_no); //退款笔数 string batch_num = "1"; //必填,参数detail_data的值中,“#”字符出现的数量加1,最大支持1000笔(即“#”字符出现的数量999个) //退款详细数据 string detail_data = ""; //必填,具体格式请参见接口技术文档 StringBuilder sb = new StringBuilder(); Log.Debug(this.GetType().ToString(), "batch_num:" + batch_num); foreach (var item in 集合) { sb.AppendFormat("{0}^{1}^{2}#", "交易号", "退款金额", "退款原因"); } if (sb.Length > 0) { detail_data = sb.ToString().Substring(0, sb.ToString().Length - 1); } Log.Debug(this.GetType().ToString(), "detail_data:" + detail_data); //把请求参数打包成数组 SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>(); sParaTemp.Add("service", "refund_fastpay_by_platform_pwd");//调用的接口名,无需修改 sParaTemp.Add("partner", partner);//签约账号 sParaTemp.Add("_input_charset", _alipayPaymentSettings.InputCharset.ToLower());//字符编码格式 目前支持 gbk 或 utf-8 sParaTemp.Add("notify_url", notify_url);//服务器异步通知页面路径 sParaTemp.Add("seller_user_id", _alipayPaymentSettings.SellerId);//收款支付宝账号 sParaTemp.Add("refund_date", refund_date);//退款日期 sParaTemp.Add("batch_no", batch_no);//批次号 sParaTemp.Add("batch_num", batch_num);//退款笔数 sParaTemp.Add("detail_data", detail_data);//退款详细数据 //建立请求 Submit submit = new Submit(partner, key, input_charset, sign_type); responseText = submit.BuildRequest(sParaTemp, "get", "确认"); #endregion _httpContext.Response.Clear(); _httpContext.Response.Write(responseText); _httpContext.Response.End(); result = true; } catch (Exception ex) { responseText = ex.Message; Log.Error(this.GetType().ToString(), "Exception: " + ex.Message); } Log.Debug(this.GetType().ToString(), string.Format("支付宝退款跟踪信息。GetForm:{0}", responseText)); Log.Info(this.GetType().ToString(), "Refund End......"); return result; }
2>接收支付宝异步通知(post)
/// <summary> /// 支付宝退款异步通知 /// </summary> /// <returns></returns> [ValidateInput(false)] public ActionResult RefundNotify() { string result = string.Empty; try { Log.Info(this.GetType().ToString(), "RefundNotify Start......"); SortedDictionary<string, string> sPara = GetRequestPost(); if (sPara.Count > 0)//判断是否有带返回参数 { bool verifyResult = Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]); if (verifyResult)//验证成功 { //退款批次号 string batch_no = Request.Form["batch_no"]; Log.Debug(this.GetType().ToString(), "batch_no:" + batch_no); //退款成功总数 string success_num = Request.Form["success_num"]; Log.Debug(this.GetType().ToString(), "success_num:" + success_num); //退款结果明细 string result_details = Request.Form["result_details"]; Log.Debug(this.GetType().ToString(), "result_details:" + result_details); //交易状态 //string trade_status = Request.Form["trade_status"]; //Log.Info(this.GetType().ToString(), "trade_status:" + trade_status); //全额退款情况:trade_status= TRADE_CLOSED,而refund_status=REFUND_SUCCESS //非全额退款情况:trade_status= TRADE_SUCCESS,而refund_status=REFUND_SUCCESS Response.Write("success"); //请不要修改或删除 } else//验证失败 { Response.Write("fail"); } } else { Response.Write("无通知参数"); } } catch(Exception ex) { Log.Info(this.GetType().ToString(), "Exception:" + ex.Message); _logger.Track(string.Format("支付宝退款跟踪信息。结果:{0}", ex.Message), FoxconnConsts.APPSETTING_KEY_TRACK_INTERFACE); } Log.Info(this.GetType().ToString(), "RefundNotify End......"); return Content("fail"); }
查询接口:
/// <summary> /// 查询订单在支付宝的状态 /// </summary> /// <param name="queryOrderRequest"></param> /// <returns></returns> private void AlipayTradePCQuery(订单查询实体 orderQuery) { var result = new 订单查询实体(); if (orderQuery == null) { //"查询数据不能为空" return; } #region 调用支付宝订单查询接口 string partner = "签约账号"; string sign_type = "MD5";//签名方式:MD5、RSA、DSA string key = "MD5密钥";//商户密钥 string input_charset = "utf-8";//字符编码格式 目前支持 gbk 或 utf-8 //支付宝交易号 string trade_no = ""; //支付宝交易号与商户网站订单号不能同时为空 //商户订单号 string out_trade_no = ""; //////////////////////////////////////////////////////////////////////////////////////////////// //把请求参数打包成数组 SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>(); sParaTemp.Add("service", "single_trade_query");//调用的接口名,无需修改 sParaTemp.Add("partner", partner);//签约账号 sParaTemp.Add("_input_charset", input_charset.ToLower());//字符编码格式 目前支持 gbk 或 utf-8 sParaTemp.Add("trade_no", trade_no); sParaTemp.Add("out_trade_no", out_trade_no);//商户订单号,商户网站订单系统中唯一订单号,必填 //建立请求 Submit submit = new Submit(partner, key, input_charset, sign_type); string sHtmlText = submit.BuildRequest(sParaTemp); XmlDocument xmlDoc = new XmlDocument(); try { xmlDoc.LoadXml(sHtmlText); string isSuccess = xmlDoc.SelectSingleNode("/alipay/is_success").InnerText; if (isSuccess == "T")//请求成功 { #region 根据订单状态处理业务数据 string tradeState = xmlDoc.SelectSingleNode("/alipay/response/trade/trade_status").InnerText; if (tradeState == "TRADE_FINISHED" || tradeState == "TRADE_CLOSED" || tradeState == "TRADE_SUCCESS")//支付成功 { string transaction_id = xmlDoc.SelectSingleNode("/alipay/response/trade/trade_no").InnerText; //string buyer_id = xmlDoc.SelectSingleNode("/alipay/response/trade/buyer_id").InnerText; string buyer_emial = xmlDoc.SelectSingleNode("/alipay/response/trade/buyer_email").InnerText; //处理订单业务 } #endregion } else { string error = xmlDoc.SelectSingleNode("/alipay/error").InnerText; result.AddError(string.Format("支付宝PC网站接口查询订单失败![接口返回码:{0}]", error)); } } catch (Exception ex) { Log.Error(this.GetType().ToString(), "Exception:" + ex.Message); } #endregion }
3.记录日记类
public class Log { //在网站根目录下创建日志目录 public static string path = HttpRuntime.AppDomainAppPath + "logs\Alipay"; /** * 向日志文件写入调试信息 * @param className 类名 * @param content 写入内容 */ public static void Debug(string className, string content) { WriteLog("DEBUG", className, content); } /** * 向日志文件写入运行时信息 * @param className 类名 * @param content 写入内容 */ public static void Info(string className, string content) { WriteLog("INFO", className, content); } /** * 向日志文件写入出错信息 * @param className 类名 * @param content 写入内容 */ public static void Error(string className, string content) { WriteLog("ERROR", className, content); } /** * 实际的写日志操作 * @param type 日志记录类型 * @param className 类名 * @param content 写入内容 */ protected static void WriteLog(string type, string className, string content) { if (!Directory.Exists(path))//如果日志目录不存在就创建 { Directory.CreateDirectory(path); } string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");//获取当前系统时间 string filename = path + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";//用日期对日志文件命名 //创建或打开日志文件,向日志文件末尾追加记录 StreamWriter mySw = File.AppendText(filename); //向日志文件写入内容 string write_content = time + " " + type + " " + className + ": " + content; mySw.WriteLine(write_content); //关闭日志文件 mySw.Close(); mySw.Dispose(); } }