.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
相关文章
相关标签/搜索