PC網站支付接口,請參考支付寶官方文檔:https://b.alipay.com/signing/productSet.htm?navKey=allapi
1.須要提供簽約帳號、商戶密鑰數組
2.代碼實現:安全
支付接口(即時到帳交易):服務器
1>調用支付寶支付網關app
/// <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";//簽名方式:MD五、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)ide
/// <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("\r", ""); pubkey = pubkey.Replace("\n", ""); } 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 + "\n isSign=" + isSign.ToString() + "\n 返回回來的參數:" + GetPreSignStr(inputPara) + "\n "; //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)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";//簽名方式:MD五、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";//簽名方式:MD五、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(); } }