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; namespace Fuel.Application.Service { public class TransactionsService : ITransactionsService { private readonly EntityHelper _entityHelper; private readonly IHttpContextAccessor _httpContextAccessor; private readonly IPayService _payService; public TransactionsService(EntityHelper entityHelper, IHttpContextAccessor httpContextAccessor, IPayService payService) { _entityHelper = entityHelper; _httpContextAccessor = httpContextAccessor; _payService = payService; } /// /// 创建订单 /// /// /// public async Task CreateTransactions(UploadTransactions uploadTransactions) { string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault(); Guid guid = Guid.Parse(Buid); string key = string.Empty; if (uploadTransactions.Type == 1)//预支付 { key = uploadTransactions.NozzleId + ":" + uploadTransactions.OriginalAmount + ":" + uploadTransactions.Qty + ":" + uploadTransactions.MiniProgramID + ":" + Buid; } else//后支付 { key = uploadTransactions.NozzleId + ":" + uploadTransactions.OriginalAmount + ":" + uploadTransactions.Qty + ":" + uploadTransactions.MiniProgramID + ":" + uploadTransactions.FuelItemTransactionEndTime + ":" + uploadTransactions.TransactionNumber + ":" + Buid; } transactions output = await GetRedisTransactions(uploadTransactions, key); if (output != null) { return ServiceResponse.Ok(output); } var _product = await _entityHelper.GetEntitiesAsync(_ => _.Buid == guid && _.ProductName == uploadTransactions.Product); var _nozzle = await _entityHelper.GetEntitiesAsync(_ => _.Buid == guid && _.ExternalGunNumber == uploadTransactions.NozzleId); var transactions = uploadTransactions.ToTransactions(uploadTransactions, guid, _product.FirstOrDefault(), _nozzle.FirstOrDefault()); var respond = await _entityHelper.InsertEntityAsync(transactions); string jsonString = JsonConvert.SerializeObject(respond); RedisHelper.SetAsync(key, jsonString, 3600); return ServiceResponse.Ok(respond); } public async Task GetTransactionsAsync(TransactionsInput input) { string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault(); Guid guid = Guid.Parse(Buid); Expression> where = p => p.Buid == guid; if (input.TransactionID != null) { where = CombineExpressions(where, p => p.Id == input.TransactionID); } if (input.type != null) { var status = (transactionsORDERSTATUS)input.type.Value; where = CombineExpressions(where, p => p.OrderStatus == status); } if (input.MiniProgramID != null) { where = CombineExpressions(where, p => p.MiniProgramID == input.MiniProgramID); } if (input.TransactionSTime != null) { where = CombineExpressions(where, p => p.TransactionTime >= input.TransactionSTime); } if (input.TransactionETime != null) { where = CombineExpressions(where, p => p.TransactionTime == input.TransactionETime); } if (!string.IsNullOrEmpty(input.Product)) { where = CombineExpressions(where, p => p.ProductName == input.Product); } var result = await _entityHelper.GetEntitiesAsync(where); return ServiceResponse.Ok(result); } /// /// 小程序查询未支付订单 /// /// public async Task GetMiniProgramTransactionsUnpaidAsync(TransactionsInput input) { string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault(); Guid guid = Guid.Parse(Buid); Expression> where = p => p.Buid == guid; if (input.MiniProgramID == null) { return ServiceResponse.Error("用户id为空"); } where = CombineExpressions(where, p => p.MiniProgramID == input.MiniProgramID && p.OrderStatus == transactionsORDERSTATUS.Unpaid); var result = await _entityHelper.GetEntitiesAsync(where); return ServiceResponse.Ok(result); } /// /// 小程序查询已支付订单 /// /// public async Task GetMiniProgramTransactionsPaidAsync(TransactionsInput input) { string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault(); Guid guid = Guid.Parse(Buid); Expression> where = p => p.Buid == guid; if (input.MiniProgramID == null) { return ServiceResponse.Error("用户id为空"); } where = CombineExpressions(where, p => p.MiniProgramID == input.MiniProgramID && p.OrderStatus == transactionsORDERSTATUS.Paid); var result = await _entityHelper.GetEntitiesAsync(where); return ServiceResponse.Ok(result); } /// /// 提交支付 /// /// /// 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) { string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault(); var respond = RedisHelper.GetAsync(key).Result; if (respond == null) { return null; } transactions transactions = JsonConvert.DeserializeObject(respond); 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, double longitude, double latitude) { string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault(); Guid guid = Guid.Parse(Buid); var businessunitinfo = _entityHelper.GetEntitiesAsync(_ => _.Buid == guid).Result.FirstOrDefault(); if (businessunitinfo == null) { 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) { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "未查询到订单!"); } else if (trx.OrderStatus == transactionsORDERSTATUS.FullyRefunded) { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "该订单已退款"); } else if (trx.OrderStatus == transactionsORDERSTATUS.PartiallyRefunded) { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "该订单已部分退款"); } else if (trx.OrderStatus == transactionsORDERSTATUS.Unpaid) { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "该订单未支付"); } else if (trx.OrderStatus == transactionsORDERSTATUS.Unpaid) { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "该订单未支付"); } //获取单价 decimal? ProductPrice = _entityHelper.GetEntitiesAsync(_ => _.Id == trx.ProductId).Result.FirstOrDefault().ProductPrice; if (ProductPrice == null) { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "单价获取失败"); } //计算退款金额 decimal RefundAmount = (decimal)((trx.Qty - trx.OriginalQty) * ProductPrice.Value); if (RefundAmount <= 0.0M) { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "该笔单无需退款"); } //退款 var serviceResult = await _payService.ReturnProcess(RefundAmount, trx.TransactionNumber); Payment.Core.Models.ElectronicOrderProcessResultModel payResult = (Payment.Core.Models.ElectronicOrderProcessResultModel)serviceResult.Data; if (!serviceResult.IsSuccessful() || payResult.ResultCode == "PAY_ERROR") { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "退款失败"); } trx.RefundAmount = RefundAmount; _entityHelper.UpdateAsync(trx); return ServiceResponse.Ok(trx); } public async Task Redeem(int trxId, decimal OriginalQty) { var trx = _entityHelper.GetEntitiesAsync(_ => _.Id == trxId).Result.FirstOrDefault(); if (trx == null) { return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "未查询到订单!"); } trx.OriginalQty = OriginalQty; _entityHelper.UpdateAsync(trx); return ServiceResponse.Ok(trx); } } }