asp .net mvc支付寶支付服務端demo
阿新 • • 發佈:2019-01-05
本來支付寶支付不需要服務端提供什麼程式碼的,最多就是儲存一些公鑰和私鑰,但是為了安全,最好還是要在服務端提供支付寶的回撥,畢竟客戶端是不可相信的。
看了一下支付寶的開發文件,比微信支付的開發文件詳細得多,微信開發文件,我竟然沒找到服務端的一些demo,我也是醉了。
簡單的來講,支付寶支付分為三步
第一步:拼接引數
biz_content = "{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\"" + Consume.ToString("0.00") + "\",\"subject\":\"" + ConsumeType + "\",\"body\":\"我是支付寶支付\",\"out_trade_no\":\"" + orders.OrderId + "\"}"; //把請求引數打包成陣列 Dictionary<string, string> sParaTemp = new Dictionary<string, string>(); sParaTemp.Add("app_id", Com.Alipay.Config.App_id); //寫在一個類裡面,配置檔案 sParaTemp.Add("biz_content", biz_content); sParaTemp.Add("charset", "utf-8"); sParaTemp.Add("method", "alipay.trade.app.pay"); sParaTemp.Add("notify_url", notify_url); sParaTemp.Add("sign_type", Com.Alipay.Config.Sign_type); sParaTemp.Add("timestamp", timestamp); sParaTemp.Add("version", version);
注意total_amount 他的單位是元,並且是精確到分的。還有notify_url一定要是可訪問的,不然也會報錯,如果是mvc的,就類似這樣http://XXXX/KKPay/AliPayNotify ,一般來說,報錯最多的還是這一步,要步步小心。
第二步:簽名
簽名方法如下:
/// <summary> /// 生成請求時的簽名 /// </summary> /// <param name="sPara">請求給支付寶的引數陣列</param> /// <returns>簽名結果</returns> public static string BuildRequestMysign(Dictionary<string, string> sPara) { //把陣列所有元素,按照“引數=引數值”的模式用“&”字元拼接成字串 string prestr = Core.CreateLinkString(sPara); //把最終的字串簽名,獲得簽名結果 string mysign = ""; switch (_sign_type) { case "RSA": mysign = RSAFromPkcs8.sign(prestr, _private_key, _input_charset); break; default: mysign = ""; break; } return mysign; }
這個方法是獲取sign的,得到sign後,把他加到DIctionary裡面去
sParaTemp.Add("sign", sign);
第三步:編碼
/// <summary> /// 把陣列所有元素,按照“引數=引數值”的模式用“&”字元拼接成字串,並對引數值做urlencode /// </summary> /// <param name="sArray">需要拼接的陣列</param> /// <param name="code">字元編碼</param> /// <returns>拼接完成以後的字串</returns> public static string CreateLinkStringUrlencode(Dictionary<string, string> dicArray, Encoding code) { StringBuilder prestr = new StringBuilder(); foreach (KeyValuePair<string, string> temp in dicArray) { prestr.Append(temp.Key + "=" + HttpUtility.UrlEncode(temp.Value, code) + "&"); } //去掉最後一個&字元 int nLen = prestr.Length; prestr.Remove(nLen - 1, 1); return prestr.ToString(); }
編碼方式UTF-8
這個獲得的就是傳給支付寶的字串,把它給客戶端童鞋。客戶端同學發起支付後,支付寶會往notify_url裡面發一個請求。這個請求是post的形式的,他會返回來很多東西,具體是哪些東西可以看支付寶的文件。
我們要寫一個接收回調的,他返回來的是支付寶支付是否成功。
首先我們要驗證這個訊息是不是支付寶發出的合法訊息,因為有可能是別人偽裝支付寶發出的支付成功的訊息,這樣,就會造成損失。
/// <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 = "true";
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;
}
}
如果驗證成功,獲取交易的狀態
if (Request.Form["trade_status"] == "TRADE_FINISHED")
{
//判斷該筆訂單是否在商戶網站中已經做過處理
//如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程式
//如果有做過處理,不執行商戶的業務程式
//注意:
//退款日期超過可退款期限後(如三個月可退款),支付寶系統傳送該交易狀態通知
}
else if (Request.Form["trade_status"] == "TRADE_SUCCESS")
{
//判斷該筆訂單是否在商戶網站中已經做過處理
//如果沒有做過處理,根據訂單號(out_trade_no)在商戶網站的訂單系統中查到該筆訂單的詳細,並執行商戶的業務程式
//如果有做過處理,不執行商戶的業務程式
}
}
如果你的回撥地址,沒收到請求,支付寶會一直給你發訊息,好像是一共發9次還是幾次,忘記了,最後處理完,也要給支付寶發一個接收成功的訊息,表明我接收到了回撥。