zoukankan      html  css  js  c++  java
  • .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
  • 相关阅读:
    JVM工作原理--垃圾收集
    并发编程之单例模式
    设计模式之动态代理
    UML类图基础
    CAP理论的理解
    Dubbo RPC调用参数校验---错误message自动返回
    ELK日志分析系统搭建
    Kafka原理及应用(一)
    HTTPS的原理
    Maven 生命周期的概念(指令默认顺序执行)
  • 原文地址:https://www.cnblogs.com/wenha/p/10263518.html
Copyright © 2011-2022 走看看