123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- 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;
- namespace Fuel.Application.Service
- {
- public class TransactionsService : ITransactionsService
- {
- private readonly EntityHelper _entityHelper;
- private readonly IHttpContextAccessor _httpContextAccessor;
- private readonly IPayService _payService;
- public readonly IFreeSql _fsql;
- public TransactionsService(EntityHelper entityHelper, IHttpContextAccessor httpContextAccessor, IPayService payService, IFreeSql fsql)
- {
- _entityHelper = entityHelper;
- _httpContextAccessor = httpContextAccessor;
- _payService = payService;
- _fsql = fsql;
- }
- /// <summary>
- /// 创建订单
- /// </summary>
- /// <param name="uploadTransactions"></param>
- /// <returns></returns>
- public async Task<ServiceResponse> CreateTransactions(UploadTransactions uploadTransactions)
- {
- Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id
- string key = string.Empty;
- int OrderType = 0;//订单类型
- if (OrderType == 1)//预支付
- {
- key = uploadTransactions.ExternalGunNumber + ":" +
- uploadTransactions.OriginalAmount + ":" +
- uploadTransactions.Qty + ":" +
- uploadTransactions.MiniProgramID + ":" +
- Buid.ToString();
- }
- 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 _product = await _entityHelper.GetEntitiesAsync<product>(_ => _.Buid == Buid && _.ProductName == uploadTransactions.Product);
- if (_product.Count() <= 0)
- {
- return ServiceResponse.Error("油品查询失败,油品名称:" + uploadTransactions.Product);
- }
- var _nozzle = await _entityHelper.GetEntitiesAsync<nozzle>(_ => _.Buid == Buid && _.ExternalGunNumber == uploadTransactions.ExternalGunNumber);
- if (_nozzle.Count() <= 0)
- {
- return ServiceResponse.Error("油枪查询失败,油枪名称:" + uploadTransactions.ExternalGunNumber);
- }
- var trx = uploadTransactions.ToTransactions(uploadTransactions, Buid, _product.FirstOrDefault(), _nozzle.FirstOrDefault(), OrderType);
- //int affectedRows = _fsql.Insert<transactions>().AppendData(trx).ExecuteAffrows();
- // var affectedRows = _fsql.Insert<transactions>().AppendData(trx).ExecuteInserted();
- var id = _fsql.Insert(trx).ExecuteIdentity();
- if (id > 0)
- {
- var insertedTransaction = _fsql.Select<transactions>()
- .Where(t => t.Id == id)
- .First();
- string jsonString = JsonConvert.SerializeObject(insertedTransaction);
- RedisHelper.SetAsync(key, jsonString, 3600);
- return ServiceResponse.Ok(insertedTransaction);
- }
- else
- {
- return ServiceResponse.Error("订单信息插入失败");
- }
- }
- public async Task<ServiceResponse> GetTransactionsAsync(TransactionsInput input)
- {
- string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault();
- Guid guid = Guid.Parse(Buid);
- Expression<Func<transactions, bool>> 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<transactions>(where);
- return ServiceResponse.Ok(result);
- }
- /// <summary>
- /// 小程序查询未支付订单
- /// </summary>
- /// <returns></returns>
- public async Task<ServiceResponse> GetMiniProgramTransactionsUnpaidAsync(TransactionsInput input)
- {
- string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault();
- Guid guid = Guid.Parse(Buid);
- Expression<Func<transactions, bool>> 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<transactions>(where);
- return ServiceResponse.Ok(result);
- }
- /// <summary>
- /// 小程序用户根据抢号查询未支付订单
- /// </summary>
- /// <returns></returns>
- public async Task<ServiceResponse> GetMiniProgramTransactionsUnpaidNozzleAsync(TransactionsInput input)
- {
- string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault();
- Guid guid = Guid.Parse(Buid);
- Expression<Func<transactions, bool>> where = p => p.Buid == guid;
- if (input.MiniProgramID == null)
- {
- return ServiceResponse.Error("用户id为空");
- }
- where = CombineExpressions(where, p => p.NozzleId == input.NozzleId && p.OrderStatus == transactionsORDERSTATUS.Unpaid);
- var result = await _entityHelper.GetEntitiesAsync<transactions>(where);
- return ServiceResponse.Ok(result);
- }
- /// <summary>
- /// 小程序查询已支付订单
- /// </summary>
- /// <returns></returns>
- public async Task<ServiceResponse> GetMiniProgramTransactionsPaidAsync(TransactionsInput input)
- {
- string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault();
- Guid guid = Guid.Parse(Buid);
- Expression<Func<transactions, bool>> 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<transactions>(where);
- return ServiceResponse.Ok(result);
- }
- /// <summary>
- /// 提交支付
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- public async Task<ServiceResponse> CommitPayment(int trxId, string AuthCode)
- {
- bool paymentOK = false;
- var trx = _entityHelper.GetEntitiesAsync<transactions>(_ => _.Id == trxId).Result.FirstOrDefault();
- if (trx == null)
- {
- return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "未查询到订单!");
- }
- var paytype = _entityHelper.GetEntitiesAsync<paytype>(_ => _.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);
- }
- /// <summary>
- /// 查询redis订单缓存
- /// </summary>
- /// <returns></returns>
- public async Task<transactions> 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<transactions>(respond);
- return transactions;
- }
- // 辅助方法:组合两个表达式
- private static Expression<Func<T, bool>> CombineExpressions<T>(Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
- {
- ParameterExpression param = expr1.Parameters[0];
- Expression body = Expression.AndAlso(expr1.Body, Expression.Invoke(expr2, param));
- return Expression.Lambda<Func<T, bool>>(body, param);
- }
- /// <summary>
- /// 退款
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- public async Task<ServiceResponse> RefundTrx(int trxId,
- double longitude,
- double latitude)
- {
- string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault();
- Guid guid = Guid.Parse(Buid);
- var businessunitinfo = _entityHelper.GetEntitiesAsync<businessunitinfo>(_ => _.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<transactions>(_ => _.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<product>(_ => _.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, "ALL_IN_SCAN", 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<ServiceResponse> UnifiedOrder(int trxId)
- {
- var trx = _entityHelper.GetEntitiesAsync<transactions>(_ => _.Id == trxId).Result.FirstOrDefault();
- if (trx == null)
- {
- return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "未查询到订单!");
- }
- var serviceResult = await _payService.UnifiedOrder((decimal)trx.OriginalAmount, "ALL_IN_SCAN");
- if (!serviceResult.IsSuccessful())
- {
- return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "统一下单失败");
- }
- return ServiceResponse.Ok(serviceResult.Data);
- }
- public async Task<ServiceResponse> Redeem(int trxId, decimal OriginalQty)
- {
- var trx = _entityHelper.GetEntitiesAsync<transactions>(_ => _.Id == trxId).Result.FirstOrDefault();
- if (trx == null)
- {
- return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "未查询到订单!");
- }
- trx.OriginalQty = OriginalQty;
- _entityHelper.UpdateAsync(trx);
- return ServiceResponse.Ok(trx);
- }
- }
- }
|