using Alipay.AopSdk.Core; using Alipay.AopSdk.Core.Domain; using Alipay.AopSdk.Core.Request; using Alipay.AopSdk.Core.Util; using Hncore.Infrastructure.Common; using Hncore.Infrastructure.Serializer; using Hncore.Infrastructure.WebApi; using Hncore.Pass.PaymentCenter.Model; using Hncore.Pass.PaymentCenter.Pay.WxPay; using Hncore.Pass.PaymentCenter.WxPay.WechatJsPay; using Hncore.Pass.Vpn.Domain; using Hncore.Pass.Vpn.Request.Product; using Hncore.Pass.Vpn.Response.Product; using Hncore.Pass.Vpn.Service; using Home.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Linq; using Hncore.Infrastructure.Extension; namespace Home.Controllers { public class productController : MvcBaseController { string Ali_APP_ID =""; string Ali_APP_PRIVATE_KEY = ""; string ALIPAY_PUBLIC_KEY = ""; string Wx_AppId = ""; string Wx_MchId = ""; string Wx_MchKey = ""; ProductService m_ProductService; ProductPackageService m_ProductPackageService; private ProductOrderService m_ProductOrderService; private IConfiguration m_Configuration; private WxPayClient m_WxPayClient; ProductAccountService m_ProductAccountService; WxAppUserService m_WxAppUserService; UserService m_UserService; ProductUserPriceService m_ProductUserPriceService; public productController(ProductService _ProductService , ProductOrderService _ProductOrderService , ProductPackageService _ProductPackageService , WxPayClient _WxPayClient ,ProductAccountService _ProductAccountService , WxAppUserService _WxAppUserService ,UserService _UserService , ProductUserPriceService _ProductUserPriceService , IConfiguration _Configuration) { m_ProductService = _ProductService; m_ProductOrderService = _ProductOrderService; m_ProductPackageService = _ProductPackageService; m_Configuration = _Configuration; m_WxPayClient = _WxPayClient; Ali_APP_ID = m_Configuration["Aliyun:Pay:AppId"]; Ali_APP_PRIVATE_KEY = m_Configuration["Aliyun:Pay:PrivateKey"]; ALIPAY_PUBLIC_KEY = m_Configuration["Aliyun:Pay:PublicKey"];//支付宝的公钥,而不是应用的公钥 Wx_AppId = m_Configuration["WxApps:AppID"]; Wx_MchId = m_Configuration["WxApps:MchId"]; Wx_MchKey = m_Configuration["WxApps:MchKey"]; m_ProductAccountService = _ProductAccountService; m_WxAppUserService = _WxAppUserService; m_UserService = _UserService; m_ProductUserPriceService = _ProductUserPriceService; } [HttpGet] public async Task Index() { var respList = await m_ProductService.ProductWithPackage(1); var userInfo = this.Request.GetUserInfo(); if (userInfo != null) { var userPrices = await m_ProductUserPriceService.GetProductUserPrice(userInfo.UserId); foreach(var product in respList) { product.Packages.ForEach(m => { var userPrice = userPrices.FirstOrDefault(p => p.PackageId == m.Id && p.ProductId == m.ProductId); if (userPrice != null && userPrice.UserPrice > 0) { m.Price = userPrice.UserPrice; } }); } } return View(respList); } [HttpPost,UserAuth] public async Task CreateOrder([FromBody]CreateOrderRequest request) { var userId = this.Request.GetUserInfo().UserId; var ret = await m_ProductOrderService.CreateOrder(request, userId); if (ret.Code != ResultCode.C_SUCCESS) { return ret; } if (ret.Data.OtherPayAmount == 0) { await m_ProductOrderService.ProcessOrderAccount(ret.Data); return new ApiResult("00"); } var data = new OrderPayModel() { OrderInfo = ret.Data, }; if (ret.Data.PayType == PayType.Wechat) { var url = await CreateWxPayOrder(ret.Data); data.PayData = url; return new ApiResult(data); } else { var body = await CreateAliPayOrder(ret.Data); data.PayData = body; } return new ApiResult(data); } #region 微信支付 private async Task CreateWxPayOrder(ProductOrderEntity request) { string callBackUrl = m_Configuration["NotifyUrl"]; var mchInfo = new MchInfo() { MchId = Wx_MchId, Key = Wx_MchKey }; var createOrderRes = ""; var pName=request.Accounts.Split(",").FirstOrDefault(); var oName = $"{request.ProductName}-{request.PackageName}"; if (pName.Has()) oName = $"{oName}-{pName}"; if (request.PayChannel == PayChannel.WxPc) { var payRequest = new WxScanPayCreateOrderRequest() { AppId = Wx_AppId, Body = oName, MchId = Wx_MchId, NotifyUrl = callBackUrl, OutTradeNo = request.OrderNo, StoreId = 2, TenantId = 1157, TotalFee = (int)(request.OtherPayAmount * 100), ProductId = request.ProductId.ToString(), TimeExpire=DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss") }; createOrderRes = await m_WxPayClient.ScanPayCreateOrderAsync(payRequest, mchInfo); } else if (request.PayChannel == PayChannel.WxH5) { var payRequest = new WxH5PayCreateOrderRequest() { AppId = Wx_AppId, Body = oName, MchId = Wx_MchId, NotifyUrl = callBackUrl, OutTradeNo = request.OrderNo, StoreId = 2, TenantId = 1157, TotalFee = (int)(request.OtherPayAmount * 100), ProductId = request.ProductId.ToString(), TimeExpire = DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss") }; createOrderRes = await m_WxPayClient.H5PayCreateOrderAsync(payRequest, mchInfo); } else { var wxUserInfo = await m_WxAppUserService.GetWxUser(Wx_AppId, request.UserId); var payRequest = new WxJsPayCreateOrderRequest() { AppId = Wx_AppId, Body = oName, MchId = Wx_MchId, NotifyUrl = callBackUrl, OutTradeNo = request.OrderNo, StoreId = 2, TenantId = 1157, TotalFee = (int)(request.OtherPayAmount * 100), UserOpenId = wxUserInfo.Openid, TimeExpire = DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss") }; createOrderRes = await m_WxPayClient.JsPayCreateOrderAsync(payRequest, mchInfo); } return createOrderRes; } [HttpPost, AllowAnonymous] public async Task WxOrderCallBack() { try { string xml = ""; LogHelper.Trace("微信支付回调开始", "Notify"); if (Request.Body.CanSeek) { Request.Body.Position = 0; } using (System.IO.StreamReader reader = new System.IO.StreamReader(Request.Body)) { xml = reader.ReadToEnd(); } LogHelper.Trace("微信支付回调,原始数据:", $"{xml}"); WxPayChecker payData = new WxPayChecker(); payData.FromXmlNoCheckSign(xml); if (!payData.IsSet("out_trade_no")) { return FailXml(); } // 给支付平台的订单号为支付记录id string orderId = payData["out_trade_no"]; string TransactionId = payData["transaction_id"]; var order = await m_ProductOrderService.GetOrderByNo(orderId); if(order.OrderState== OrderStatus.Complete|| order.OrderState == OrderStatus.PayOk) return SuccessXml(); var queryRet = await m_WxPayClient.OrderQuery(new WxJsPayOrderQueryRequest() { AppId = Wx_AppId, NonceStr = payData.GenerateNonceStr(), TransactionId = TransactionId }, new MchInfo() { MchId = Wx_MchId, Key = Wx_MchKey }); if (!queryRet) return FailXml(); payData.MchKey = Wx_MchKey; if (!payData.CheckSign()) return FailXml(); order.OrderState = OrderStatus.PayOk; order.TradeNo = TransactionId; order.UpdateTime = DateTime.Now; await m_ProductOrderService.Update(order); await m_ProductOrderService.ProcessOrderAccount(order); } catch (Exception e) { LogHelper.Error("微信支付通知处理失败", e); return FailXml(); } return SuccessXml(); } public string FailXml() { return "FAIL "; } private string SuccessXml() { return "SUCCESS "; } #endregion #region 阿里支付 private async Task CreateAliPayOrder(ProductOrderEntity request) { string callBackUrl = m_Configuration["Aliyun:Pay:NotifyUrl"]; string ReturnUrl = m_Configuration["Aliyun:Pay:ReturnUrl"]; var pName = request.Accounts.Split(",").FirstOrDefault(); var oName = $"{request.ProductName}-{request.PackageName}"; if (pName.Has()) oName = $"{oName}-{pName}"; if (request.PayChannel == PayChannel.AliPc) { // 组装业务参数model AlipayTradePagePayModel model = new AlipayTradePagePayModel { Body = request.PackageName, Subject = oName, TotalAmount = request.OtherPayAmount.ToString(), OutTradeNo = request.OrderNo, ProductCode = "FAST_INSTANT_TRADE_PAY",//QUICK_WAP_PAY TimeoutExpress="15m" }; AlipayTradePagePayRequest aliRequest = new AlipayTradePagePayRequest(); // 设置同步回调地址 aliRequest.SetReturnUrl(ReturnUrl); // 设置异步通知接收地址 aliRequest.SetNotifyUrl(callBackUrl); // 将业务model载入到request aliRequest.SetBizModel(model); var _aopClient = new DefaultAopClient("https://openapi.alipay.com/gateway.do", Ali_APP_ID, Ali_APP_PRIVATE_KEY); var response = await _aopClient.PageExecuteAsync(aliRequest); return response.Body; } else if (request.PayChannel == PayChannel.AliH5) { Ali_APP_ID = m_Configuration["Aliyun:PayH5:AppId"]; Ali_APP_PRIVATE_KEY = m_Configuration["Aliyun:PayH5:PrivateKey"]; ALIPAY_PUBLIC_KEY = m_Configuration["Aliyun:PayH5:PublicKey"]; callBackUrl = m_Configuration["Aliyun:PayH5:NotifyUrl"]; ReturnUrl = m_Configuration["Aliyun:PayH5:ReturnUrl"]; // 组装业务参数model AlipayTradeWapPayModel model = new AlipayTradeWapPayModel { Body = request.PackageName, Subject = oName, TotalAmount = request.OtherPayAmount.ToString(), OutTradeNo = request.OrderNo, ProductCode = "QUICK_WAP_PAY", QuitUrl =this.Request.GetUrl(), TimeoutExpress = "15m" }; AlipayTradeWapPayRequest aliRequest = new AlipayTradeWapPayRequest(); // 设置同步回调地址 aliRequest.SetReturnUrl(ReturnUrl); // 设置异步通知接收地址 aliRequest.SetNotifyUrl(callBackUrl); // 将业务model载入到request aliRequest.SetBizModel(model); var _aopClient = new DefaultAopClient("https://openapi.alipay.com/gateway.do", Ali_APP_ID, Ali_APP_PRIVATE_KEY); var response = await _aopClient.PageExecuteAsync(aliRequest); return response.Body; } return ""; } /// /// 支付同步回调 /// [HttpGet, AllowAnonymous] public IActionResult AliReturn() { /* 实际验证过程建议商户添加以下校验。 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号, 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额), 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email) 4、验证app_id是否为该商户本身。 */ Dictionary sArray = GetRequestGet(); if (sArray.Count != 0) { bool flag = AlipaySignature.RSACheckV2(sArray, ALIPAY_PUBLIC_KEY, "utf-8", "RSA2", false); if (flag) { var ordereNo = sArray["out_trade_no"]; // var order = await m_ProductOrderService.GetOrderByNo(ordereNo); Console.WriteLine($"同步验证通过,订单号:{sArray["out_trade_no"]}"); ViewData["PayResult"] = "同步验证通过"; } else { Console.WriteLine($"同步验证失败,订单号:{sArray["out_trade_no"]}"); ViewData["PayResult"] = "同步验证失败"; } } return Redirect("~/User/MyAccounts"); } [HttpPost, AllowAnonymous] public async Task AliNotify() { /* 实际验证过程建议商户添加以下校验。 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号, 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额), 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email) 4、验证app_id是否为该商户本身。 */ Dictionary sArray = GetRequestPost(); LogHelper.Info("AliNotify", AlipaySignature.GetSignContent(sArray)); if (sArray.Count != 0) { // bool flag = AlipaySignature.RSA2Check(sArray, ALIPAY_PUBLIC_KEY); bool flag = AlipaySignature.RSACheckV2(sArray, ALIPAY_PUBLIC_KEY, "utf-8", "RSA2", false); if (flag) { //交易状态 //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //请务必判断请求时的total_amount与通知时获取的total_fee为一致的 //如果有做过处理,不执行商户的业务程序 //注意: //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 try { var ordereNo = sArray["out_trade_no"]; var order = await m_ProductOrderService.GetOrderByNo(ordereNo); if (order.OrderState == OrderStatus.Complete|| order.OrderState == OrderStatus.PayOk) { await Response.WriteAsync("success"); return; } order.OrderState = OrderStatus.PayOk; order.TradeNo = sArray["trade_no"]; order.UpdateTime = DateTime.Now; await m_ProductOrderService.Update(order); await m_ProductOrderService.ProcessOrderAccount(order); Console.WriteLine(Request.Form["trade_status"]); await Response.WriteAsync("success"); }catch(Exception ex) { LogHelper.Error("AliNotify.Exception", ex.Message); await Response.WriteAsync("fail"); } } else { LogHelper.Error("AliNotify.Error", "签名校验失败"); await Response.WriteAsync("fail"); } } } /// /// 支付同步回调 /// [HttpGet, AllowAnonymous] public IActionResult AliReturnH5() { /* 实际验证过程建议商户添加以下校验。 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号, 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额), 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email) 4、验证app_id是否为该商户本身。 */ ALIPAY_PUBLIC_KEY = m_Configuration["Aliyun:PayH5:PublicKey"]; Dictionary sArray = GetRequestGet(); if (sArray.Count != 0) { bool flag = AlipaySignature.RSACheckV2(sArray, ALIPAY_PUBLIC_KEY, "utf-8", "RSA2", false); if (flag) { var ordereNo = sArray["out_trade_no"]; // var order = await m_ProductOrderService.GetOrderByNo(ordereNo); Console.WriteLine($"同步验证通过,订单号:{sArray["out_trade_no"]}"); ViewData["PayResult"] = "同步验证通过"; } else { Console.WriteLine($"同步验证失败,订单号:{sArray["out_trade_no"]}"); ViewData["PayResult"] = "同步验证失败"; } } return Redirect("~/User/MyAccounts"); } [HttpPost, AllowAnonymous] public async Task AliNotifyH5() { /* 实际验证过程建议商户添加以下校验。 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号, 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额), 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email) 4、验证app_id是否为该商户本身。 */ ALIPAY_PUBLIC_KEY = m_Configuration["Aliyun:PayH5:PublicKey"]; Dictionary sArray = GetRequestPost(); LogHelper.Info("AliNotify", AlipaySignature.GetSignContent(sArray)); if (sArray.Count != 0) { // bool flag = AlipaySignature.RSA2Check(sArray, ALIPAY_PUBLIC_KEY); bool flag = AlipaySignature.RSACheckV2(sArray, ALIPAY_PUBLIC_KEY, "utf-8", "RSA2", false); if (flag) { //交易状态 //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //请务必判断请求时的total_amount与通知时获取的total_fee为一致的 //如果有做过处理,不执行商户的业务程序 //注意: //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 try { var ordereNo = sArray["out_trade_no"]; var order = await m_ProductOrderService.GetOrderByNo(ordereNo); if (order.OrderState == OrderStatus.Complete || order.OrderState == OrderStatus.PayOk) { await Response.WriteAsync("success"); return; } order.OrderState = OrderStatus.PayOk; order.TradeNo = sArray["trade_no"]; order.UpdateTime = DateTime.Now; await m_ProductOrderService.Update(order); await m_ProductOrderService.ProcessOrderAccount(order); Console.WriteLine(Request.Form["trade_status"]); await Response.WriteAsync("success"); } catch (Exception ex) { LogHelper.Error("AliNotify.Exception", ex.Message); await Response.WriteAsync("fail"); } } else { LogHelper.Error("AliNotify.Error", "签名校验失败"); await Response.WriteAsync("fail"); } } } private Dictionary GetRequestGet() { Dictionary sArray = new Dictionary(); ICollection requestItem = Request.Query.Keys; foreach (var item in requestItem) { sArray.Add(item, Request.Query[item]); } return sArray; } private Dictionary GetRequestPost() { Dictionary sArray = new Dictionary(); ICollection requestItem = Request.Form.Keys; foreach (var item in requestItem) { sArray.Add(item, Request.Form[item]); } return sArray; } #endregion //[HttpGet] //public async Task Success() //{ // return Content("Success"); //} //[HttpGet] //public async Task ErrorInfo() //{ // return Content("Error"); //} [HttpGet, UserAuth] public async Task TestIndex(int id) { var userId = this.Request.GetUserInfo().UserId; var product = await m_ProductService.GetById(id); var package = await m_ProductPackageService.Query(m => m.IsTest == 1 && m.ProductId == id).FirstOrDefaultAsync(); var restTimes = await m_ProductAccountService.GetRestTestCount(userId); return View("Test", new PackageInfoResponse() { Package = package, Product = product, RestTimes = restTimes }); } [HttpGet, UserAuth] public async Task Test(int id) { var product = await m_ProductService.GetById(id); var package = await m_ProductPackageService.Query(m => m.IsTest == 1 && m.ProductId == id).FirstOrDefaultAsync(); var restTimes = 0; var userInfo = this.Request.GetUserInfo(); if (userInfo != null) { var userId = userInfo.UserId; restTimes = await m_ProductAccountService.GetRestTestCount(userId); } return View("Test", new PackageInfoResponse() { Package = package, Product = product, RestTimes = restTimes }); } [HttpGet] public async Task Soft() { var ret = await m_ProductService.Query(true).ToListAsync(); return View(ret); } [HttpGet, AllowAnonymous] public async Task IsPay(string orderNo) { var orderInfo=await m_ProductOrderService.GetOrderByNo(orderNo); if (orderInfo.OrderState == OrderStatus.PayOk || orderInfo.OrderState == OrderStatus.Complete) return new ApiResult(1); else return new ApiResult(0); } [HttpGet,UserAuth] public async Task Buy(int id) { var userId = this.Request.GetUserInfo().UserId; var package = await m_ProductPackageService.GetById(id); var product = await m_ProductService.GetById(package.ProductId); var userPrice = await m_ProductUserPriceService.GetPackageUserPrice(package.Id, userId); if (userPrice != null && userPrice.UserPrice > 0) { package.Price = userPrice.UserPrice; } return View("buy", new PackageInfoResponse() { Package = package, Product = product }); } [HttpGet] public async Task ReBuyIndex(string accounts,int productId=0) { ViewBag.accounts = ""; ViewBag.errorTip = ""; var model = new ProductWithPackageResponse(); if (accounts.NotHas()) { ViewBag.errorTip = "请选择账号"; return View(model); } var accountList = await m_ProductAccountService.GetAccounts(accounts); if (productId > 0) accountList = accountList.Where(m => m.ProductId == productId).ToList(); var productIds = accountList.Select(m => m.ProductId); var connectCountList = accountList.Select(m => m.ConnectCount); if (productIds.Distinct().Count() != 1 || connectCountList.Distinct().Count() != 1) { ViewBag.errorTip = "续费账号必须为同一种产品且相同的连接数"; return View(model); } ViewBag.accounts = accounts; var id = productIds.First().Value; var respList = await m_ProductService.GetOneProductWithPackage(id); var userInfo = this.Request.GetUserInfo(); if (userInfo != null) { var userPrices = await m_ProductUserPriceService.GetProductUserPrice(id, userInfo.UserId); respList.Packages.ForEach(m => { var userPrice = userPrices.FirstOrDefault(p => p.PackageId == m.Id); if (userPrice != null && userPrice.UserPrice > 0) { m.Price = userPrice.UserPrice; } }); } return View(respList); } [HttpGet,UserAuth] public async Task ReBuy(int packageId, string accounts) { var package = await m_ProductPackageService.GetById(packageId); var product = await m_ProductService.GetById(package.ProductId); var account = ""; if (accounts.IndexOf(",") == -1) { account = accounts; } else { account = accounts.Split(',')[0]; } var accountEntity = await m_ProductAccountService.GetProductAccountInfo(package.ProductId, account); var userId = this.Request.GetUserInfo().UserId; var userPrice = await m_ProductUserPriceService.GetPackageUserPrice(packageId, userId); if (userPrice != null && userPrice.UserPrice > 0) { package.Price = userPrice.UserPrice; } var model = new PackageInfoResponse() { Package = package, Product = product }; ViewBag.accounts = accounts; ViewBag.orderType = accounts.Split(",").Count() > 1 ? 4 : 3; ViewBag.ConnectCount = accountEntity == null ? 1 : accountEntity.ConnectCount; return View(model); } } }