支付寶PC網站接口對接

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);
        }
View Code

驗籤、創建請求類異步

    /// <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;
        }
    }
View Code

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"));
        }
View Code 
        /// <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;
        }
View Code 

支付寶通知處理類函數

   /// <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 + "&notify_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;
        }
    }
View Code

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");
        }
View Code
       /// <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;
        }
View Code

退款接口(即時到帳有密退款接口):學習

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;
        }
View Code

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");
        }
View Code

查詢接口:

        /// <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
        }
View Code

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();
        }
    }
View Code
相關文章
相關標籤/搜索