using Fuel.Core.Transactions.Dto; using Microsoft.AspNetCore.Http; using Newtonsoft.Json; using FuelServer.Core.Entity; using System.Linq.Expressions; using Fuel.Core.Models; using System.Net; using Fuel.Payment.Service.Pay; using DFS.Core.Abstractions.View; using Fuel.Core; using System; using System.Transactions; using Fuel.Core.WechatServer; using Fuel.Core.Nozzle.Dto; using Fuel.Application.MqttService; using Org.BouncyCastle.Asn1.X509; using Jayrock.Json; using Fuel.Core.Transactions; using Microsoft.Extensions.DependencyInjection; using static Fuel.Core.WechatServer.WeChatService; using System.Linq.Dynamic.Core; using System.Text.Json; using Org.BouncyCastle.Asn1.Ocsp; namespace Fuel.Application.Service { public class TransactionsService : ITransactionsService { private readonly EntityHelper _entityHelper; private readonly IHttpContextAccessor _httpContextAccessor; private readonly IPayService _payService; public readonly IFreeSql _fsql; private readonly IMqttClientService _mqttService; private readonly IServiceScopeFactory _serviceScopeFactory; static NLog.Logger logger = NLog.LogManager.LoadConfiguration("nlog.xml").GetLogger("Main"); public TransactionsService(EntityHelper entityHelper, IHttpContextAccessor httpContextAccessor, IPayService payService, IFreeSql fsql, IMqttClientService mqttService, IServiceScopeFactory serviceScopeFactory) { _entityHelper = entityHelper; _httpContextAccessor = httpContextAccessor; _payService = payService; _fsql = fsql; _mqttService = mqttService; _serviceScopeFactory = serviceScopeFactory; } /// /// 创建订单 /// /// /// public async Task CreateTransactions(UploadTransactions uploadTransactions) { Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id var site = _fsql.Select().Where(_ => _.Buid == Buid).First(); if (site == null) { return ServiceResponse.Error("站点信息查询为空 buid: " + Buid); } string key = string.Empty; var _product = await _entityHelper.GetEntitiesAsync(_ => _.Buid == Buid && _.ProductName == uploadTransactions.Product); if (_product.Count() <= 0) { return ServiceResponse.Error("油品查询失败,油品名称:" + uploadTransactions.Product); } var _nozzle = await _entityHelper.GetEntitiesAsync(_ => _.Buid == Buid && _.ExternalGunNumber == uploadTransactions.ExternalGunNumber); if (_nozzle.Count() <= 0) { return ServiceResponse.Error("油枪查询失败,油枪名称:" + uploadTransactions.ExternalGunNumber); } if (site.PaymentMode == 1)//预支付 { key = uploadTransactions.ExternalGunNumber + ":" + uploadTransactions.OriginalAmount + ":" + uploadTransactions.Qty + ":" + uploadTransactions.MiniProgramID + ":" + Buid.ToString(); string WachatID = HttpRequestReader.GetWachatID(); //用户 var userSession = WechatUserSessionRepo.GetUserSession(WachatID.ToString()); if (userSession == null) { return ServiceResponse.Error(HttpStatusCode.NonAuthoritativeInformation, "未找到用户!"); } var user = _fsql.Select().Where(_ => _.OpenId == userSession.openid).First(); if (uploadTransactions.OriginalAmount != null) { decimal decimalValue = uploadTransactions.OriginalAmount.HasValue ? uploadTransactions.OriginalAmount.Value : 0m; decimal ProductPrice = _product.First().ProductPrice.HasValue ? _product.First().ProductPrice.Value : 0m; decimal qty = decimalValue / ProductPrice; uploadTransactions.Qty = qty; //订单金额不能小于2元、订单金额不能大于9900元 if (uploadTransactions.OriginalAmount < 2 || uploadTransactions.OriginalAmount > 9900) { return ServiceResponse.Error(HttpStatusCode.NonAuthoritativeInformation, "订单金额不能小于2元、订单金额不能大于9900元"); } } else if (uploadTransactions.Qty != null) { decimal decimalValue = uploadTransactions.Qty.HasValue ? uploadTransactions.Qty.Value : 0m; decimal ProductPrice = _product.First().ProductPrice.HasValue ? _product.First().ProductPrice.Value : 0m; decimal OriginalAmount = decimalValue * ProductPrice; uploadTransactions.OriginalAmount = OriginalAmount; if (uploadTransactions.Qty < 1 || OriginalAmount > 9900) { return ServiceResponse.Error(HttpStatusCode.NonAuthoritativeInformation, "升数不能小于1升,订单升数乘单价不能大于9900元"); } } else if (uploadTransactions.OriginalAmount == null && uploadTransactions.Qty == null) { return ServiceResponse.Error("金额与升数为空"); } uploadTransactions.MiniProgramID = user.Id; } else//后支付 { key = uploadTransactions.ExternalGunNumber + ":" + uploadTransactions.OriginalAmount + ":" + uploadTransactions.Qty + ":" + uploadTransactions.MiniProgramID + ":" + uploadTransactions.FuelItemTransactionEndTime + ":" + uploadTransactions.TransactionNumber + ":" + Buid.ToString(); } transactions output = await GetRedisTransactions(uploadTransactions, key); if (output != null) { return ServiceResponse.Ok(output); } var trx = uploadTransactions.ToTransactions(uploadTransactions, Buid, _product.FirstOrDefault(), _nozzle.FirstOrDefault(), site.PaymentMode); //int affectedRows = _fsql.Insert().AppendData(trx).ExecuteAffrows(); // var affectedRows = _fsql.Insert().AppendData(trx).ExecuteInserted(); var id = _fsql.Insert(trx).ExecuteIdentity(); if (id > 0) { var insertedTransaction = _fsql.Select() .Where(t => t.Id == id) .First(); string jsonString = JsonConvert.SerializeObject(insertedTransaction); RedisHelper.SetAsync(key, jsonString, 600); return ServiceResponse.Ok(insertedTransaction); } else { return ServiceResponse.Error("订单信息插入失败"); } } /// /// 后支付查询 /// /// /// public async Task GetTransactionsAsync(RequestModel input) { Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id var site = _fsql.Select().Where(_ => _.Buid == Buid).First(); var _nozzle = _fsql.Select().Where(_ => _.Buid == Buid).ToList();//根据油枪id查询外部枪号 var user = _fsql.Select().Where(_ => _.Buid == Buid).ToList(); var paytype = _fsql.Select().ToList(); Expression> where = p => p.Buid == Buid; //查油枪 if (input.filter.NozzleID != "") { long.TryParse(input.filter.NozzleID, out long NozzleID); var nozzle = _nozzle.Where(_ => _.ExternalGunNumber == NozzleID).First();//根据油枪id查询外部枪号 where = CombineExpressions(where, p => p.NozzleId == nozzle.Id); } //查油品 if (input.filter.ProductName != "") { where = CombineExpressions(where, p => p.ProductName == input.filter.ProductName); } //查站点 if (input.filter.siteName != "") { where = CombineExpressions(where, p => p.Buid == site.Buid); } //查用户 if (input.filter.username != "") { var userid = user.Where(_ => _.UserName == input.filter.username).First(); where = CombineExpressions(where, p => p.MiniProgramID == userid.Id); } //查加油时间 if (input.filter.TransactionTime != null) { where = CombineExpressions(where, p => p.TransactionTime >= input.filter.TransactionTime[0] && p.TransactionTime <= input.filter.TransactionTime[1]); } //查支付模式 if (input.filter.OrderType != "") { transactionsORDERTYPE OrderType = transactionsORDERTYPE.Postpayment; if (input.filter.OrderType == "0") { OrderType = transactionsORDERTYPE.Postpayment; } else if (input.filter.OrderType == "1") { OrderType = transactionsORDERTYPE.Prepayment; } where = CombineExpressions(where, p => p.OrderType == OrderType); } //查支付状态 if (input.filter.OrderStatus != "") { transactionsORDERSTATUS OrderStatus = transactionsORDERSTATUS.Paid; if (input.filter.OrderStatus == "0") { OrderStatus = transactionsORDERSTATUS.Unpaid; } else if (input.filter.OrderStatus == "1") { OrderStatus = transactionsORDERSTATUS.Paid; } else if (input.filter.OrderStatus == "2") { OrderStatus = transactionsORDERSTATUS.Paying; } else if (input.filter.OrderStatus == "3") { OrderStatus = transactionsORDERSTATUS.CardPayment; } else if (input.filter.OrderStatus == "4") { OrderStatus = transactionsORDERSTATUS.Completed; } else if (input.filter.OrderStatus == "5") { OrderStatus = transactionsORDERSTATUS.Cancelled; } where = CombineExpressions(where, p => p.OrderStatus == OrderStatus); } var result = _fsql.Select().Where(where).Count(out var total).Page(input.currentPage,input.pageSize).ToList(); result = result.OrderByDescending(_ => _.TransactionTime).ToList(); List list = new List(); foreach (var item in result) { // var nozzle = _nozzle.Where(_ => _.Id == item.NozzleId)?.First();//根据油枪id查询外部枪号 var nozzle = _nozzle.FirstOrDefault(_ => _.Id == item.NozzleId);//根据油枪id查询外部枪号 var pay = paytype.FirstOrDefault(_ => _.Id == item.PaymentMethod)?.Name; TransactionsList transactions = new TransactionsList(); transactions.TransactionNumber = item.TransactionNumber; transactions.SiteName = site.Name; transactions.NozzleProductName = item.NozzleId + " | " + item.ProductName; transactions.ActualPaymentAmount = string.IsNullOrEmpty(item.ActualPaymentAmount.ToString()) ? null : item.ActualPaymentAmount.ToString() + "元"; transactions.TransactionTime = item.TransactionTime?.ToString("yyyy-MM-dd hh:mm:ss"); transactions.OrderStatus = GetChineseStatus(item.OrderStatus); transactions.RefundAmount = string.IsNullOrEmpty(item.RefundAmount.ToString()) ? null : item.RefundAmount.ToString() + "元"; transactions.OrderType = item.OrderType == transactionsORDERTYPE.Prepayment ? "预支付":"后支付"; if (item.MiniProgramID != null) { var userid = user.Where(_ => _.Id == item.MiniProgramID).FirstOrDefault(); transactions.UserName = userid?.UserName; string UserPhoneNumber = user.Where(_ => _.Id == item.MiniProgramID).FirstOrDefault()?.UserPhoneNumber; if (!string.IsNullOrEmpty(UserPhoneNumber)) { transactions.UserPhoneNumber = HideMiddleDigits(UserPhoneNumber,3,4); } } transactions.PriceQty = item.Price + " | " + item.Qty; transactions.PaymentMethod = pay; list.Add(transactions); } return ServiceResponse.Ok(new { list, total }); } /// /// 预支付查询 /// /// /// public async Task GetPrepaymentTransactionsAsync(RequestModel input) { Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id var site = _fsql.Select().Where(_ => _.Buid == Buid).First(); var _nozzle = _fsql.Select().Where(_ => _.Buid == Buid).ToList();//根据油枪id查询外部枪号 var user = _fsql.Select().Where(_ => _.Buid == Buid).ToList(); var paytype = _fsql.Select().ToList(); Expression> where = p => p.Buid == Buid; //查油枪 if (input.filter.NozzleID != "") { long.TryParse(input.filter.NozzleID, out long NozzleID); var nozzle = _nozzle.Where(_ => _.ExternalGunNumber == NozzleID).First();//根据油枪id查询外部枪号 where = CombineExpressions(where, p => p.NozzleId == nozzle.Id); } //查油品 if (input.filter.ProductName != "") { where = CombineExpressions(where, p => p.ProductName == input.filter.ProductName); } //查站点 if (input.filter.siteName != "") { where = CombineExpressions(where, p => p.Buid == site.Buid); } //查用户 if (input.filter.username != "") { var userid = user.Where(_ => _.UserName == input.filter.username).First(); where = CombineExpressions(where, p => p.MiniProgramID == userid.Id); } //查加油时间 if (input.filter.TransactionTime != null) { where = CombineExpressions(where, p => p.TransactionTime >= input.filter.TransactionTime[0] && p.TransactionTime <= input.filter.TransactionTime[1]); } //查支付模式 if (input.filter.OrderType != "") { transactionsORDERTYPE OrderType = transactionsORDERTYPE.Postpayment; if (input.filter.OrderType == "0") { OrderType = transactionsORDERTYPE.Postpayment; } else if (input.filter.OrderType == "1") { OrderType = transactionsORDERTYPE.Prepayment; } where = CombineExpressions(where, p => p.OrderType == OrderType); } //查支付状态 if (input.filter.OrderStatus != "") { transactionsORDERSTATUS OrderStatus = transactionsORDERSTATUS.Paid; if (input.filter.OrderStatus == "0") { OrderStatus = transactionsORDERSTATUS.Unpaid; } else if (input.filter.OrderStatus == "1") { OrderStatus = transactionsORDERSTATUS.Paid; } else if (input.filter.OrderStatus == "2") { OrderStatus = transactionsORDERSTATUS.Paying; } else if (input.filter.OrderStatus == "3") { OrderStatus = transactionsORDERSTATUS.CardPayment; } else if (input.filter.OrderStatus == "4") { OrderStatus = transactionsORDERSTATUS.Completed; } else if (input.filter.OrderStatus == "5") { OrderStatus = transactionsORDERSTATUS.Cancelled; } where = CombineExpressions(where, p => p.OrderStatus == OrderStatus); } var result = _fsql.Select().Where(where).Count(out var total).Page(input.currentPage, input.pageSize).ToList(); result = result.OrderByDescending(_ => _.TransactionTime).ToList(); List list = new List(); foreach (var item in result) { // var nozzle = _nozzle.Where(_ => _.Id == item.NozzleId)?.First();//根据油枪id查询外部枪号 var nozzle = _nozzle.FirstOrDefault(_ => _.Id == item.NozzleId);//根据油枪id查询外部枪号 var pay = paytype.FirstOrDefault(_ => _.Id == item.PaymentMethod)?.Name; PrepaymentTransactionsList transactions = new PrepaymentTransactionsList(); transactions.TransactionNumber = item.TransactionNumber; transactions.SiteName = site.Name; transactions.NozzleProductName = item.NozzleId + " | " + item.ProductName; transactions.ActualPaymentAmount = string.IsNullOrEmpty(item.ActualPaymentAmount.ToString()) ? null : item.ActualPaymentAmount.ToString() + "元"; transactions.TransactionTime = item.TransactionTime?.ToString("yyyy-MM-dd hh:mm:ss"); transactions.OrderStatus = GetChineseStatus(item.OrderStatus); transactions.RefundAmount = string.IsNullOrEmpty(item.RefundAmount.ToString()) ? null : item.RefundAmount.ToString() + "元"; transactions.OrderType = item.OrderType == transactionsORDERTYPE.Prepayment ? "预支付" : "后支付"; if (item.MiniProgramID != null) { var userid = user.Where(_ => _.Id == item.MiniProgramID).FirstOrDefault(); transactions.UserName = userid?.UserName; string UserPhoneNumber = user.Where(_ => _.Id == item.MiniProgramID).FirstOrDefault()?.UserPhoneNumber; if (!string.IsNullOrEmpty(UserPhoneNumber)) { transactions.UserPhoneNumber = HideMiddleDigits(UserPhoneNumber, 3, 4); } } transactions.PriceQty = item.Price + " | " + item.Qty; transactions.PaymentMethod = pay; transactions.authorizationStatus = GetAuthorizationStatus(item.authorizationStatus); transactions.RefundStatus = GetRefundStatus(item.RefundStatus); list.Add(transactions); } return ServiceResponse.Ok(new { list, total }); } /// /// 小程序查询未支付订单 /// /// public async Task GetMiniProgramTransactionsUnpaidAsync(TransactionsInput input) { Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id Expression> where = p => p.Buid == Buid; string WachatID = HttpRequestReader.GetWachatID(); //用户 var userSession = WechatUserSessionRepo.GetUserSession(WachatID.ToString()); if (userSession == null) { return ServiceResponse.Error(HttpStatusCode.NonAuthoritativeInformation, "未找到用户!"); } DateTime dayBeforeTime = DateTime.Now.AddDays(-1); var user = _fsql.Select().Where(_ => _.OpenId == userSession.openid).First(); where = CombineExpressions(where, p => p.MiniProgramID == user.Id && p.OrderStatus == transactionsORDERSTATUS.Unpaid && p.TransactionTime >= dayBeforeTime); var result = await _entityHelper.GetEntitiesAsync(where); result = result.OrderByDescending(x => x.CreateTime).ToList(); return ServiceResponse.Ok(result); } /// /// 小程序用户根据抢号查询未支付订单 /// /// public async Task GetMiniProgramTransactionsUnpaidNozzleAsync(long NozzleId) { Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id Expression> where = p => p.Buid == Buid; string WachatID = HttpRequestReader.GetWachatID(); //用户 var userSession = WechatUserSessionRepo.GetUserSession(WachatID.ToString()); if (userSession == null) { return ServiceResponse.Error(HttpStatusCode.NonAuthoritativeInformation, "未找到用户!"); } DateTime dayBeforeTime = DateTime.Now.AddDays(-1); var _nozzle = _fsql.Select().Where(_ => _.Id == NozzleId).First();//根据油枪id查询外部枪号 where = CombineExpressions(where, p => p.NozzleId == _nozzle.ExternalGunNumber && p.OrderStatus == transactionsORDERSTATUS.Unpaid && p.TransactionTime >= dayBeforeTime); var result = await _entityHelper.GetEntitiesAsync(where); result = result.OrderByDescending(x => x.CreateTime).ToList(); return ServiceResponse.Ok(result); } /// /// 小程序查询已支付订单 /// /// public async Task GetMiniProgramTransactionsPaidAsync(TransactionsInput input) { Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id Expression> where = p => p.Buid == Buid; string WachatID = HttpRequestReader.GetWachatID(); //用户 var userSession = WechatUserSessionRepo.GetUserSession(WachatID.ToString()); if (userSession == null) { return ServiceResponse.Error(HttpStatusCode.NonAuthoritativeInformation, "未找到用户!"); } var user = _fsql.Select().Where(_ => _.OpenId == userSession.openid).First(); where = CombineExpressions(where, p => p.MiniProgramID == user.Id && p.OrderStatus == transactionsORDERSTATUS.Paid); var result = await _entityHelper.GetEntitiesAsync(where); return ServiceResponse.Ok(result); } /// /// 小程序查询已支付订单 /// /// public async Task WXFindOrders(DateTime? dateTime, int pageNum, int lineCount) { Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id Expression> where = p => p.Buid == Buid; string WachatID = HttpRequestReader.GetWachatID(); //用户 var userSession = WechatUserSessionRepo.GetUserSession(WachatID.ToString()); if (userSession == null) { return ServiceResponse.Error(HttpStatusCode.NonAuthoritativeInformation, "未找到用户!"); } var user = _fsql.Select().Where(_ => _.OpenId == userSession.openid).First(); DateTime time = dateTime != null ? (DateTime)dateTime : DateTime.Now; var select = _fsql.Select().Where(_ => _.MiniProgramID == user.Id && (_.TransactionTime >= DateTime.Now.AddDays(-30) && _.TransactionTime <= time)); var list = await select.Page(pageNum, lineCount).OrderByDescending(_ => _.TransactionTime).ToListAsync(); return ServiceResponse.Ok(list); } /// /// 提交支付 /// /// /// public async Task CommitPayment(int trxId, string AuthCode) { bool paymentOK = false; var trx = _entityHelper.GetEntitiesAsync(_ => _.Id == trxId).Result.FirstOrDefault(); if (trx == null) { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "未查询到订单!"); } var paytype = _entityHelper.GetEntitiesAsync(_ => _.Id == trx.PaymentMethod).Result.FirstOrDefault(); string billNumber = SequenceNumber.Next();//订单编号 trx.TransactionNumber = billNumber; decimal payDueAmount = (decimal)trx.OriginalAmount; string Channel = paytype.Channel; var serviceResult = await _payService.PerformElectronicProcess(AuthCode, payDueAmount, billNumber); Payment.Core.Models.ElectronicOrderProcessResultModel payResult = (Payment.Core.Models.ElectronicOrderProcessResultModel)serviceResult.Data; if (!serviceResult.IsSuccessful() || payResult.ResultCode == "PAY_ERROR") { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "支付失败"); } trx.ActualPaymentAmount = payDueAmount;//实际支付金额 trx.ResultCode = payResult?.ResultCode;//支付成功应该为0 trx.ErrorDetail = payResult?.ErrorDetail; _entityHelper.UpdateAsync(trx); return ServiceResponse.Ok(trx); } /// /// 查询redis订单缓存 /// /// public async Task GetRedisTransactions(UploadTransactions uploadTransactions, string key) { Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id var respond = RedisHelper.GetAsync(key).Result; if (respond == null) { return null; } transactions transactions = JsonConvert.DeserializeObject(respond); var trx = _entityHelper.GetEntitiesAsync(_ => _.Id == transactions.Id).Result.FirstOrDefault(); if (trx == null || trx.OrderStatus != transactionsORDERSTATUS.Unpaid) { return null; } return transactions; } // 辅助方法:组合两个表达式 private static Expression> CombineExpressions(Expression> expr1, Expression> expr2) { ParameterExpression param = expr1.Parameters[0]; Expression body = Expression.AndAlso(expr1.Body, Expression.Invoke(expr2, param)); return Expression.Lambda>(body, param); } /// /// 退款 /// /// /// public async Task RefundTrx(int trxId, decimal? OriginalQty = null) { Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id var businessunitinfo = _entityHelper.GetEntitiesAsync(_ => _.Buid == Buid).Result.FirstOrDefault(); if (businessunitinfo == null) { logger.Debug($"RefundTrx,退款失败,站点为空,Buid={Buid} ,trxId={trxId}"); return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "站点为空"); } string[] parts = businessunitinfo.GpsCoordinates.Split(','); // if (parts.Length == 2 && //double.TryParse(parts[0], out double latitude2) && //double.TryParse(parts[1], out double longitude2)) // { // } // else // { // return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "站点经纬度获取失败"); // } // //计算调用方和油站的距离,超过距离判定为恶意请求 // double distance = DistanceCalculator.CalculateDistance(longitude, latitude, longitude2, latitude2); // if (distance > 5) // { // return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "该请求大于油站地址5公里"); // } var trx = _entityHelper.GetEntitiesAsync(_ => _.Id == trxId).Result.FirstOrDefault(); if (trx == null) { logger.Debug($"退款失败,未查询到订单,Buid={Buid} ,trxId={trxId}"); return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "未查询到订单!"); } else if (trx.RefundStatus == RefundStatus.FullyRefunded) { logger.Debug($"该订单已退款,未查询到订单,Buid={Buid} ,trxId={trxId}"); return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "该订单已退款"); } else if (trx.RefundStatus == RefundStatus.PartiallyRefunded) { logger.Debug($"该订单已部分退款,Buid={Buid} ,trxId={trxId}"); return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "该订单已部分退款"); } else if (trx.OrderStatus == transactionsORDERSTATUS.Unpaid) { logger.Debug($"该订单已退款,该订单未支付,Buid={Buid} ,trxId={trxId}"); return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "该订单未支付"); } //获取单价 decimal? ProductPrice = _entityHelper.GetEntitiesAsync(_ => _.Id == trx.ProductId).Result.FirstOrDefault().ProductPrice; if (ProductPrice == null) { logger.Debug($"该订单已退款,单价获取失败,Buid={Buid} ,trxId={trxId}"); return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "单价获取失败"); } //计算退款金额 //decimal RefundAmount = (decimal)trx.ActualPaymentAmount; decimal RefundAmount = 0.0M; if (businessunitinfo.PaymentMode == 0)//后支付 { logger.Debug($"后支付模式无法退款!,Buid={Buid} ,trxId={trxId}"); return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "后支付模式无法退款!"); // RefundAmount = (decimal)((trx.Qty - trx.OriginalQty) * ProductPrice.Value); } else if (businessunitinfo.PaymentMode == 1)//预支付 { decimal volume = OriginalQty ?? 0m; RefundAmount = (decimal)((trx.Qty - volume) * trx.Price); //RefundAmount = (decimal)((trx.Qty - OriginalQty) * ProductPrice.Value); } if (RefundAmount <= 0.0M) { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "该笔单无需退款"); } //退款 var serviceResult = await _payService.ReturnProcess(RefundAmount, (decimal)trx.ActualPaymentAmount, "WX_SCAN", trx.BillNumber); Payment.Core.Models.ElectronicOrderProcessResultModel payResult = (Payment.Core.Models.ElectronicOrderProcessResultModel)serviceResult.Data; if (!serviceResult.IsSuccessful() || payResult.ResultCode == "PAY_ERROR") { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "退款失败"); } if (RefundAmount == (decimal)trx.ActualPaymentAmount) { trx.RefundStatus = RefundStatus.FullyRefunded;//全额退款 } else { trx.RefundStatus = RefundStatus.PartiallyRefunded;//部分退款 } trx.OrderStatus = transactionsORDERSTATUS.Cancelled; trx.RefundAmount = RefundAmount; int affectedRows = _fsql.Update().SetSource(trx).ExecuteAffrows(); var user = _fsql.Select().Where(_ => _.Id == trx.MiniProgramID).First(); string jsonString = JsonConvert.SerializeObject(trx); await _mqttService.SubscribeAsync("refund/" + Buid); await Task.Delay(2000); var sendjson = new { data = jsonString, UserName = user.UserName, UserPhoneNumber = user.UserPhoneNumber }; await _mqttService.PublishAsync("refund/" + Buid, JsonConvert.SerializeObject(sendjson)); return ServiceResponse.Ok(trx); } public async Task UnifiedOrder(int trxId) { Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id try { logger.Debug("UnifiedOrder start++"); string WachatID = HttpRequestReader.GetWachatID(); //用户 var userSession = WechatUserSessionRepo.GetUserSession(WachatID.ToString()); if (userSession == null) { return ServiceResponse.Error(HttpStatusCode.NonAuthoritativeInformation, "未找到用户!"); } //var userSession = new WechatUserSessionResponse() { buId = "12345678-9abc-def0-1234-56789abcdef0", openid = "o8pFb5cWH1KkBDvGls2X7yMiFkGA" }; var site = _fsql.Select().Where(_ => _.Buid == Buid).First(); var weChatService = new WeChatService(site.Appid, site.Secret); var user = _fsql.Select().Where(_ => _.OpenId == userSession.openid).First(); var trx = _entityHelper.GetEntitiesAsync(_ => _.Id == trxId).Result.FirstOrDefault(); if (trx == null) { logger.Debug($"统一下单,Buid={Buid} ,trxId={trxId},未查询到订单"); return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "未查询到订单!"); } logger.Debug($"统一下单开始,Buid={Buid} ,trxId={trxId}"); var serviceResult = await _payService.UnifiedOrder(trx.OriginalAmount.Value, "WX_SCAN", userSession.openid); var dataProperties = serviceResult.Data.GetType().GetProperty("UnifiedOrderResult"); if (!serviceResult.IsSuccessful() || dataProperties == null) { logger.Debug($"统一下单失败,Buid={Buid} ,trxId={trxId}" ); return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "统一下单失败"); } //小程序支付完后,云端需要通过订单编号去支付平台查询支付状态,以便更新订单信息 _ = Task.Delay(1500).ContinueWith(async _ => { using (var scope = _serviceScopeFactory.CreateScope()) { var scopedMqttService = scope.ServiceProvider.GetRequiredService(); var dataProperties = serviceResult.Data.GetType().GetProperty("eOrder"); var orderModel = (Fuel.Payment.Core.Models.ElectronicOrderModel)dataProperties.GetValue(serviceResult.Data); var genericResponse = await _payService.QueryOrder(orderModel); logger.Debug($"统一下单,Buid={Buid} ,trxId={trxId},genericResponse.Data={genericResponse.Data}"); if (genericResponse.IsSuccessful() && orderModel.TradeStatus == Fuel.Payment.Core.Models.TradeStatus.SUCCESS) { trx.OrderStatus = transactionsORDERSTATUS.Paid;//将订单状态更改成已支付 trx.MiniProgramID = user.Id; trx.BillNumber = orderModel.BillNumber; trx.BillNumberBase62 = NumericBase62Converter.Encode(orderModel.BillNumber); trx.ActualPaymentAmount = trx.OriginalAmount; trx.PaymentMethod = 2;//2 :微信支付 try { await scopedMqttService.SubscribeAsync("paid/" + Buid); string jsonString = JsonConvert.SerializeObject(trx); await Task.Delay(2000); var sendjson = new { data = jsonString, UserName = user.UserName, UserPhoneNumber = user.UserPhoneNumber }; logger.Debug($"统一下单,Buid={Buid} ,trxId={trxId},订单推送fcc sendjson={System.Text.Json.JsonSerializer.Serialize(sendjson)}"); //支付完成将订单信息推送到fcc scopedMqttService.PublishAsync("paid/" + Buid, JsonConvert.SerializeObject(sendjson)); } catch (Exception ex) { logger.Debug($"统一下单,Buid={Buid} ,trxId={trxId},异常:"+ ex.Message); } logger.Debug($"统一下单,Buid={Buid} ,trxId={trxId},更新订单信息"); int affectedRows = _fsql.Update().SetSource(trx).ExecuteAffrows(); logger.Debug($"统一下单,Buid={Buid} ,trxId={trxId},更新状态" + affectedRows); //SendMessage(trx,Buid); } } }); var unifiedOrderResult = dataProperties.GetValue(serviceResult.Data); var options = new JsonSerializerOptions { IgnoreReadOnlyProperties = true // 忽略只读属性 }; string serializedUnifiedOrderResult = System.Text.Json.JsonSerializer.Serialize(unifiedOrderResult, options); logger.Debug($"统一下单,Buid={Buid} ,trxId={trxId}, 支付信息 " + serializedUnifiedOrderResult); return ServiceResponse.Ok(unifiedOrderResult); } catch (Exception ex) { logger.Debug($"统一下单,Buid={Buid} ,trxId={trxId},Exception:" +ex.Message); return ServiceResponse.Error(ex.Message); } } public async Task Redeem(int trxId, decimal OriginalQty, decimal FuelItemPumpTotalizerVolume) { var trx = _entityHelper.GetEntitiesAsync(_ => _.Id == trxId).Result.FirstOrDefault(); if (trx == null) { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "未查询到订单!"); } var refund = await RefundTrx(trxId, OriginalQty); trx = _entityHelper.GetEntitiesAsync(_ => _.Id == trxId).Result.FirstOrDefault(); trx.OriginalQty = OriginalQty; trx.FuelItemPumpTotalizerVolume = FuelItemPumpTotalizerVolume; if (refund.IsSuccessful() || refund.StatusCode == HttpStatusCode.NotAcceptable) { trx.OrderStatus = transactionsORDERSTATUS.Completed; } int affectedRows = _fsql.Update().SetSource(trx).ExecuteAffrows(); return ServiceResponse.Ok(trx); } /// /// 微信发送模板消息 /// /// public async Task SendMessage(int trxId, string orderType) { var data = new Dictionary();//动态字段 Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id var trx = _entityHelper.GetEntitiesAsync(_ => _.Id == trxId).Result.FirstOrDefault(); var site = _fsql.Select().Where(_ => _.Buid == Buid).First(); var weChatService = new WeChatService(site.Appid, site.Secret); string WachatID = HttpRequestReader.GetWachatID(); //用户 //var userSession = WechatUserSessionRepo.GetUserSession(WachatID.ToString()); //if (userSession == null) //{ //} //var user = _fsql.Select().Where(_ => _.OpenId == userSession.openid).First(); var user = _fsql.Select().Where(_ => _.OpenId == WachatID).First(); var template = _fsql.Select().Where(_ => _.Buid == Buid && _.Type == 2 && _.Name == "小程序通知模板").First(); if (template == null) { //模板获取失败 return; } //将金额小数改成俩位 if (trx.ActualPaymentAmount.HasValue) { decimal roundedValue = Math.Round(trx.ActualPaymentAmount.Value, 2, MidpointRounding.AwayFromZero); trx.ActualPaymentAmount = roundedValue; } // var BillNumber = EncodeBillNumber(trx.BillNumber); var config = JsonConvert.DeserializeObject(template.Value); var dataDict = new Dictionary(); var dynamicData = new Dictionary { { "orderType", orderType}, { "BillNumber", trx.BillNumberBase62 },//trx.BillNumber { "ProductName_Qty", trx.ProductName + " & " + trx.Qty + "L"}, { "ActualPaymentAmount",trx.ActualPaymentAmount.ToString() + "元" }, { "TransactionTime", ToFormattedString(trx.TransactionTime) } }; foreach (var mapping in config.DataMappings) { string dataFieldName = mapping.Key; string targetFieldName = mapping.Value; if (dynamicData.TryGetValue(dataFieldName, out object value)) { dataDict.Add(targetFieldName, new { value = value }); } } // 准备要发送的模板消息内容 var templateMessage = new WeChatService.TemplateMessage { ToUser = user.OpenId, TemplateId = config.TemplateId, Page = "pages/historyOrder/historyOrder", Data = dataDict }; //var templateMessage = new WeChatService.TemplateMessage //{ // ToUser = user.OpenId, // TemplateId = "V0tl-4n-5hwNZc4SrEttvrmawAyM-SB0pQWZNwp54Ks", // Page = "pages/historyOrder/historyOrder", // Data = new // { // short_thing10 = new { value = orderType }, // character_string11 = new { value = trx.BillNumber }, // thing12 = new { value = trx.ProductName + " | " + trx.Qty + "L"}, // amount13 = new { value = trx.ActualPaymentAmount }, // time14 = new { value = ToFormattedString(trx.TransactionTime) }, // } //}; weChatService.SendTemplateMessage(templateMessage); } public string ToFormattedString(DateTime? dateTime) { if (dateTime.HasValue) { return dateTime.Value.ToString("yyyy-MM-dd HH:mm:ss"); } else { return null; } } public static string GetAuthorizationStatus(AuthorizationStatus status) { switch (status) { case AuthorizationStatus.Unauthorized: return "未授权"; case AuthorizationStatus.Authorized: return "已授权"; case AuthorizationStatus.WaitAuthorization: return "等待授权"; case AuthorizationStatus.FillingUp: return "加油中"; default: throw new ArgumentOutOfRangeException(nameof(status), status, null); } } public static string GetRefundStatus(RefundStatus status) { switch (status) { case RefundStatus.NotRefunded: return "无退款"; case RefundStatus.FullyRefunded: return "订单全额退款"; case RefundStatus.PartiallyRefunded: return "订单部分退款"; default: throw new ArgumentOutOfRangeException(nameof(status), status, null); } } public static string GetChineseStatus(transactionsORDERSTATUS status) { switch (status) { case transactionsORDERSTATUS.Unpaid: return "订单未支付"; case transactionsORDERSTATUS.Paid: return "订单已支付"; case transactionsORDERSTATUS.Paying: return "订单正在支付中"; case transactionsORDERSTATUS.CardPayment: return "订单通过卡支付"; case transactionsORDERSTATUS.Completed: return "订单已完成"; case transactionsORDERSTATUS.Cancelled: return "已退款"; default: throw new ArgumentOutOfRangeException(nameof(status), status, null); } } /// /// 隐藏手机号中间的几位数字 /// /// 原始手机号 /// 开始隐藏的位置 /// 需要隐藏的字符长度 /// 处理后的手机号 public static string HideMiddleDigits(string phoneNumber, int startIndex, int length) { if (string.IsNullOrEmpty(phoneNumber) || startIndex + length > phoneNumber.Length) { return phoneNumber; // 如果输入无效,则返回原始手机号 } string visiblePartStart = phoneNumber.Substring(0, startIndex); // 手机号前部分 string hiddenPart = new string('*', length); // 中间隐藏部分 string visiblePartEnd = phoneNumber.Substring(startIndex + length); // 手机号后部分 return visiblePartStart + hiddenPart + visiblePartEnd; } } }