已经很久没有搞过.NET了,朋友有一个网站 ,须要接入支付宝功能,从新对接了一下。web
一、开发前,须要一个企业支付宝帐号登陆,获取 PID和 配置密钥json
官方文档:https://docs.open.alipay.com/62/104743/app
二、下载官方的服务端代码异步
官方下载地址:https://docs.open.alipay.com/270/106291/xss
这里要注意一下,官方的服务端代码,是没有工程文件的,须要在vs2013中,打开-网站,加载整个文件。配置pid和ras密钥,是能够跑起来的,效果还不错,支付和退款的功能都有了。ide
三、官方给过来的是webform的代码,改为MVC也很简单,代码以下post
支付和回调通知:网站
namespace YinCai.Web.Controllers { public class AlipayController : BaseController { // // GET: /Alipay/ public ActionResult Pay(int Id) { ScOrder orderModel = BLLSession.IScOrderService.GetOne(m => m.OrderID == Id); DefaultAopClient client = new DefaultAopClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", "1.0", AlipayConfig.sign_type, AlipayConfig.alipay_public_key, AlipayConfig.charset, false); // 外部订单号,商户网站订单系统中惟一的订单号 string out_trade_no = orderModel.OrderNo.ToString(); // 订单名称 string subject = orderModel.OrderName; // 付款金额 string total_amout = orderModel.PayPrice.ToString(); // 商品描述 string body = ""; // 组装业务参数model AlipayTradePagePayModel model = new AlipayTradePagePayModel(); model.Body = body; model.Subject = subject; model.TotalAmount = total_amout; model.OutTradeNo = out_trade_no; model.ProductCode = "FAST_INSTANT_TRADE_PAY"; AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); // 设置同步回调地址 request.SetReturnUrl(Common.ConfigHelper.AlipayReturnUrl); // 设置异步通知接收地址 request.SetNotifyUrl(Common.ConfigHelper.AlipayNotifyUrl); // 将业务model载入到request request.SetBizModel(model); AlipayTradePagePayResponse response = null; try { response = client.pageExecute(request, null, "post"); string rep = response.Body.Replace("<input", "<input type='hidden'"); return Content(rep); } catch (Exception exp) { Common.LogHelper.WriteLog(exp, "支付宝跳转失败!"); throw exp; } } // 支付宝异步通知 // gmt_create=2019-09-01+14%3a12%3a35&charset=UTF-8&gmt_payment=2019-09-01+14%3a12%3a38¬ify_time=2019-09-01+14%3a12%3a39&subject=1&sign=XNAQMiLoXKxUoZEfiSkNxmiBJDnw5xszNiFuu20XQzmnLbwuwDXVFsaYaR8OtV6qD%2bsymeZjSfm0%2fvAY1q7V2QiyTtMqnvBG23nbeklLxGvY2GKOKnULI8M7Wl9dJs70bbMsENhEY1ATOLpqven2dcJJkLIwIHec%2fKgU4EdrEbR7nNaa89m3iDkO6wd3uKyrBvhfE208kPbJc62AGPa46V1HvzmtL66kbgPVBG9K7yI5En%2ba1y6fMs%2fmOJecrNt%2bozXcw0Bkw2P47a9A5drkH1wakkiK3a4SOsJekb7mr1jtphSLIaq5SoImwZsFLtnM6Hjrl8lhUTjl9jQrwPAFzw%3d%3d&buyer_id=2088302047105765&invoice_amount=0.01&version=1.0¬ify_id=2019090100222141238005760509611566&fund_bill_list=%5b%7b%22amount%22%3a%220.01%22%2c%22fundChannel%22%3a%22ALIPAYACCOUNT%22%7d%5d¬ify_type=trade_status_sync&out_trade_no=2019090110003&total_amount=0.01&trade_status=TRADE_SUCCESS&trade_no=2019090122001405760595489512&auth_app_id=2019082266394313&receipt_amount=0.01&point_amount=0.00&buyer_pay_amount=0.01&app_id=2019082266394313&sign_type=RSA2&seller_id=2088631096812893 public ActionResult Notify() { Common.LogHelper.WriteInfoLog("支付宝回调通知---" + Request.Form.ToString()); /* 实际验证过程建议商户添加如下校验。 一、商户须要验证该通知数据中的out_trade_no是否为商户系统中建立的订单号, 二、判断total_amount是否确实为该订单的实际金额(即商户订单建立时的金额), 三、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操做方(有的时候,一个商户可能有多个seller_id/seller_email) 四、验证app_id是否为该商户自己。 */ long orderno = long.Parse(Request["out_trade_no"]); string appId = Request["app_id"]; //string seller_id = Request.Form["seller_id"]; string totalAmount = Request["total_amount"]; ScOrder orderModel = BLLSession.IScOrderService.GetOne(m => m.OrderNo == orderno); if (orderModel == null || appId != AlipayConfig.app_id || orderModel.PayPrice != decimal.Parse(totalAmount)) { Common.LogHelper.WriteLog("支付宝回调信息异常" + Request.Form.ToString()); return Content("fail"); ; } Dictionary<string, string> sArray = GetRequestPost(); if (sArray.Count != 0) { bool flag = AlipaySignature.RSACheckV1(sArray, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type, false); if (flag) { //交易状态 //判断该笔订单是否在商户网站中已经作过处理 //若是没有作过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //请务必判断请求时的total_amount与通知时获取的total_fee为一致的 //若是有作过处理,不执行商户的业务程序 //注意: //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 string trade_status = Request["trade_status"]; orderModel.PayNotifyTime = DateTime.Now; BLLSession.IScOrderService.ModifyModel(orderModel); Common.LogHelper.WriteInfoLog("支付宝验签成功,支付成功---" + orderno); return Content("success"); } else { //Response.Write("fail"); Common.LogHelper.WriteLog("支付宝回调通知验签失败---" + Request.Form.ToString()); return Content("fail"); } } return Content("fail"); } // 支付宝同步通知,支付成功页 ReturnUrl // /alipay/PaySuccess/2019090110021?charset=UTF-8&out_trade_no=2019090110021&method=alipay.trade.page.pay.return&total_amount=0.01&sign=fUsyiAQiFSpHOmBn%2Bd0QZbdfdGyXtfIHYeZziKIpJGJpa38L7Jx1C4jnaCRuYuqTnMvawwg0ExqXpT6T88BPTdjK5Rcm9tL6zL8U8N%2B7lHEMyPMT2LaiuFAGzmnlSZyVJleGdUEzgvQZ3jbX9OdZEpLFOVyRnj8Ax%2B%2BlW5M9oInyncCg6VBw2%2BbDG5m8epPyBFUIBWxQINcyKrCDbDFwVIxGjji%2FW11adC7il8earoOB4gXKArxVB7SVYZcHXjiONZJEXyRMMuscD4ZV%2FPwH3Wtf5BUv%2BHtHqJWr8a5u9ijZCI7GzZwUdDYKnOamqp7HMFychsrUgAAcVPfdjAxe%2Bg%3D%3D&trade_no=2019090122001405760597459839&auth_app_id=2019082266394313&version=1.0&app_id=2019082266394313&sign_type=RSA2&seller_id=2088631096812893×tamp=2019-09-01+18%3A18%3A20 public ActionResult PaySuccess() { Common.LogHelper.WriteLog("支付宝同步验证参数----" + Request.RawUrl); long orderno = long.Parse(Request["out_trade_no"]); string appId = Request["app_id"]; string totalAmount = Request["total_amount"]; ScOrder orderModel = BLLSession.IScOrderService.GetOne(m => m.OrderNo == orderno); if (orderModel == null || appId != AlipayConfig.app_id || orderModel.PayPrice != decimal.Parse(totalAmount)) { Common.LogHelper.WriteLog("支付宝同步验证异常----" + Request.RawUrl); return RedirectToAction("payfail","alipay"); } /* 实际验证过程建议商户添加如下校验。 一、商户须要验证该通知数据中的out_trade_no是否为商户系统中建立的订单号, 二、判断total_amount是否确实为该订单的实际金额(即商户订单建立时的金额), 三、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操做方(有的时候,一个商户可能有多个seller_id/seller_email) 四、验证app_id是否为该商户自己。 */ Dictionary<string, string> sArray = GetRequestGet(); if (sArray.Count != 0) { bool flag = AlipaySignature.RSACheckV1(sArray, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type, false); if (flag) { string trade_no = Request["trade_no"]; orderModel.OrderStatus = (int)OrderStateEnum.Paid; orderModel.PayType = (int)PayTypeEnum.Alipay; orderModel.PayTime = DateTime.Now; orderModel.PayTradeNo = trade_no; BLLSession.IScOrderService.ModifyModel(orderModel); } else { Common.LogHelper.WriteLog("支付宝同步验证失败----" + Request.RawUrl); return RedirectToAction("payfail", "alipay"); } } return View(orderModel); } public ActionResult PayFail() { return View(); } #region --参数获取组装 // get 方式组装回调参数 public Dictionary<string, string> GetRequestGet() { int i = 0; Dictionary<string, string> sArray = new Dictionary<string, string>(); NameValueCollection coll; //coll = Request.Form; coll = Request.QueryString; String[] requestItem = coll.AllKeys; for (i = 0; i < requestItem.Length; i++) { sArray.Add(requestItem[i], Request.QueryString[requestItem[i]]); } return sArray; } // post 方式组装回调参数 public Dictionary<string, string> GetRequestPost() { int i = 0; Dictionary<string, string> sArray = new Dictionary<string, string>(); NameValueCollection coll; //coll = Request.Form; coll = Request.Form; String[] requestItem = coll.AllKeys; for (i = 0; i < requestItem.Length; i++) { sArray.Add(requestItem[i], Request.Form[requestItem[i]]); } return sArray; } #endregion } }
退款:ui
// 退款成功返回 //{"alipay_trade_refund_response":{"code":"10000","msg":"Success","buyer_logon_id":"jys***@163.com","buyer_user_id":"2088302047105765","fund_change":"Y","gmt_refund_pay":"2019-09-01 16:08:02","out_trade_no":"2019090110004","refund_fee":"0.01","send_back_fee":"0.00","trade_no":"2019090122001405760597435123"},"sign":"IL+00djGKL/7UBxQS9oTPwKySlzHrnZLtzsqbH1ZkyAgv8E2Hl+PZZtbVAnH7+7XtpfLDxwY+4EyN0EmL75reU3fiBmpmL9JROsCQy2hQG4WmeSB2GKg2kFyAgmOh7uoYbKW/HWV35NfxdpoCZNdGyYWWhxIz0qui2xIH3u46WPBN5Yk5uMmhNNzUP8pW18XxssI7htqD3ey7qagntwPFTlL5JeUmz8Fbusk+xQJ3p6wj58IHetm2Mio1KDSEZblE/2+T7ZkgrBrQqw77Y4DpCi8m98MFMdAMCQ/3qiWH65H4cPPXXrQ2pprVLA6m8DjmPhzsuYk7noyHYJo4uMFwg=="} [HttpPost] public ActionResult Refund(int Id) { ScOrder orderModel = BLLSession.IScOrderService.GetOne(m=>m.OrderID == Id); if (orderModel == null) { return JsonMsgErr("退款出错拉"); } DefaultAopClient client = new DefaultAopClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", "1.0", AlipayConfig.sign_type, AlipayConfig.alipay_public_key, AlipayConfig.charset, false); // 商户订单号,和交易号不能同时为空 string out_trade_no = orderModel.OrderNo.ToString(); // 支付宝交易号,和商户订单号不能同时为空 string trade_no = orderModel.PayTradeNo; // 退款金额,不能大于订单总金额 string refund_amount = orderModel.PayPrice.ToString(); // 退款缘由 string refund_reason = "正常退款"; // 退款单号,同一笔屡次退款须要保证惟一,部分退款该参数必填。 string out_request_no = orderModel.OrderNo.ToString(); AlipayTradeRefundModel model = new AlipayTradeRefundModel(); model.OutTradeNo = out_trade_no; model.TradeNo = trade_no; model.RefundAmount = refund_amount; model.RefundReason = refund_reason; model.OutRequestNo = out_request_no; AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); request.SetBizModel(model); AlipayTradeRefundResponse response = null; try { response = client.Execute(request); Common.LogHelper.WriteInfoLog("支付宝退款成功---" + response.Body); RefundModel refundModel = JsonConvert.DeserializeObject<RefundModel>(response.Body); string code = refundModel.alipay_trade_refund_response.code; // 能够重复退款,因此不须要判断fund_change string fund_change = refundModel.alipay_trade_refund_response.fund_change; if (code == "10000") { orderModel.RefundTime = DateTime.Now; orderModel.RefundReason = "正常退款"; orderModel.OrderStatus = (int)OrderStateEnum.Refund; BLLSession.IScOrderService.ModifyModel(orderModel); return JsonMsgOk("退款成功"); } } catch (Exception exp) { throw exp; } return JsonMsgOk("退款失败"); }