using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; using SKIT.FlurlHttpClient.Wechat.TenpayV3; using SKIT.FlurlHttpClient.Wechat.TenpayV3.Events; using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models; using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings; using System.Text; using Zncy.CloudCar.WeChat.Service.Options; using Zncy.CloudCar.WeChat.Service.Services.HttpClients; using Znyc.CloudCar.Auth.HttpContextUser; using Znyc.CloudCar.Caching; using Znyc.CloudCar.Configuration; using Znyc.CloudCar.IRepository.CardIntro; using Znyc.CloudCar.IRepository.Order; using Znyc.CloudCar.IRepository.PaymentRecord; using Znyc.CloudCar.IRepository.Recharge; using Znyc.CloudCar.IServices.Auth; using Znyc.CloudCar.IServices.Currency; using Znyc.CloudCar.IServices.User; using Znyc.CloudCar.Model.Dtos.Auth; using Znyc.CloudCar.Model.Entities; using Znyc.CloudCar.Model.ViewModels.ReportsCallBack; using Znyc.CloudCar.Utility.Attributes; using Znyc.CloudCar.Utility.Extensions; using Znyc.CloudCar.Utility.Helper; namespace Znyc.CloudCar.Services.Auth { public class AuthService : IAuthService { private readonly IRedisOperationRepository _redisCache; private readonly IHttpContextUser _httpContextUser; private readonly IRechargeIntroRepository _rechargeIntroRepository; private readonly IOrderRepository _orderRepository; private readonly IOrderDetailRepository _orderDetailRepository; private readonly IPaymentRecordRepository _paymentRecordRepository; private readonly ILogger _logger; private readonly IHttpContextAccessor _httpContextAccessor; private readonly ICurrencyService _currencyService; private readonly IUserCardService _userCardService; private readonly ICardIntroRepository _cardIntroRepository; //private readonly IRedisOperationRepository _redisOperationRepository; //private readonly IWeChatApiHttpClientFactory _weChatApiHttpClientFactory; private readonly WeChatOptions _weChatOptions; private readonly TenpayOptions _tenpayOptions; private readonly IWechatTenpayHttpClientFactory _tenpayHttpClientFactory; public AuthService( IRedisOperationRepository redisCache, IHttpContextUser httpContextUser, IRechargeIntroRepository rechargeIntroRepository, IOrderRepository orderRepository, IOrderDetailRepository orderDetailRepository, IPaymentRecordRepository paymentRecordRepository, ILogger logger, IHttpContextAccessor httpContextAccessor, ICurrencyService currencyService, IUserCardService userCardService, ICardIntroRepository cardIntroRepository, //IRedisOperationRepository redisOperationRepository, //IWeChatApiHttpClientFactory weChatApiHttpClientFactory, IOptions weChatOptions, IOptions tenpayOptions, IWechatTenpayHttpClientFactory tenpayHttpClientFactory ) { _redisCache = redisCache; _httpContextUser = httpContextUser; _rechargeIntroRepository = rechargeIntroRepository; _orderRepository = orderRepository; _orderDetailRepository = orderDetailRepository; _paymentRecordRepository = paymentRecordRepository; _logger = logger; _httpContextAccessor = httpContextAccessor; _currencyService = currencyService; _userCardService = userCardService; _cardIntroRepository = cardIntroRepository; // _redisOperationRepository = redisOperationRepository; //_weChatApiHttpClientFactory = weChatApiHttpClientFactory; _weChatOptions = weChatOptions.Value; _tenpayOptions = tenpayOptions.Value; _tenpayHttpClientFactory = tenpayHttpClientFactory; } /// /// 获取百度AccessToken /// /// public ResponseOutput GetAccessTokenAsync() { string key = string.Format(GlobalCacheKeyVars.BaiduAccessToken, AppSettingsConstVars.ApiKey); BaiduAccessTokenOutput baiduAccessToken = _redisCache.Get(key); if (baiduAccessToken.IsNull()) { string authHost = $"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={ AppSettingsConstVars.ApiKey }&client_secret={ AppSettingsConstVars.SecretKey }&"; HttpClient client = new HttpClient(); HttpResponseMessage response = client.GetAsync(authHost).Result; baiduAccessToken = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result); _redisCache.SetAsync(key, baiduAccessToken, TimeSpan.FromDays(30)); } ResponseOutput output = new ResponseOutput() { Data = baiduAccessToken, Successed = true, Code = 1 }; return output; } /// /// 微信支付 /// /// /// /// [Transaction] public async Task WxPay(long productId, int type) { if (type == (int)GlobalEnumVars.OrderType.BuyCurrency) { RechargeIntroEntity entity = await _rechargeIntroRepository.GetAsync(productId); if (entity.IsNotNull()) { //订单信息 OrderEntity order = await _orderRepository.InsertAsync(new OrderEntity { OrderSn = CommonHelper.GetOrderSn(productId), UserId = _httpContextUser.Id, PaymentMethod = (int)GlobalEnumVars.PaymentMethod.WX, OrderMoney = entity.Price, DistrictMoney = 0, PaymentMoney = entity.Price, ShippingCompName = "", ShippingSn = "", PayTime = DateTime.Now, OrderStatus = (int)GlobalEnumVars.OrderStatus.NotPaying, OrderCurrency = entity.ProductValue, OrderType = type }); //明细 await _orderDetailRepository.InsertAsync(new OrderDetailEntity { OrderId = order.Id, ProductId = productId, ProductName = entity.ProductName, ProductPrice = entity.Price }); //付款记录 PaymentRecordEntity paymentRecord = await _paymentRecordRepository.InsertAsync(new PaymentRecordEntity { UserId = _httpContextUser.Id, OrderId = order.Id, PaySn = "", PayStatus = (int)GlobalEnumVars.OrderStatus.NotPaying, PayPlatform = (int)GlobalEnumVars.PaymentMethod.WX, PaymentMoney = order.PaymentMoney }); return await CreateOrderByJsapi(_httpContextUser.OpenId, entity.ProductName, order.PaymentMoney.ObjectToInt(), paymentRecord.Id); } return new ResponseOutput() { Successed = false, Msg = "商品信息不存在", Code = 0 }; } else { CardIntroEntity entity = await _cardIntroRepository.GetAsync(x => x.Id == productId); if (entity.IsNotNull()) { //订单信息 OrderEntity order = await _orderRepository.InsertAsync(new OrderEntity { OrderSn = CommonHelper.GetOrderSn(productId), UserId = _httpContextUser.Id, PaymentMethod = (int)GlobalEnumVars.PaymentMethod.WX, OrderMoney = entity.CardValue, DistrictMoney = 0, PaymentMoney = entity.CardValue, ShippingCompName = "", ShippingSn = "", PayTime = DateTime.Now, OrderStatus = (int)GlobalEnumVars.OrderStatus.NotPaying, OrderCurrency = entity.SendValue, OrderType = type }); //明细 await _orderDetailRepository.InsertAsync(new OrderDetailEntity { OrderId = order.Id, ProductId = productId, ProductName = entity.CardName, ProductPrice = entity.CardValue }); //付款记录 PaymentRecordEntity paymentRecord = await _paymentRecordRepository.InsertAsync(new PaymentRecordEntity { UserId = _httpContextUser.Id, OrderId = order.Id, PaySn = "", PayStatus = (int)GlobalEnumVars.OrderStatus.NotPaying, PayPlatform = (int)GlobalEnumVars.PaymentMethod.WX, PaymentMoney = order.PaymentMoney }); return await CreateOrderByJsapi(_httpContextUser.OpenId, entity.CardName, order.PaymentMoney.ObjectToInt(), paymentRecord.Id); } return new ResponseOutput() { Successed = false, Msg = "商品信息不存在", Code = 0 }; } } /// /// 微信小程序支付回调 /// /// [Transaction] public async Task NotifyUrl(string content) { try { _logger.LogError("NotifyUrl"); var client = _tenpayHttpClientFactory.Create(_tenpayOptions.Merchants[0].MerchantId); var callbackModel = client.DeserializeEvent(content); if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType)) { var callbackResource = client.DecryptEventResource(callbackModel); //attach string paymentId = callbackResource.Attachment; //业务处理 PaymentRecordEntity paymentRecord = await _paymentRecordRepository.GetAsync(Convert.ToInt64(paymentId)); if (paymentRecord.IsNotNull()) { paymentRecord.PayStatus = (int)GlobalEnumVars.PayStatus.Paying; await _paymentRecordRepository.UpdateAsync(paymentRecord); //order OrderEntity order = await _orderRepository.GetAsync(paymentRecord.OrderId); if (order.IsNotNull()) { //积分操作 var orderDetail = await _orderDetailRepository.Select.Where(x => x.OrderId == order.Id) .ToOneAsync(); if (order.OrderStatus != (int)GlobalEnumVars.OrderStatus.Paying) { if (order.OrderType == (int)GlobalEnumVars.OrderType.BuyCurrency) { RechargeIntroEntity entity = await _rechargeIntroRepository.GetAsync(orderDetail.ProductId); await _currencyService.AddCurrencyByCharge(order.UserId, order.Id, entity.AllValue); } if (order.OrderType == (int)GlobalEnumVars.OrderType.PreferentialCard) { CardIntroEntity entity = await _cardIntroRepository.GetAsync(x => x.Id == orderDetail.ProductId); await _currencyService.AddCurrencyByBuyCard(order.UserId, order.Id, entity.SendValue); await _userCardService.AddUserCardAsync(order.UserId, entity.Id, entity.Aging); } } order.OrderStatus = (int)GlobalEnumVars.OrderStatus.Paying; await _orderRepository.UpdateAsync(order); } } } string xml = "" + "SUCCESS" + "OK" + ""; return xml; } catch (Exception ex) { _logger.LogError(ex, ex.Message); string xml = "" + "FAIL" + "支付通知失败" + ""; return xml; } } /// /// 获取微信access_token /// /// public WxAccessTokenOutput GetWxAccessTokenAsync() { //var client = _weChatApiHttpClientFactory.CreateWxOpenClient(); //var request = new CgibinTokenRequest(); //var response = await client.ExecuteCgibinTokenAsync(request); //await _redisOperationRepository.SetAsync( // GlobalEnumVars.AccessTokenEnum.WxOpenAccessToken.ToString(), response.AccessToken, TimeSpan.FromDays(30)); //var accessToken = await _redisOperationRepository.GetAsync(GlobalEnumVars.AccessTokenEnum.WxOpenAccessToken.ToString()); //return accessToken; string key = string.Format(GlobalCacheKeyVars.WxAccessToken, _weChatOptions.WxOpenAppId); WxAccessTokenOutput wxAccessToken = _redisCache.Get(key); if (wxAccessToken.IsNull()) { string authHost = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={_weChatOptions.WxOpenAppId}&secret={_weChatOptions.WxOpenAppSecret}"; HttpClient client = new HttpClient(); HttpResponseMessage response = client.GetAsync(authHost).Result; wxAccessToken = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result); _redisCache.SetAsync(key, wxAccessToken, TimeSpan.FromHours(1.5)); } return wxAccessToken; } /// /// 获取小程序 /// /// public ResponseOutput GetUnlimitedAsync() { //var accessToken = WeChatCacheAccessTokenHelper.GetWxOpenAccessToken(); string key = string.Format(GlobalCacheKeyVars.WxAccessToken, _weChatOptions.WxOpenAppId); WxAccessTokenOutput wxAccessToken = _redisCache.Get(key); if (wxAccessToken.IsNull()) { wxAccessToken = GetWxAccessTokenAsync(); } string authHost = $"https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={wxAccessToken.access_token}"; System.Net.HttpWebRequest request; request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(authHost); request.Method = "POST"; request.ContentType = "application/json;charset=UTF-8"; string scene = $"Id={_httpContextUser.Id}"; string options = "{\"scene\":\"" + scene + "\",\"page\":\"pages/index/index\"}"; byte[] payload = Encoding.UTF8.GetBytes(options); request.ContentLength = payload.Length; Stream writer = request.GetRequestStream(); writer.Write(payload, 0, payload.Length); writer.Close(); System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse(); Stream s = response.GetResponseStream(); List bytes = new List(); int temp = s.ReadByte(); while (temp != -1) { bytes.Add((byte)temp); temp = s.ReadByte(); } byte[] result = bytes.ToArray(); string base64 = Convert.ToBase64String(result);//将byte[]转为base64 return new ResponseOutput() { Data = "{\"errcode\":0,\"errmsg\":\"获取成功\",\"buffer\":\"" + base64 + "\"}", Successed = true, Code = 1 }; } /// /// 获取小程序 /// /// public ResponseOutput GetQrCodeAsync(long id) { //var accessToken = WeChatCacheAccessTokenHelper.GetWxOpenAccessToken(); string key = string.Format(GlobalCacheKeyVars.WxAccessToken, _weChatOptions.WxOpenAppId); WxAccessTokenOutput wxAccessToken = _redisCache.Get(key); if (wxAccessToken.IsNull()) { wxAccessToken = GetWxAccessTokenAsync(); } string authHost = $"https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={wxAccessToken.access_token}"; System.Net.HttpWebRequest request; request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(authHost); request.Method = "POST"; request.ContentType = "application/json;charset=UTF-8"; string scene = $"{id},{_httpContextUser.Id}"; string options = "{\"scene\":\"" + scene + "\",\"page\":\"pages/detail/detail\"}"; byte[] payload = Encoding.UTF8.GetBytes(options); request.ContentLength = payload.Length; Stream writer = request.GetRequestStream(); writer.Write(payload, 0, payload.Length); writer.Close(); System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse(); Stream s = response.GetResponseStream(); List bytes = new List(); int temp = s.ReadByte(); while (temp != -1) { bytes.Add((byte)temp); temp = s.ReadByte(); } byte[] result = bytes.ToArray(); string base64 = Convert.ToBase64String(result);//将byte[]转为base64 return new ResponseOutput() { Data = "{\"errcode\":0,\"errmsg\":\"获取成功\",\"buffer\":\"" + base64 + "\"}", Successed = true, Code = 1 }; } /// /// JSAPI下单支付 /// /// /// /// /// /// public async Task CreateOrderByJsapi(string openId, string body, int price, long paymentId) { var manager = new InMemoryCertificateManager(); var options = new WechatTenpayClientOptions() { MerchantId = _tenpayOptions.Merchants[0].MerchantId, MerchantV3Secret = _tenpayOptions.Merchants[0].SecretV3, MerchantCertificateSerialNumber = _tenpayOptions.Merchants[0].CertSerialNumber, MerchantCertificatePrivateKey = @"-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDF+wWe6XTe/o1K 8Ri2lXMRJFgtjZYjxX9E8GZt7rirZRMlsgpqBjymJt/7P2LAxqafUbM9bMOlo6Ec ppjyw8yrSGTaHqSzWhoP7NuxpCw9Y4x8QOCIjsp0+UV6aE/AVw/+jfhkn7dBfAqP kIrpRlLjTYti0GSLwPVYCHDHKyYKo2pXbAlCpLjZY0c5Q4cAajPYLUrtAd9Jwzo1 vt8aTcIsgPVK8nXJM00BYsvT9NVlV15eWgU/cXg1tzJN6ZT6t75c4iTu9aoGTp2b x0Zd6OsK0FZ4NwfvcQIKHxzShbjeTuK3SMkNd3asvUXsUpus6dJbryEg2d3Emura SaVcg5tLAgMBAAECggEASOTt4t7OOzS6TTeMA93u6gbZuJwDBdS30Wg6LovQzrp+ XEi7cOIu/nYdzeI+t//sZYitWBZtytT+gxAMDIZvGzmieHUD601nfymUkkmCSHAY z78LbPw2Ku+E11cE1iq4Jt+a72GnFaNYOBfeLZnI9wwcIBveiV5YdztUWuDWNt/i JO8+cQol/y9gZqZeZSkE+ksM6SvQzhfEuGzQDXjYyOiIgja+M2mMLw2GQnqryDky giBmJkqpCFXMw9GQa8lnM5Tw7WRsGoJm/NzMsUuyIT3kwSeUOPlkLd0mzJTcDmmR HRKV6D5lQEH+sxYrCdJ+AgBLOKdg9GALfjdSK/c8IQKBgQDw0kBMDdUwgvJ6JOT1 uxlnsXz1BLh1NcS9LzM04h+Bt80omAzwt8jeXW9OgqwvOenWoi58Du4I8RsxnoFC tktqaBqW3a8e47b4UJ1LHr15OukxM24Kkulg7+2/MexMTmN2AYVskqI5Y8ebcQnt WrYkar2VeedEANFZx5GF4NlMSQKBgQDSdYSmmw5Oi7oHuhkhOKz3/uH+vWWM2yTX tgFml+iWy8+k8uYxw1BAwoeqNzJNqH/7goKSIudhZt5G/Fz3i1ZAFdYVix5XCLjF 3ySz6NPyLGo2MJpWSCoLPqHGFp6jFHmXzDySUsT4YcWeCT88yBM3lGgqJL7Eq8dc gysJqCqi8wKBgQDhL5lUBLNPM4NNV+aJKTUuUzdHXeymHWskhFhboP5ZK+e5h8TB 6vj3hWMphONBHeRdATZ6ZvOKhPoqwc6Y9SE8FLCYVh8EwWY8eBU9QzdlfwLDMRY6 6Pk13eTwndwZ1ksG85Ex30O2amkiHudrfSFImE9C0MTCQAmC7CxVhdVrkQKBgAbx XYjpgJVSwrZSi1WvOvWLcQUoVltJN3PuSymJRWEEJDt6z+FAYjtgr30MCRrKvj4b 1hbgE+YAsMCCvsZj0FqY3dEkH8IbRY0xiVJuEd/hWzeibtT92HU6gbe5M06J9GDv mefx1xGimBRYlb95kji5Kp6JS8nNKOyCXz8YTx/FAoGBAKKMZgPpN+4Qd1ZuvALm couRMQf6EWuCB7u9VuzJW/aaAIEGEXCC4HLEIYpROBwNrG313yseGVzPT2txoxw6 u2XjfkdEkhLU3W54TSw4EJedWE5d+TGGqf9eMRdUbhCXylPzTlxmnFwGb0Z31eh7 MndPWjaUAjvKQ5xFYg4gUezL -----END PRIVATE KEY-----", PlatformCertificateManager = manager // 证书管理器的具体用法请参阅下文的高级技巧与加密、验签有关的章节 }; var client = new WechatTenpayClient(options); //var client = _tenpayHttpClientFactory.Create(_tenpayOptions.Merchants[0].MerchantId); var request = new CreatePayTransactionJsapiRequest() { OutTradeNumber = $"{_tenpayOptions.Merchants[0].MerchantId}" + DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff"), AppId = _weChatOptions.WxOpenAppId, Description = body, ExpireTime = DateTimeOffset.Now.AddMinutes(15), NotifyUrl = _tenpayOptions.NotifyUrl, Amount = new CreatePayTransactionJsapiRequest.Types.Amount() { Total = price * 100 }, Payer = new CreatePayTransactionJsapiRequest.Types.Payer() { OpenId = openId }, Attachment = paymentId.ToString() }; var response = await client.ExecuteCreatePayTransactionJsapiAsync(request); if (!response.IsSuccessful()) { _logger.LogWarning( "JSAPI 下单失败(状态码:{0},错误代码:{1},错误描述:{2})。", response.RawStatus, response.ErrorCode, response.ErrorMessage ); } var paramMap = client.GenerateParametersForJsapiPayRequest(request.AppId, response.PrepayId); return new ResponseOutput() { Data = paramMap, Successed = true, Code = 1 }; } } }