.Net後臺實現支付寶APP支付

前面討論了微信支付,接下來聊聊支付寶的APP支付(新款支付寶支付)。其實這些支付原理都同樣,只不過具體到每一個支付平臺,所使用的支付配置參數不一樣,返回至支付端的下單參數也不一樣。算法

話很少說,直接上代碼。json

在App.Pay項目中使用NuGet管理器添加引用Alipay.AopSdk,也能夠不添加引用,將官方SDK源碼放至項目中。數組

添加完引用後,咱們就能夠開工了,新建文件夾AliPay,在文件夾中新建AliPayConfig類,存放支付寶APP支付所需的參數,一樣,這些參數我也放在了配置文件中。服務器

 1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6 using System.Web.Configuration;  7 
 8 namespace App.Pay.AliPay  9 { 10     public class AliPayConfig 11  { 12         //支付寶網關地址
13         public static string serviceUrl = WebConfigurationManager.AppSettings["aliServiceUrl"].ToString(); 14 
15         //應用ID
16         public static string appId = WebConfigurationManager.AppSettings["aliAppId"].ToString(); 17 
18         //開發者私鑰,由開發者本身生成
19         public static string privateKey = WebConfigurationManager.AppSettings["aliPrivateKey"].ToString(); 20 
21         //支付寶的應用公鑰
22         public static string publicKey = WebConfigurationManager.AppSettings["aliPublicKey"].ToString(); 23 
24         //支付寶的支付公鑰
25         public static string payKey = WebConfigurationManager.AppSettings["aliPayKey"].ToString(); 26 
27         //服務器異步通知頁面路徑
28         public static string notify_url = WebConfigurationManager.AppSettings["aliNotifyUrl"].ToString(); 29 
30         //頁面跳轉同步通知頁面路徑
31         public static string return_url = WebConfigurationManager.AppSettings["aliReturnUrl"].ToString(); 32 
33         //參數返回格式,只支持json
34         public static string format = WebConfigurationManager.AppSettings["aliFormat"].ToString(); 35 
36         // 調用的接口版本,固定爲:1.0
37         public static string version = WebConfigurationManager.AppSettings["aliVersion"].ToString(); 38 
39         // 商戶生成簽名字符串所使用的簽名算法類型,目前支持RSA2和RSA,推薦使用RSA2
40         public static string signType = WebConfigurationManager.AppSettings["aliSignType"].ToString(); 41 
42         // 字符編碼格式 目前支持utf-8
43         public static string charset = WebConfigurationManager.AppSettings["aliCharset"].ToString(); 44 
45         // false 表示不從文件加載密鑰
46         public static bool keyFromFile = false; 47 
48         // 日誌記錄
49         public static string LogPath = WebConfigurationManager.AppSettings["AliLog"].ToString(); 50  } 51 }
View Code

 支付寶支付中有個沙箱測試環境,咱們能夠先在沙箱環境下調通整個流程(沙箱支付寶裏面的錢是虛擬的哦)。介紹一下這幾個支付參數。微信

  ①aliServiceUrl支付寶網關地址,固定不變的,沙箱環境下用沙箱的,正式環境下用正式的。app

  ②aliAppId支付寶APPID,aliPrivateKey支付寶應用私鑰,aliPublicKey支付寶應用公鑰,aliPayKey支付寶公鑰dom

    aliPublicKey和aliPayKey是不同的,一個是應用公鑰,一個是支付寶公鑰,回調接口中驗籤使用的是支付寶公鑰異步

  ③aliNotifyUrl服務器通知,aliReturnUrl網頁重定向通知(暫時沒有用到)。主要使用到的仍是aliNotifyUrl,買家付完款後(trade_status=WAIT_SELLER_SEND_GOODS),支付寶服務端會自動向商戶後臺發送支付回調通知,一樣,商戶在支付回調通知中修改訂單相關狀態,反饋給支付寶success,表示成功接收到回調,這個狀態下支付寶不會再繼續通知商戶後臺。ide

  ④aliFormat、aliVersion、aliSignType、aliCharset這幾個參數都是固定不變的,簽名的時候使用。測試

 1 <!--支付寶app支付-->
 2     <add key="aliServiceUrl" value=""/>
 3     <add key="aliAppId" value="" />
 4     <add key="aliPrivateKey" value=""/>
 5     <add key="aliPublicKey" value="" />
 6     <add key="aliPayKey" value="" />
 7     <add key="aliNotifyUrl" value="" />
 8     <add key="aliReturnUrl" value="" />
 9     <add key="aliFormat" value="json" />
