.Net后台实现支付宝APP支付

前面讨论了微信支付,接下来聊聊支付宝的APP支付(新款支付宝支付)。其实这些支付原理都一样,只不过具体到每个支付平台,所使用的支付配置参数不同,返回至支付端的下单参数也不同。

话不多说,直接上代码。

在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支付宝网关地址,固定不变的,沙箱环境下用沙箱的,正式环境下用正式的。

  ②aliAppId支付宝APPID,aliPrivateKey支付宝应用私钥,aliPublicKey支付宝应用公钥,aliPayKey支付宝公钥

    aliPublicKey和aliPayKey是不一样的,一个是应用公钥,一个是支付宝公钥,回调接口中验签使用的是支付宝公钥

  ③aliNotifyUrl服务器通知,aliReturnUrl网页重定向通知(暂时没有用到)。主要使用到的还是aliNotifyUrl,买家付完款后(trade_status=WAIT_SELLER_SEND_GOODS),支付宝服务端会自动向商户后台发送支付回调通知,同样,商户在支付回调通知中修改订单相关状态,反馈给支付宝success,表示成功接收到回调,这个状态下支付宝不会再继续通知商户后台。

  ④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
原文地址:https://www.cnblogs.com/wenha/p/10263518.html