10     <add key="aliVersion" value="1.0" />
11     <add key="aliSignType" value="RSA2" />
12     <add key="aliCharset" value="utf-8" />
View Code

新建AliPay類

 1 using Aop.Api;  2 using System;  3 using System.Collections.Generic;  4 using System.Linq;  5 using System.Text;  6 using System.Threading.Tasks;  7 
 8 namespace App.Pay.AliPay  9 { 10     public class AliPay 11  { 12         public static IAopClient GetAlipayClient() 13  { 14             string serviceUrl = AliPayConfig.serviceUrl; 15 
16             string appId = AliPayConfig.appId; 17 
18             string privateKey = AliPayConfig.privateKey; 19 
20             string publivKey = AliPayConfig.publicKey; 21 
22             string format = AliPayConfig.format; 23 
24             string version = AliPayConfig.version; 25 
26             string signType = AliPayConfig.signType; 27 
28             string charset = AliPayConfig.charset; 29 
30             bool keyFromFile = AliPayConfig.keyFromFile; 31 
32 
33             IAopClient client = new DefaultAopClient(serviceUrl, appId, privateKey, format, version, signType, publivKey, charset, keyFromFile); ; 34 
35             return client; 36  } 37  } 38 }
View Code

接下來就是業務中的具體調用

 1 using Aop.Api;  2 using Aop.Api.Domain;  3 using Aop.Api.Request;  4 using Aop.Api.Response;  5 using Aop.Api.Util;  6 using App.Common.Extension;  7 using App.Pay.AliPay;  8 using System;  9 using System.Collections.Generic;  10 using System.Collections.Specialized;  11 using System.Linq;  12 using System.Web;  13 using System.Web.Mvc;  14 
 15 namespace App.WebTest.Controllers  16 {  17     public class AliPayController : BaseController  18  {  19         /// <summary>
 20         /// 訂單編號  21         /// </summary>
 22         /// <param name="oidStr"></param>
 23         /// <returns></returns>
 24         public ActionResult AliPay(string oidStr)  25  {  26             #region 驗證訂單有效
 27 
 28             if (string.IsNullOrEmpty(oidStr))  29  {  30                 return Json(false, "OrderError");  31  }  32 
 33             int[] oIds = Serialize.JsonTo<int[]>(oidStr);  34 
 35             decimal payPrice = 0;  36 
 37             ///訂單驗證,統計訂單總金額
 38 
 39             #endregion
 40 
 41             #region 統一下單
 42             try
 43  {  44                 var notify_url = AliPayConfig.notify_url;  45                 var return_url = AliPayConfig.return_url;  46                 IAopClient client = Pay.AliPay.AliPay.GetAlipayClient();  47                 AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();  48                 //SDK已經封裝掉了公共參數,這裏只須要傳入業務參數。如下方法爲sdk的model入參方式(model和biz_content同時存在的狀況下取biz_content)。
 49                 AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();  50                 model.Subject = "商品購買";  51                 model.TotalAmount = payPrice.ToString("F2");  52                 model.ProductCode = "QUICK_MSECURITY_PAY";  53                 Random rd = new Random();  54                 var payNum = DateTime.Now.ToString("yyyyMMddHHmmss") + rd.Next(0, 1000).ToString().PadLeft(3, '0');  55                 model.OutTradeNo = payNum;  56                 model.TimeoutExpress = "30m";  57  request.SetBizModel(model);  58  request.SetNotifyUrl(notify_url);  59                 //request.SetReturnUrl(return_url);  60                 //這裏和普通的接口調用不一樣,使用的是sdkExecute
 61                 AlipayTradeAppPayResponse response = client.SdkExecute(request);  62 
 63                 //統一下單  64                 //OrderBll.Value.UpdateOrderApp(oIds, payNum);
 65 
 66                 return Json(true, new { response.Body }, "OK");  67  }  68             catch (Exception ex)  69  {  70                 return Json(new { Result = false, msg = "缺乏參數" });  71  }  72             #endregion
 73  }  74 
 75         /// <summary>
 76         /// 頁面跳轉同步通知頁面  77         /// </summary>
 78         /// <returns></returns>
 79         public ActionResult ReturnUrl()  80  {  81             Pay.Log Log = new Pay.Log(Pay.AliPay.AliPayConfig.LogPath);  82             Log.Info("ReturnUrl", "支付頁面同步回調");  83             //將同步通知中收到的全部參數都存放到map中
 84             IDictionary<string, string> map = GetRequestGet();  85             if (map.Count > 0) //判斷是否有帶返回參數
 86  {  87                 try
 88  {  89                     //支付寶的公鑰
 90                     string alipayPublicKey = AliPayConfig.payKey;  91                     string signType = AliPayConfig.signType;  92                     string charset = AliPayConfig.charset;  93                     bool keyFromFile = false;  94                     // 獲取支付寶GET過來反饋信息 
 95                     bool verify_result = AlipaySignature.RSACheckV1(map, alipayPublicKey, charset, signType, keyFromFile);  96                     if (verify_result)  97  {  98                         // 驗證成功 
 99                         return Json(new { Result = true, msg = "驗證成功" }); 100  } 101                     else
102  { 103                         Log.Error("AliPayNotifyUrl", "支付驗證失敗"); 104                         return Json(new { Result = false, msg = "驗證失敗" }); 105  } 106  } 107                 catch (Exception e) 108  { 109                     //throw new Exception(e.Message);
110                     return Json(new { Result = false, msg = "驗證失敗" }); 111                     Log.Error("AliPayNotifyUrl", "支付驗證失敗"); 112  } 113  } 114             else
115  { 116                 return Json(new { Result = false, msg = "無返回參數" }); 117  } 118  } 119 
120         /// <summary>
121         /// 服務器異步通知頁面 122         /// </summary>
123         public void AliPayNotifyUrl() 124  { 125             Pay.Log Log = new Pay.Log(AliPayConfig.LogPath); 126             Log.Info("AliPayNotifyUrl", "支付頁面異步回調"); 127             IDictionary<string, string> map = GetRequestPost(); 128 
129             if (map.Count > 0) 130  { 131                 try
132  { 133                     string alipayPublicKey = AliPayConfig.payKey; 134                     string signType = AliPayConfig.signType; 135                     string charset = AliPayConfig.charset; 136                     bool keyFromFile = false; 137 
138                     bool verify_result = AlipaySignature.RSACheckV1(map, alipayPublicKey, charset, signType, keyFromFile); 139                     Log.Info("AliPayNotifyUrl驗籤", verify_result + ""); 140 
141                     //驗籤成功後,按照支付結果異步通知中的描述,對支付結果中的業務內容進行二次校驗,校驗成功後再response中返回success並繼續商戶自身業務處理,校驗失敗返回false
142                     if (verify_result) 143  { 144                         //商戶訂單號
145                         string out_trade_no = map["out_trade_no"]; 146                         //支付寶交易號
147                         string trade_no = map["trade_no"]; 148                         //交易建立時間
149                         string gmt_create = map["gmt_create"]; 150                         //交易付款時間
151                         string gmt_payment = map["gmt_payment"]; 152                         //通知時間
153                         string notify_time = map["notify_time"]; 154                         //通知類型 trade_status_sync
155                         string notify_type = map["notify_type"]; 156                         //通知校驗ID
157                         string notify_id = map["notify_id"]; 158                         //開發者的app_id
159                         string app_id = map["app_id"]; 160                         //賣家支付寶用戶號
161                         string seller_id = map["seller_id"]; 162                         //買家支付寶用戶號
163                         string buyer_id = map["buyer_id"]; 164                         //實收金額
165                         string receipt_amount = map["receipt_amount"]; 166                         //交易狀態
167                         string return_code = map["trade_status"]; 168 
169                         //交易狀態TRADE_FINISHED的通知觸發條件是商戶簽約的產品不支持退款功能的前提下,買家付款成功; 170                         //或者,商戶簽約的產品支持退款功能的前提下,交易已經成功而且已經超過可退款期限 171                         //狀態TRADE_SUCCESS的通知觸發條件是商戶簽約的產品支持退款功能的前提下,買家付款成功
172                         if (return_code == "TRADE_FINISHED" || return_code == "TRADE_SUCCESS") 173  { 174                             string msg; 175 
176                             Log.Error("AliPayNotifyUrl", receipt_amount + "==" + trade_no + "==" + return_code + "==" + out_trade_no + "==" + gmt_payment); 177 
178                             //判斷該筆訂單是否在商戶網站中已經作過處理
179                             ///支付回調的業務處理
180                             //bool res = OrderBll.Value.CompleteAliPay(receipt_amount, trade_no, return_code, out_trade_no, gmt_payment, out msg);
181                             bool res = true; 182 
183                             if (res == false) 184  { 185                                 Response.Write("添加支付信息失敗!"); 186  } 187                             Log.Error("AliPayNotifyUrl", "支付成功"); 188                             Response.Write("success");  //請不要修改或刪除
189  } 190  } 191                     else
192  { 193                         //驗證失敗
194                         Log.Error("AliPayNotifyUrl", "支付驗證失敗"); 195                         Response.Write("驗證失敗!"); 196  } 197  } 198                 catch (Exception e) 199  { 200                     Response.Write("添加支付信息失敗!"); 201                     Log.Error("AliPayNotifyUrl", "添加支付信息失敗"); 202  } 203  } 204             else
205  { 206                 //無返回參數
207                 Response.Write("無返回參數!"); 208                 Log.Error("AliPayNotifyUrl", "無返回參數"); 209  } 210  } 211         //[AllowUser] 212         //public ActionResult TestAliPay() 213         //{ 214 
215         // var receipt_amount = "0.01"; 216         // var trade_no = "20181226220013......."; 217         // var return_code = "TRADE_SUCCESS"; 218         // var out_trade_no = "20181226103124129"; 219         // var gmt_payment = "2018-12-26 10:31:29"; 220 
221         // string msg = ""; 222         // bool res = OrderBll.Value.CompleteAliPay(receipt_amount, trade_no, return_code, out_trade_no, gmt_payment, out msg); 223 
224         // return Json(res); 225         //}
226 
227         /// <summary>
228         /// 獲取支付寶Get過來的通知消息,並以「參數名=參數值」的形式組成數組 229         /// </summary>
230         /// <returns></returns>
231         public IDictionary<string, string> GetRequestGet() 232  { 233             Pay.Log Log = new Pay.Log(Pay.AliPay.AliPayConfig.LogPath); 234             int i = 0; 235             IDictionary<string, string> sArry = new Dictionary<string, string>(); 236  NameValueCollection coll; 237             coll = Request.QueryString; 238 
239             String[] requstItem = coll.AllKeys; 240 
241             for (i = 0; i < requstItem.Length; i++) 242  { 243                 Log.Info("GetRequestGet", requstItem[i] + ":" + Request.QueryString[requstItem[i]]); 244  sArry.Add(requstItem[i], Request.QueryString[requstItem[i]]); 245  } 246 
247             return sArry; 248  } 249 
250         /// <summary>
251         /// 獲取支付寶POST過來通知消息,並以「參數名=參數值」的形式組成數組 252         /// </summary>
253         /// <returns>request回來的信息組成的數組</returns>
254         public IDictionary<string, string> GetRequestPost() 255  { 256             Pay.Log Log = new Pay.Log(Pay.AliPay.AliPayConfig.LogPath); 257             int i = 0; 258             IDictionary<string, string> sArray = new Dictionary<string, string>(); 259  NameValueCollection coll; 260 
261             //Load Form variables into NameValueCollection variable.
262             coll = Request.Form; 263 
264             // Get names of all forms into a string array.
265             String[] requestItem = coll.AllKeys; 266             for (i = 0; i < requestItem.Length; i++) 267  { 268                 Log.Info("GetRequestPost", requestItem[i] + ":" + Request.Form[requestItem[i]]); 269  sArray.Add(requestItem[i], Request.Form[requestItem[i]]); 270  } 271 
272             return sArray; 273  } 274  } 275 }
View Code
相關文章
相關標籤/搜索