Explorar o código

小程序接口

Your Name hai 3 meses
pai
achega
78317b1bd8
Modificáronse 36 ficheiros con 922 adicións e 88 borrados
  1. 2 1
      FuelCloud/Fuel.Application/Service/INozzleService.cs
  2. 15 0
      FuelCloud/Fuel.Application/Service/ISiteService.cs
  3. 2 0
      FuelCloud/Fuel.Application/Service/ITransactionsService.cs
  4. 32 13
      FuelCloud/Fuel.Application/Service/NozzleService.cs
  5. 95 0
      FuelCloud/Fuel.Application/Service/SiteService.cs
  6. 72 16
      FuelCloud/Fuel.Application/Service/TransactionsService.cs
  7. 28 0
      FuelCloud/Fuel.Application/Service/UserService.cs
  8. 7 0
      FuelCloud/FuelCloud.sln
  9. 1 0
      FuelCloud/src/Fuel.Payment.Core/GenericProcessResponse.cs
  10. 1 0
      FuelCloud/src/Fuel.Payment.Core/Models/ElectronicOrderModel.cs
  11. 19 0
      FuelCloud/src/Fuel.Payment.Core/Models/PayInfo.cs
  12. 52 0
      FuelCloud/src/Fuel.Payment.Core/Models/PosJsonDateConverter.cs
  13. 27 2
      FuelCloud/src/Fuel.Payment.Server/Controllers/AuthController.cs
  14. 14 5
      FuelCloud/src/Fuel.Payment.Server/Controllers/NozzleController.cs
  15. 32 0
      FuelCloud/src/Fuel.Payment.Server/Controllers/SiteController.cs
  16. 35 5
      FuelCloud/src/Fuel.Payment.Server/Controllers/TransactionsController.cs
  17. 3 0
      FuelCloud/src/Fuel.Payment.Server/MicServer/Middlewares/SignatureValidationMiddleware.cs
  18. 122 2
      FuelCloud/src/Fuel.Payment.Server/MicServer/Middlewares/SignatureValidator.cs
  19. 1 0
      FuelCloud/src/Fuel.Payment.Server/Program.cs
  20. 4 0
      FuelCloud/src/Fuel.Payment.Service/AliPaymentProcessor/Alipay/AlipayPaymentProcessor.cs
  21. 28 1
      FuelCloud/src/Fuel.Payment.Service/AllInPayProcessor/AllInPay/AllInPayProcessor.cs
  22. 8 0
      FuelCloud/src/Fuel.Payment.Service/Factory/AsyncPaymentProcessor.cs
  23. 1 0
      FuelCloud/src/Fuel.Payment.Service/Pay/IPayService.cs
  24. 43 3
      FuelCloud/src/Fuel.Payment.Service/Pay/PayService.cs
  25. 4 0
      FuelCloud/src/Fuel.Payment.Service/UnionPayProcessor/MiniUnionPayProcessor.cs
  26. 5 0
      FuelCloud/src/Fuel.Payment.Service/UnionPayProcessor/UnionPayProcessor.cs
  27. 8 1
      FuelCloud/src/FuelServer.Core/Entity/businessunitinfo.cs
  28. 17 13
      FuelCloud/src/FuelServer.Core/Entity/transactions.cs
  29. 19 0
      FuelCloud/src/FuelServer.Core/HttpRequestReader.cs
  30. 14 15
      FuelCloud/src/FuelServer.Core/Nozzle/Dto/UploadNozzle.cs
  31. 74 0
      FuelCloud/src/FuelServer.Core/Sm4Encryptor.cs
  32. 4 0
      FuelCloud/src/FuelServer.Core/Transactions/Dto/TransactionsInput.cs
  33. 13 11
      FuelCloud/src/FuelServer.Core/Transactions/Dto/UploadTransactions.cs
  34. 14 0
      FuelCloud/src/FuelServer.Core/WechatServer/WechatConstants.cs
  35. 90 0
      FuelCloud/src/FuelServer.Core/WechatServer/WechatUserSessionRepo.cs
  36. 16 0
      FuelCloud/src/FuelServer.Core/WechatServer/WechatUserSessionResponse.cs

+ 2 - 1
FuelCloud/Fuel.Application/Service/INozzleService.cs

@@ -10,7 +10,7 @@ namespace Fuel.Application.Service
 {
     public interface INozzleService
     {
-        Task<ServiceResponse> uploadNozzle(UploadNozzle uploadNozzle);
+        Task<ServiceResponse> UploadNozzle(UploadNozzle uploadNozzle);
         Task<ServiceResponse> UpdateNozzle(UploadNozzle uploadNozzle);
         Task<ServiceResponse> DeleteNozzle(UploadNozzle uploadNozzle);
         Task<List<NozzleInfo>> GetNozzleInfo(int Nozzleid);
@@ -20,5 +20,6 @@ namespace Fuel.Application.Service
         Task<ServiceResponse> UploadTanks(UploadTanks uploadTanks);
         Task<ServiceResponse> UpdateTanks(UploadTanks uploadTanks);
         Task<ServiceResponse> DeleteTanks(UploadTanks uploadTanks);
+        Task<ServiceResponse> UpdateNozzleStatus(List<UploadNozzleStatus> uploadNozzleStatuses);
     }
 }

+ 15 - 0
FuelCloud/Fuel.Application/Service/ISiteService.cs

@@ -0,0 +1,15 @@
+using Fuel.Core.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Fuel.Application.Service
+{
+    public interface ISiteService
+    {
+        Task<ServiceResponse> GetSiteInfo();
+        Task<ServiceResponse> GetAppidSecret(string Code);
+    }
+}

+ 2 - 0
FuelCloud/Fuel.Application/Service/ITransactionsService.cs

@@ -16,10 +16,12 @@ namespace Fuel.Application.Service
         Task<ServiceResponse> GetTransactionsAsync(TransactionsInput input);
         Task<ServiceResponse> CommitPayment(int trxId, string AuthCode);
         Task<ServiceResponse> GetMiniProgramTransactionsUnpaidAsync(TransactionsInput input);
+        Task<ServiceResponse> GetMiniProgramTransactionsUnpaidNozzleAsync(TransactionsInput input);
         Task<ServiceResponse> GetMiniProgramTransactionsPaidAsync(TransactionsInput input);
         Task<ServiceResponse> RefundTrx(int trxId,
             double longitude,
             double latitude);
         Task<ServiceResponse> Redeem(int trxId, decimal OriginalQty);
+        Task<ServiceResponse> UnifiedOrder(int trxId);
     }
 }

+ 32 - 13
FuelCloud/Fuel.Application/Service/NozzleService.cs

@@ -62,7 +62,7 @@ namespace Fuel.Application.Service
             var _product = _fsql.Select<product>().Where(_ => _.Buid == guid && _.ProductId == uploadProduct.ProductId).First();
             if (_product == null)
             {
-                return ServiceResponse.Error("未找到油枪");
+                return await UploadProduct(uploadProduct);
             }
             _product.ProductCode = uploadProduct.ProductCode;
             _product.ProductName = uploadProduct.ProductName;
@@ -118,11 +118,11 @@ namespace Fuel.Application.Service
             }
             tanks tanks = new tanks();
             tanks.Buid = guid;
-            tanks.ProductId = uploadTanks.ProductId;
+            tanks.ProductId = (long)uploadTanks.ProductId;
             tanks.TankCapacity = uploadTanks.TankCapacity;
             tanks.ProductName = uploadTanks.ProductName;
             tanks.TankNumber = uploadTanks.TankNumber;
-
+            tanks.TankID = uploadTanks.TankID;
             int affectedRows = _fsql.Insert<tanks>().AppendData(tanks).ExecuteAffrows();
             if (affectedRows <= 0)
             {
@@ -140,11 +140,11 @@ namespace Fuel.Application.Service
         {
             Guid guid = HttpRequestReader.GetCurrentBuId(); //站点id
             var _tanks = _fsql.Select<tanks>().Where(_ => _.Buid == guid && _.TankID == uploadTanks.TankID).First();
-            if (_tanks != null)
+            if (_tanks == null)
             {
-                return ServiceResponse.Error("油灌已存在,请勿重复上传");
+                return await UploadTanks(uploadTanks);
             }
-            _tanks.ProductId = uploadTanks.ProductId;
+            _tanks.ProductId = (long)uploadTanks.ProductId;
             _tanks.TankCapacity = uploadTanks.TankCapacity;
             _tanks.ProductName = uploadTanks.ProductName;
             _tanks.TankNumber = uploadTanks.TankNumber;
@@ -165,9 +165,9 @@ namespace Fuel.Application.Service
         {
             Guid guid = HttpRequestReader.GetCurrentBuId(); //站点id
             var _tanks = _fsql.Select<tanks>().Where(_ => _.Buid == guid && _.TankID == uploadTanks.TankID).First();
-            if (_tanks != null)
+            if (_tanks == null)
             {
-                return ServiceResponse.Error("油灌已存在,请勿重复上传");
+                return ServiceResponse.Error("油灌不存在,删除失败");
             }
             int affectedRows = _fsql.Delete<tanks>()
      .Where(p => p.TankID == uploadTanks.TankID)
@@ -188,21 +188,21 @@ namespace Fuel.Application.Service
         /// </summary>
         /// <param name="uploadNozzle"></param>
         /// <returns></returns>
-        public async Task<ServiceResponse> uploadNozzle(UploadNozzle uploadNozzle)
+        public async Task<ServiceResponse> UploadNozzle(UploadNozzle uploadNozzle)
         {
             //RedisHelper.HSetAsync("Transaction", "11:22:33:44", "3232");
             //RedisHelper.SetAsync("33:22:33:44", "qweqweqwe", 3600);
             // var fsdds = RedisHelper.GetAsync("33:22:33:44");
             //var das = RedisHelper.ExpireAsync("33:22:33:44", 10);
             Guid guid = HttpRequestReader.GetCurrentBuId(); //站点id
-            var _product = _fsql.Select<product>().Where(_ => _.Buid == guid && _.ProductName == uploadNozzle.ProductName).First();
-            var _tanks = _fsql.Select<tanks>().Where(_ => _.Buid == guid && _.TankNumber == uploadNozzle.TankNumber).First();
+            var _product = _fsql.Select<product>().Where(_ => _.Buid == guid && _.ProductId == uploadNozzle.ProductId).First();
+            var _tanks = _fsql.Select<tanks>().Where(_ => _.Buid == guid && _.TankID == uploadNozzle.TankID).First();
             var isproduct = _fsql.Select<nozzle>().Where(_ => _.Buid == guid && _.NozzleId == uploadNozzle.NozzleId).First();
             if (isproduct != null)
             {
                 return ServiceResponse.Error("油枪已存在");
             }
-            if (_product != null || _tanks != null)
+            if (_product == null || _tanks == null)
             {
                 return ServiceResponse.Error("油品或油罐信息为空");
             }
@@ -213,6 +213,7 @@ namespace Fuel.Application.Service
             _nozzle.InternalGunNumber = uploadNozzle.InternalGunNumber;
             _nozzle.ExternalGunNumber = uploadNozzle.ExternalGunNumber;
             _nozzle.ProductID = _product.Id;
+            _nozzle.NozzleId = uploadNozzle.NozzleId;
             int affectedRows = _fsql.Insert<nozzle>().AppendData(_nozzle).ExecuteAffrows();
             if (affectedRows <= 0)
             {
@@ -231,11 +232,13 @@ namespace Fuel.Application.Service
             var _nozzle = _fsql.Select<nozzle>().Where(_ => _.Buid == guid && _.NozzleId == uploadNozzle.NozzleId).First();
             if (_nozzle == null)
             {
-                return ServiceResponse.Error("未找到油枪");
+                return await UploadNozzle(uploadNozzle);
             }
             _nozzle.PumpId = uploadNozzle.PumpID;
             _nozzle.InternalGunNumber = uploadNozzle.InternalGunNumber;
             _nozzle.ExternalGunNumber = uploadNozzle.ExternalGunNumber;
+            _nozzle.TankId = (long)uploadNozzle.TankID;
+            _nozzle.ProductID = (long)uploadNozzle.ProductId;
             int affectedRows = _fsql.Update<nozzle>().SetSource(_nozzle).ExecuteAffrows();
             if (affectedRows <= 0)
             {
@@ -266,6 +269,22 @@ namespace Fuel.Application.Service
             return ServiceResponse.Ok();
         }
 
+        public async Task<ServiceResponse> UpdateNozzleStatus(List<UploadNozzleStatus> uploadNozzleStatuses)
+        {
+            Guid guid = HttpRequestReader.GetCurrentBuId(); //站点id
+            List<nozzle> nozzleStatuses = new List<nozzle>();
+            foreach (var n in uploadNozzleStatuses)
+            {
+                nozzleStatuses.Add(new nozzle() { 
+                    NozzleId = n.NozzleId,
+                    Buid = guid,
+                    Status = n.Status
+                });
+            }
+            int affectedRows = _fsql.InsertOrUpdate<nozzle>().SetSource(nozzleStatuses).ExecuteAffrows();
+            return ServiceResponse.Ok();
+        }
+
         public async Task<List<NozzleInfo>> GetNozzleInfo(int Nozzleid)
         {
             Guid guid = HttpRequestReader.GetCurrentBuId(); //站点id

+ 95 - 0
FuelCloud/Fuel.Application/Service/SiteService.cs

@@ -0,0 +1,95 @@
+using Fuel.Core;
+using Fuel.Core.Models;
+using Fuel.Core.Nozzle.Dto;
+using Fuel.Core.Transactions.Dto;
+using Fuel.Core.WechatServer;
+using FuelServer.Core.Entity;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Fuel.Application.Service
+{
+    public class SiteService: ISiteService
+    {
+        public readonly IFreeSql _fsql;
+        public SiteService(IFreeSql freeSql)
+        { 
+             _fsql = freeSql;
+        }
+        public async Task<ServiceResponse> GetSiteInfo()
+        {
+            Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id
+            var site = _fsql.Select<businessunitinfo>().Where(_ => _.Buid == Buid ).First();
+            var SiteInfo = new {
+                site = new { 
+                  Name = site.Name,//站点名称
+                  GpsCoordinates = site.GpsCoordinates,//油站经纬度
+                  PaymentMode = site.PaymentMode,//预支付:1,后支付:2
+                },
+                userInfo = new
+                {
+                    UserName = "",//用户名称
+                    UserAvatarUrl = "",//用户头像地址
+                    UserAddress= "",//用户地址
+                    UserPhoneNumber = ""//用户手机号
+                }
+            };
+            return ServiceResponse.Ok(SiteInfo);
+        }
+        public async Task<ServiceResponse> GetAppidSecret(string Code)
+        {
+            Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id
+            var site = _fsql.Select<businessunitinfo>().Where(_ => _.Buid == Buid).First();
+            if (site == null)
+            {
+                return ServiceResponse.Error("获取站点小程序appid与Secret失败,BUID:" + Buid);
+            }
+            WechatUserSessionResponse userSession =
+               await WechatLoginCodeToSessionKeyNOpenId(Code, site.Appid,site.Secret);
+            var thirdSessionKey = GenerateThirdSessionKey();
+            WechatUserSessionRepo.AddUserSession(thirdSessionKey, userSession);
+            return ServiceResponse.Ok(thirdSessionKey);
+        }
+        /// <summary>
+        /// 微信小程序登录
+        /// </summary>
+        /// <param name="jsCode"></param>
+        /// <param name="AppId"></param>
+        /// <param name="AppSecret"></param>
+        /// <returns></returns>
+        public static async Task<WechatUserSessionResponse> WechatLoginCodeToSessionKeyNOpenId(string jsCode, string AppId, string AppSecret)
+        {
+            string url = string.Format(WechatConstants.Jscode2sessionUrl,
+               AppId, AppSecret, jsCode);
+            HttpClient client = new HttpClient();
+            client.DefaultRequestHeaders.Accept.Clear();
+            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+
+            HttpResponseMessage response = await client.GetAsync(url);
+            if (response.IsSuccessStatusCode)
+            {
+                var responseContent = await response.Content.ReadAsStringAsync();
+
+                var userSession = JsonConvert.DeserializeObject<WechatUserSessionResponse>(responseContent);
+
+                return userSession;
+            }
+            else
+            {
+                return null;
+            }
+
+        }
+        private string GenerateThirdSessionKey()
+        {
+            var thirdSessionKey = Guid.NewGuid();
+            return thirdSessionKey.ToString();
+        }
+
+    }
+}

+ 72 - 16
FuelCloud/Fuel.Application/Service/TransactionsService.cs

@@ -8,6 +8,8 @@ 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
@@ -17,11 +19,13 @@ namespace Fuel.Application.Service
         private readonly EntityHelper _entityHelper;
         private readonly IHttpContextAccessor _httpContextAccessor;
         private readonly IPayService _payService;
-        public TransactionsService(EntityHelper entityHelper, IHttpContextAccessor httpContextAccessor, 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>
@@ -31,40 +35,60 @@ namespace Fuel.Application.Service
         /// <returns></returns>
         public async Task<ServiceResponse> CreateTransactions(UploadTransactions uploadTransactions)
         {
-            string Buid = _httpContextAccessor.HttpContext.Request.Headers["Buid"].FirstOrDefault();
-            Guid guid = Guid.Parse(Buid);
+            Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id
             string key = string.Empty;
-            if (uploadTransactions.Type == 1)//预支付
+            int OrderType = 0;//订单类型
+            if (OrderType == 1)//预支付
             {
-                key = uploadTransactions.NozzleId + ":" +
+                key = uploadTransactions.ExternalGunNumber + ":" +
                          uploadTransactions.OriginalAmount + ":" +
                          uploadTransactions.Qty + ":" +
                          uploadTransactions.MiniProgramID + ":" +
-                         Buid;
+                         Buid.ToString();
             }
             else//后支付
             {
-                key = uploadTransactions.NozzleId + ":" +
+                key = uploadTransactions.ExternalGunNumber + ":" +
                        uploadTransactions.OriginalAmount + ":" +
                        uploadTransactions.Qty + ":" +
                        uploadTransactions.MiniProgramID + ":" +
                        uploadTransactions.FuelItemTransactionEndTime + ":" +
                         uploadTransactions.TransactionNumber + ":" +
-                       Buid;
+                       Buid.ToString();
             }
             transactions output = await GetRedisTransactions(uploadTransactions, key);
             if (output != null)
             {
                 return ServiceResponse.Ok(output);
             }
-            var _product = await _entityHelper.GetEntitiesAsync<product>(_ => _.Buid == guid && _.ProductName == uploadTransactions.Product);
-            var _nozzle = await _entityHelper.GetEntitiesAsync<nozzle>(_ => _.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);
+            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(respond);
+                RedisHelper.SetAsync(key, jsonString, 3600);
+                return ServiceResponse.Ok(insertedTransaction);
+            }
+            else
+            {
+                return ServiceResponse.Error("订单信息插入失败");
+            }
         }
         public async Task<ServiceResponse> GetTransactionsAsync(TransactionsInput input)
         {
@@ -116,6 +140,24 @@ namespace Fuel.Application.Service
             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>
@@ -253,7 +295,7 @@ namespace Fuel.Application.Service
                 return ServiceResponse.Error(HttpStatusCode.NotAcceptable, "该笔单无需退款");
             }
             //退款
-            var serviceResult = await _payService.ReturnProcess(RefundAmount, trx.TransactionNumber);
+            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")
             {
@@ -264,6 +306,20 @@ namespace Fuel.Application.Service
             _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();

+ 28 - 0
FuelCloud/Fuel.Application/Service/UserService.cs

@@ -39,7 +39,21 @@ namespace Fuel.Application.Service
                 permissionList.Add(permission.d.Code);
             }
             permissionList.Add("Nozzle:uploadNozzle:POST");
+            permissionList.Add("Nozzle:UpdateNozzle:PUT");
             permissionList.Add("Nozzle:DeleteNozzle:Delete");
+            permissionList.Add("Nozzle:UpdateNozzleStatus:PUT");
+
+            permissionList.Add("Nozzle:uploadProduct:POST");
+            permissionList.Add("Nozzle:UpdateProduct:Put");
+            permissionList.Add("Nozzle:DeleteProduct:Delete");
+            permissionList.Add("Nozzle:GetNozzleInfo:GET");
+
+            permissionList.Add("Nozzle:uploadTanks:POST");
+            permissionList.Add("Nozzle:UpdateTanks:Put");
+            permissionList.Add("Nozzle:DeleteTanks:Delete");
+
+            permissionList.Add("Transactions:CreateTransactions:POST");
+            permissionList.Add("Transactions:UnifiedOrder:GET");
             return permissionList;
 
         }
@@ -59,7 +73,21 @@ namespace Fuel.Application.Service
                     permissionList.Add(permission.e.Code);
             }
             permissionList.Add("Nozzle:uploadNozzle:POST");
+            permissionList.Add("Nozzle:UpdateNozzle:PUT");
             permissionList.Add("Nozzle:DeleteNozzle:Delete");
+            permissionList.Add("Nozzle:UpdateNozzleStatus:PUT");
+
+            permissionList.Add("Nozzle:uploadProduct:POST");
+            permissionList.Add("Nozzle:UpdateProduct:Put");
+            permissionList.Add("Nozzle:DeleteProduct:Delete");
+            permissionList.Add("Nozzle:GetNozzleInfo:GET");
+
+            permissionList.Add("Nozzle:uploadTanks:POST");
+            permissionList.Add("Nozzle:UpdateTanks:Put");
+            permissionList.Add("Nozzle:DeleteTanks:Delete");
+
+            permissionList.Add("Transactions:CreateTransactions:POST");
+            permissionList.Add("Transactions:UnifiedOrder:GET");
             return permissionList;
         }
         public Task<users> GetUsers()

+ 7 - 0
FuelCloud/FuelCloud.sln

@@ -27,6 +27,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fuel.Infrastructure", "Fuel
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fuel.Application", "Fuel.Application\Fuel.Application.csproj", "{6DBC4319-6D95-482B-9DBD-2F48BA72B0D9}"
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fuel.Payment.Core", "src\Fuel.Payment.Core\Fuel.Payment.Core.csproj", "{60BA5832-E5A2-479F-A3C2-CC3AA2538D94}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -73,6 +75,10 @@ Global
 		{6DBC4319-6D95-482B-9DBD-2F48BA72B0D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{6DBC4319-6D95-482B-9DBD-2F48BA72B0D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{6DBC4319-6D95-482B-9DBD-2F48BA72B0D9}.Release|Any CPU.Build.0 = Release|Any CPU
+		{60BA5832-E5A2-479F-A3C2-CC3AA2538D94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{60BA5832-E5A2-479F-A3C2-CC3AA2538D94}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{60BA5832-E5A2-479F-A3C2-CC3AA2538D94}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{60BA5832-E5A2-479F-A3C2-CC3AA2538D94}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -89,6 +95,7 @@ Global
 		{AEDE8AC1-17AB-47A3-8CBA-36D32484B6ED} = {A70E5B56-8E5C-4EB2-92F0-66FA7E67A2D1}
 		{FB53499B-CA9D-4E75-9EDC-2A04DCD4C5D1} = {A70E5B56-8E5C-4EB2-92F0-66FA7E67A2D1}
 		{6DBC4319-6D95-482B-9DBD-2F48BA72B0D9} = {A70E5B56-8E5C-4EB2-92F0-66FA7E67A2D1}
+		{60BA5832-E5A2-479F-A3C2-CC3AA2538D94} = {A70E5B56-8E5C-4EB2-92F0-66FA7E67A2D1}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {61A0BE4B-D15C-4489-B07B-A028AEC93C1D}

+ 1 - 0
FuelCloud/src/Fuel.Payment.Core/GenericProcessResponse.cs

@@ -18,5 +18,6 @@ namespace Fuel.Payment.Core
         public TongLianResponseV2 AllInPayResponseV2 { get; set; }
         public ElectronicOrderModel electronicOrderModel { get; set; }
         public  List<ElectronicOrderProcessResultModel> ProcessResults { get; set; }
+        public object UnifiedOrderResult { get; set; }
     }
 }

+ 1 - 0
FuelCloud/src/Fuel.Payment.Core/Models/ElectronicOrderModel.cs

@@ -102,6 +102,7 @@ namespace Fuel.Payment.Core.Models
         /// Gets or sets the process result which from the communication result with the 3rd party payment server
         /// </summary>
         public List<ElectronicOrderProcessResultModel> ProcessResults { get; set; }
+        public object UnifiedOrderResult { get; set; }
 
         public string ToSimpleLogString()
         {

+ 19 - 0
FuelCloud/src/Fuel.Payment.Core/Models/PayInfo.cs

@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Fuel.Payment.Core.Models
+{
+    public class PayInfo
+    {
+        public string appId { get; set; }
+        public string timeStamp { get; set; }
+        public string nonceStr { get; set; }
+        public string package { get; set; }
+        public string signType { get; set; }
+        public string paySign { get; set; }
+        public string billNumber { get; set; }
+    }
+}

+ 52 - 0
FuelCloud/src/Fuel.Payment.Core/Models/PosJsonDateConverter.cs

@@ -0,0 +1,52 @@
+using Newtonsoft.Json.Converters;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using System.Globalization;
+
+
+namespace Fuel.Payment.Core.Models
+{
+    public class PosJsonDateConverter : DateTimeConverterBase
+    {
+        List<string> timeFormats = new List<string>{
+            "M/d/yyyy h:mm:ss",
+            "M/d/yyyy h:mm:ss tt",
+            "yyyy/M/d h:mm:ss",
+            "yyyy/M/d h:mm:ss tt",
+            "yyyy/MM/dd h:mm:ss",
+            "yyyy-MM-dd HH:mm:ss",
+            "yyyy-MM-dd HH:mm:ss tt",
+            "yyyy-MM-dd HH:mm:ss fff",
+            "yyyy-MM-dd HH:mm:ss ffffff"};
+
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            DateTime result;
+            try
+            {
+                foreach (var format in timeFormats)
+                {
+                    if (DateTime.TryParseExact(reader.Value.ToString(), format, CultureInfo.InvariantCulture, DateTimeStyles.None, out result))
+                    {
+                        result = DateTime.ParseExact(reader.Value.ToString(), format, null);
+                        return result;
+                    }
+                }
+                return result = DateTime.Parse(reader.Value.ToString());
+            }
+            catch (FormatException f)
+            {
+                return default(DateTime);
+            }
+        }
+
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            writer.WriteValue(((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss.fff"));
+        }
+    }
+}

+ 27 - 2
FuelCloud/src/Fuel.Payment.Server/Controllers/AuthController.cs

@@ -1,11 +1,15 @@
 using Fuel.Application.Service;
+using Fuel.Core;
 using Fuel.Core.User;
+using Fuel.Core.WechatServer;
 using FuelServer.Core;
 using FuelServer.Core.Entity;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.IdentityModel.Tokens;
+using Newtonsoft.Json;
 using System.IdentityModel.Tokens.Jwt;
+using System.Net.Http.Headers;
 using System.Security.Claims;
 using System.Text;
 
@@ -17,18 +21,20 @@ namespace Fuel.PaymentServer.Controllers
     {
         private readonly IUserService _userService;
         private readonly IConfiguration _configuration;
+        private readonly ISiteService _siteService;
 
-        public AuthController(IUserService userService, IConfiguration configuration)
+        public AuthController(IUserService userService, IConfiguration configuration, ISiteService siteService)
         {
             _userService = userService;
             _configuration = configuration;
+            _siteService = siteService;
         }
         /// <summary>
         /// 登录
         /// </summary>
         /// <param name="login"></param>
         /// <returns></returns>
-        [HttpPost("login")]
+        [HttpGet("login")]
         public IActionResult Login([FromBody] LoginModel login)
         {
             var user = _userService.ValidateCredentials(login.Username, login.Password);
@@ -38,6 +44,25 @@ namespace Fuel.PaymentServer.Controllers
             var tokenString = GenerateJwt(user);
             return Ok(new { Token = tokenString });
         }
+        /// <summary>
+        /// 小程序登录
+        /// </summary>
+        /// <param name="login"></param>
+        /// <returns></returns>
+        [HttpGet("Wechatlogin")]
+        public async Task<IActionResult> Wechatlogin(string code)
+        {
+            Guid Buid = HttpRequestReader.GetCurrentBuId(); //站点id
+            Guid WachatID = HttpRequestReader.GetWachatID(); //小程序用户id
+            var appidResponse = await _siteService.GetAppidSecret(code);
+            if (!appidResponse.IsSuccessful())
+            {
+                return StatusCode((int)appidResponse.StatusCode, appidResponse.Message);
+            }
+            return Ok(appidResponse);
+        }
+
+
 
         private string GenerateJwt(users user)
         {

+ 14 - 5
FuelCloud/src/Fuel.Payment.Server/Controllers/NozzleController.cs

@@ -23,12 +23,12 @@ namespace Fuel.PaymentServer.Controllers
         /// </summary>
         /// <param name="uploadNozzle"></param>
         /// <returns></returns>
-        [Permission("Nozzle:uploadNozzle:POST")]
-        [Route("uploadNozzle")]
+        [Permission("Nozzle:UploadNozzle:POST")]
+        [Route("UploadNozzle")]
         [HttpPost]
-        public async Task<IActionResult> uploadNozzle(UploadNozzle uploadNozzle)
+        public async Task<IActionResult> UploadNozzle(UploadNozzle uploadNozzle)
         {
-            var serviceResult = await InozzleService.uploadNozzle(uploadNozzle);
+            var serviceResult = await InozzleService.UploadNozzle(uploadNozzle);
             return Ok(serviceResult);
         }
         /// <summary>
@@ -57,13 +57,22 @@ namespace Fuel.PaymentServer.Controllers
             var serviceResult = await InozzleService.DeleteNozzle(uploadNozzle);
             return Ok(serviceResult);
         }
+        [Permission("Nozzle:UpdateNozzleStatus:PUT")]
+        [Route("UpdateNozzleStatus")]
+        [HttpPut]
+        public async Task<IActionResult> UpdateNozzleStatus(List<UploadNozzleStatus> uploadNozzleStatuses)
+        {
+           var serviceResult = await InozzleService.UpdateNozzleStatus(uploadNozzleStatuses);
+            return Ok(serviceResult);
+        }
         /// <summary>
         /// 获取油枪信息
         /// </summary>
         /// <param name="Nozzleid"></param>
         /// <returns></returns>
+        [Permission("Nozzle:GetNozzleInfo:GET")]
         [Route("GetNozzleInfo")]
-        [HttpPost]
+        [HttpGet]
         public async Task<List<NozzleInfo>> GetNozzleInfo(int Nozzleid)
         {
             var data = await InozzleService.GetNozzleInfo(Nozzleid);

+ 32 - 0
FuelCloud/src/Fuel.Payment.Server/Controllers/SiteController.cs

@@ -0,0 +1,32 @@
+using Fuel.Application.Authorization;
+using Fuel.Application.Service;
+using Fuel.Core.Transactions.Dto;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Fuel.PaymentServer.Controllers
+{
+    [Route("api/[controller]")]
+    [ApiController]
+    public class SiteController : ControllerBase
+    {
+        private readonly ISiteService _siteService;
+       public SiteController(ISiteService siteService)
+        { 
+             _siteService = siteService;
+        }
+        /// <summary>
+        /// 获取站点信息与用户信息
+        /// </summary>
+        /// <param name=""></param>
+        /// <returns></returns>
+        [Permission("Site:GetSiteInfo:GET")]
+        [Route("GetSiteInfo")]
+        [HttpGet]
+        public async Task<IActionResult> GetSiteInfo()
+        {
+            var serviceResult = await _siteService.GetSiteInfo();
+            return Ok(serviceResult);
+        }
+    }
+}

+ 35 - 5
FuelCloud/src/Fuel.Payment.Server/Controllers/TransactionsController.cs

@@ -1,4 +1,5 @@
-using Fuel.Application.Service;
+using Fuel.Application.Authorization;
+using Fuel.Application.Service;
 using Fuel.Core.Nozzle.Dto;
 using Fuel.Core.Transactions.Dto;
 using FuelServer.Core.Entity;
@@ -10,7 +11,7 @@ namespace Fuel.PaymentServer.Controllers
 {
     [Route("api/[controller]")]
     [ApiController]
-    [Authorize]
+    //[Authorize]
     public class TransactionsController : ControllerBase
     {
         private readonly ITransactionsService _transactionsService;
@@ -23,6 +24,7 @@ namespace Fuel.PaymentServer.Controllers
         /// </summary>
         /// <param name="uploadTransactions"></param>
         /// <returns></returns>
+        [Permission("Transactions:CreateTransactions:POST")]
         [Route("CreateTransactions")]
         [HttpPost]
         public async Task<IActionResult> CreateTransactionsAsync(UploadTransactions uploadTransactions)
@@ -43,17 +45,33 @@ namespace Fuel.PaymentServer.Controllers
             return Ok(serviceResult);
         }
         /// <summary>
-        /// 小程序查询未支付订单
+        /// 小程序用户查询未支付订单
         /// </summary>
         /// <param name="input"></param>
         /// <returns></returns>
+        [Permission("Transactions:GetMiniProgramTransactionsUnpaidQuery:GET")]
         [Route("GetMiniProgramTransactionsUnpaidQuery")]
-        [HttpPost]
+        [HttpGet]
         public async Task<IActionResult> GetMiniProgramTransactionsUnpaidAsync(TransactionsInput input)
         {
             var serviceResult = await _transactionsService.GetMiniProgramTransactionsUnpaidAsync(input);
             return Ok(serviceResult);
         }
+
+        /// <summary>
+        /// 小程序用户根据抢号查询未支付订单
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        [Permission("Transactions:GetMiniProgramTransactionsUnpaidNozzle:GET")]
+        [Route("GetMiniProgramTransactionsUnpaidNozzle")]
+        [HttpGet]
+        public async Task<IActionResult> GetMiniProgramTransactionsUnpaidNozzleAsync(TransactionsInput input)
+        {
+            var serviceResult = await _transactionsService.GetMiniProgramTransactionsUnpaidNozzleAsync(input);
+            return Ok(serviceResult);
+        }
+
         /// <summary>
         /// 小程序查询已支付订单
         /// </summary>
@@ -109,6 +127,18 @@ namespace Fuel.PaymentServer.Controllers
             var serviceResult = await _transactionsService.Redeem(trxId, OriginalQty);
             return Ok(serviceResult);
         }
-
+        /// <summary>
+        /// 统一下单
+        /// </summary>
+        /// <param name="trxid"></param>
+        /// <returns></returns>
+        [Permission("Transactions:UnifiedOrder:GET")]
+        [Route("UnifiedOrder")]
+        [HttpGet]
+        public async Task<IActionResult> UnifiedOrder(int trxid)
+        {
+            var serviceResult = await _transactionsService.UnifiedOrder(trxid);
+            return Ok(serviceResult);
+        }
     }
 }

+ 3 - 0
FuelCloud/src/Fuel.Payment.Server/MicServer/Middlewares/SignatureValidationMiddleware.cs

@@ -87,6 +87,9 @@ namespace DFS.Core.Mvc.Middlewares
                     await _next(context);
                     return;
                 }
+                //await _next(context);
+                //return;
+
                 context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                 await context.Response.WriteAsync("无效的签名");
                 return;

+ 122 - 2
FuelCloud/src/Fuel.Payment.Server/MicServer/Middlewares/SignatureValidator.cs

@@ -1,6 +1,8 @@
 using DFS.Infrastructure.Extension.SM;
+using Fuel.Core;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.Logging;
+using Org.BouncyCastle.Utilities.Encoders;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -60,8 +62,14 @@ namespace DFS.Core.Mvc.Middlewares
                 //    .Select(k => $"{k}={queryString[k]}")
                 //    .Aggregate((current, next) => current + "&" + next);
 
-                // 待签字符串
-                var stringToSign = $"sign_method={signMethod}&secret_id={secretId}&nonce={nonce}&timestamp={timestamp}&{bodyContent}";
+                // 待签字符串  
+                var stringToSign = $"sign_method={signMethod}&secret_id={secretId}&nonce={nonce}&timestamp={timestamp}";
+                if (!string.IsNullOrEmpty(bodyContent))
+                {
+                    stringToSign += bodyContent;
+                }
+              //var sfd =  Sm4Encryptor.Encrypt(stringToSign, Secret);
+                //stringToSign = Sm4Encryptor.Encrypt(stringToSign, Secret);
                 stringToSign = stringToSign.SM4Encrypt_ECB(Secret);
                 // 根据 RFC3986 对字符串进行 URL 编码
                 var encodedString = Uri.EscapeDataString(stringToSign);
@@ -87,5 +95,117 @@ namespace DFS.Core.Mvc.Middlewares
             // 将字节数组转换为 Base64 字符串
             return Convert.ToBase64String(bytes);
         }
+
+        public string Encrypt(string plainText)
+        {
+            byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
+
+            // 加密
+            // byte[] encryptedBytes = sm4.EncryptECB(plainTextBytes);
+
+            // 这里我们模拟加密过程,直接返回原始数据(你需要替换为实际的加密代码)
+            byte[] encryptedBytes = plainTextBytes; // 假设加密后数据不变,仅作示例
+
+            // 返回Base64编码的加密字符串
+            return Convert.ToBase64String(encryptedBytes);
+        }
+
+
+        public  string SM4Encrypt_ECB( string plainText, string secretKey, bool hexString = false)
+        {
+            Sm4Context sm4Context = new Sm4Context();
+            sm4Context.isPadding = true;
+            sm4Context.mode = 1;
+            byte[] key = (!hexString) ? Encoding.Default.GetBytes(secretKey) : Decode(secretKey);
+            Sm4 sm = new Sm4();
+            sm.sm4_setkey_enc(sm4Context, key);
+            byte[] data = sm.sm4_crypt_ecb(sm4Context, Encoding.Default.GetBytes(plainText));
+            return Encoding.Default.GetString(Encode(data, 0, data.Length));
+        }
+        public byte[] Decode(string hexString)
+        {
+            // 确保输入字符串长度为偶数
+            if (hexString.Length % 2 != 0)
+            {
+                throw new ArgumentException("Hexadecimal string must have an even length", nameof(hexString));
+            }
+
+            // 创建一个输出流来存储解码后的字节数据
+            using (MemoryStream outputStream = new MemoryStream(hexString.Length / 2))
+            {
+                for (int i = 0; i < hexString.Length; i += 2)
+                {
+                    // 获取两个字符并将其转换为字节
+                    char highNibbleChar = hexString[i];
+                    char lowNibbleChar = hexString[i + 1];
+
+                    byte highNibble = CharToByte(highNibbleChar);
+                    byte lowNibble = CharToByte(lowNibbleChar);
+
+                    if (highNibble == 0xFF || lowNibble == 0xFF)
+                    {
+                        throw new ArgumentException("Invalid hexadecimal character encountered.", nameof(hexString));
+                    }
+
+                    // 合并两个半字节为一个完整的字节
+                    byte decodedByte = (byte)((highNibble << 4) | lowNibble);
+
+                    // 将解码后的字节写入输出流
+                    outputStream.WriteByte(decodedByte);
+                }
+
+                return outputStream.ToArray();
+            }
+        }
+
+        // 私有辅助方法用于将字符转换为对应的数值
+        private byte CharToByte(char c)
+        {
+            if (c >= '0' && c <= '9')
+                return (byte)(c - '0');
+            if (c >= 'A' && c <= 'F')
+                return (byte)(c - 'A' + 10);
+            if (c >= 'a' && c <= 'f')
+                return (byte)(c - 'a' + 10);
+
+            // 如果字符不是有效的十六进制字符,则返回0xFF作为错误标志
+            return 0xFF;
+        }
+        // 实例方法用于编码字节数组到十六进制字符串
+        public byte[] Encode(byte[] data, int offset, int length)
+        {
+            if (data == null)
+                throw new ArgumentNullException(nameof(data), "Input data cannot be null.");
+            if (offset < 0 || offset >= data.Length)
+                throw new ArgumentOutOfRangeException(nameof(offset), "Offset is out of range.");
+            if (length <= 0 || offset + length > data.Length)
+                throw new ArgumentOutOfRangeException(nameof(length), "Length is out of range.");
+
+            // 创建一个输出流来存储编码后的十六进制字符串
+            using (MemoryStream outputStream = new MemoryStream(length * 2))
+            {
+                for (int i = offset; i < offset + length; i++)
+                {
+                    byte b = data[i];
+                    // 将每个字节转换为两个十六进制字符
+                    byte highNibble = (byte)((b >> 4) & 0xF);
+                    byte lowNibble = (byte)(b & 0xF);
+
+                    outputStream.WriteByte(ConvertToHexChar(highNibble));
+                    outputStream.WriteByte(ConvertToHexChar(lowNibble));
+                }
+
+                return outputStream.ToArray();
+            }
+        }
+
+        // 私有辅助方法用于将半字节转换为对应的十六进制字符
+        private byte ConvertToHexChar(byte nibble)
+        {
+            if (nibble < 10)
+                return (byte)('0' + nibble); // 数字 0-9
+            else
+                return (byte)('a' - 10 + nibble); // 字母 a-f
+        }
     }
 }

+ 1 - 0
FuelCloud/src/Fuel.Payment.Server/Program.cs

@@ -66,6 +66,7 @@ builder.Services.AddScoped<INozzleService, NozzleService>();
 builder.Services.AddScoped<ITransactionsService, TransactionsService>();
 builder.Services.AddScoped<IUserService, UserService>();
 builder.Services.AddScoped<IApplyService, ApplyService>();
+builder.Services.AddScoped<ISiteService, SiteService>();
 builder.Services.AddScoped<Authorization>();
 // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
 builder.Services.AddEndpointsApiExplorer();

+ 4 - 0
FuelCloud/src/Fuel.Payment.Service/AliPaymentProcessor/Alipay/AlipayPaymentProcessor.cs

@@ -331,5 +331,9 @@ namespace Fuel.Payment.Service.AliPaymentProcessor.Alipay
 
         }
 
+        protected override Task<object> UnifiedOrderResult(GenericProcessResponse order, ElectronicOrderModel electronicOrderModel)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 28 - 1
FuelCloud/src/Fuel.Payment.Service/AllInPayProcessor/AllInPay/AllInPayProcessor.cs

@@ -71,6 +71,29 @@ namespace Fuel.Payment.Service.AllInPayProcessor.AllInPay
             return eOrder;
         }
         /// <summary>
+        /// 统一下单结果
+        /// </summary>
+        /// <param name="processResponse"></param>
+        /// <param name="eOrder"></param>
+        /// <returns></returns>
+        protected override async Task<object> UnifiedOrderResult(GenericProcessResponse processResponse, ElectronicOrderModel eOrder)
+        {
+            object response = null;
+            var tongLianResponse = processResponse.AllInPayResponse;
+            if (tongLianResponse != null && eOrder.TradeStatus == TradeStatus.SUCCESS &&
+                              tongLianResponse.ContainsKey("payinfo"))
+            {
+                var setting = new JsonSerializerSettings();
+                setting.Converters.Add(new PosJsonDateConverter());
+
+                var payInfo = JsonConvert.DeserializeObject<PayInfo>(tongLianResponse["payinfo"], setting);
+                payInfo.billNumber = eOrder.BillNumber;
+                response = payInfo;
+            }
+            eOrder.UnifiedOrderResult = response;
+            return eOrder;
+        }
+        /// <summary>
         /// 初始化参数
         /// </summary>
         /// <param name="order"></param>
@@ -171,6 +194,7 @@ namespace Fuel.Payment.Service.AllInPayProcessor.AllInPay
 
         public override async Task<GenericProcessResponse> UnifiedOrder(ElectronicOrderModel order)
         {
+            order.Config = Initialize(order).Result?.electronicOrderModel?.Config;
             order.TradeStatus = TradeStatus.PAYERROR;
             var response = new Dictionary<string, string>();
             try
@@ -195,10 +219,13 @@ namespace Fuel.Payment.Service.AllInPayProcessor.AllInPay
             {
                 _logger.Error($"Request AllInPayV2 exceptioned: {ex.ToString()}");
             }
-            return new GenericProcessResponse()
+            var Generic = new GenericProcessResponse()
             {
                 AllInPayResponse = response
             };
+            var ProcessResults = await UnifiedOrderResult(Generic, order);
+            Generic.UnifiedOrderResult = ProcessResults;
+            return Generic;
         }
 
         public async Task<Dictionary<string, string>> PlaceUnifiedOrder(ElectronicOrderModel order)

+ 8 - 0
FuelCloud/src/Fuel.Payment.Service/Factory/AsyncPaymentProcessor.cs

@@ -34,5 +34,13 @@ namespace Fuel.Payment.Service.Factory
         /// <param name="electronicOrderModel"></param>
         /// <returns></returns>
         protected abstract Task<ElectronicOrderModel> PaymentResult(GenericProcessResponse order, ElectronicOrderModel electronicOrderModel);
+
+        /// <summary>
+        /// 统一下单结果
+        /// </summary>
+        /// <param name="order"></param>
+        /// <param name="electronicOrderModel"></param>
+        /// <returns></returns>
+        protected abstract Task<object> UnifiedOrderResult(GenericProcessResponse order, ElectronicOrderModel electronicOrderModel);
     }
 }

+ 1 - 0
FuelCloud/src/Fuel.Payment.Service/Pay/IPayService.cs

@@ -12,5 +12,6 @@ namespace Fuel.Payment.Service.Pay
     {
         Task<ServiceResponse> PerformElectronicProcess(string AuthCode, decimal payDueAmount, string Channel = "ALL_IN_SCAN", string preCreatedBillNumber = "");
         Task<ServiceResponse> ReturnProcess(decimal payDueAmount, string Channel = "ALL_IN_SCAN", string preCreatedBillNumber = "");
+        Task<ServiceResponse> UnifiedOrder(decimal payDueAmount, string Channel = "ALL_IN_SCAN", string userId = "001");
     }
 }

+ 43 - 3
FuelCloud/src/Fuel.Payment.Service/Pay/PayService.cs

@@ -2,6 +2,7 @@
 using Fuel.Payment.Core.Enum;
 using Fuel.Payment.Core.Models;
 using Fuel.Payment.Service.Factory;
+using FuelServer.Core.Entity;
 using Org.BouncyCastle.Asn1.X509;
 using System;
 using System.Collections.Generic;
@@ -15,7 +16,7 @@ using FuelOrderDetailModel = Fuel.Payment.Core.Models.FuelOrderDetailModel;
 
 namespace Fuel.Payment.Service.Pay
 {
-    public class PayService: IPayService
+    public class PayService : IPayService
     {
         /// <summary>
         /// 支付处理
@@ -27,7 +28,7 @@ namespace Fuel.Payment.Service.Pay
             string Channel = "ALL_IN_SCAN",
             string preCreatedBillNumber = "")
         {
-            if(string.IsNullOrEmpty(preCreatedBillNumber)) 
+            if (string.IsNullOrEmpty(preCreatedBillNumber))
             {
                 preCreatedBillNumber = SequenceNumber.Next();
             }
@@ -52,7 +53,7 @@ namespace Fuel.Payment.Service.Pay
             return new ServiceResponse { StatusCode = HttpStatusCode.OK, Data = genericResponseAlipay.ProcessResults.Last() };
         }
         /// <summary>
-        /// 支付处理
+        /// 退款处理
         /// </summary>
         /// <param name="AuthCode"></param>
         /// <returns></returns>
@@ -85,6 +86,45 @@ namespace Fuel.Payment.Service.Pay
             //var Result = await eProcessor.PaymentResult(genericResponseAlipay, eOrder).ConfigureAwait(false);
             return new ServiceResponse { StatusCode = HttpStatusCode.OK, Data = genericResponseAlipay.ProcessResults.Last() };
         }
+
+        /// <summary>
+        /// 统一下单
+        /// </summary>
+        /// <param name="AuthCode"></param>
+        /// <returns></returns>
+        public async Task<ServiceResponse> UnifiedOrder(
+            decimal payDueAmount,
+            string Channel = "ALL_IN_SCAN",
+            string userId = "001"
+            )
+        {
+            var optionalParam = new Dictionary<string, object>();
+            if (!string.IsNullOrEmpty(userId))
+            {
+                optionalParam.Add("mobilePayId", "o7yXJ5NCQDKeBTiRhGjZ0QW5X5qI");
+            }
+            ElectronicOrderModel eOrder = new ElectronicOrderModel
+            {
+                Channel = Channel,
+                IsRefund = false,
+                AuthCode = "",
+                BillNumber = SequenceNumber.Next(),
+                NetAmount = payDueAmount,
+                Title = "Wayne Payment",
+                FuelOrderDetails = new List<FuelOrderDetailModel>(),
+                OperatorId = "001",
+                SiteId = "66668888",
+                Config = "",
+                Optional = optionalParam,
+            };
+            var eProcessor = AsyncPaymentProcessorFactory.Default.Get(eOrder);
+            //var payConfig = await eProcessor.Initialize(eOrder).ConfigureAwait(false);
+            //eOrder.Config = payConfig.electronicOrderModel?.Config;
+            var genericResponseAlipay = await eProcessor.UnifiedOrder(eOrder).ConfigureAwait(false);
+            return new ServiceResponse { StatusCode = HttpStatusCode.OK, Data = genericResponseAlipay.UnifiedOrderResult };
+        }
+
+
         private string GetPaymentChannelByPaymentId(PaymentID paymentID)
         {
             var channel = String.Empty;

+ 4 - 0
FuelCloud/src/Fuel.Payment.Service/UnionPayProcessor/MiniUnionPayProcessor.cs

@@ -368,5 +368,9 @@ namespace Fuel.Payment.Service.UnionPayProcessor
             }
         }
 
+        protected override Task<object> UnifiedOrderResult(GenericProcessResponse order, ElectronicOrderModel electronicOrderModel)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 5 - 0
FuelCloud/src/Fuel.Payment.Service/UnionPayProcessor/UnionPayProcessor.cs

@@ -268,5 +268,10 @@ namespace Fuel.Payment.Service.UnionPayProcessor
                 AllInPayResponse = null
             };
         }
+
+        protected override Task<object> UnifiedOrderResult(GenericProcessResponse order, ElectronicOrderModel electronicOrderModel)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 8 - 1
FuelCloud/src/FuelServer.Core/Entity/businessunitinfo.cs

@@ -61,7 +61,14 @@ namespace FuelServer.Core.Entity
 		/// </summary>
 		[JsonProperty, Column(StringLength = 100)]
 		public string Secret { get; set; }
+        /// <summary>
+        /// 预支付:1,后支付:2
+        /// </summary>
+        [JsonProperty]
+        public int PaymentMode { get; set; }
 
-	}
+
+
+    }
 
 }

+ 17 - 13
FuelCloud/src/FuelServer.Core/Entity/transactions.cs

@@ -52,17 +52,17 @@ namespace FuelServer.Core.Entity
 		[JsonProperty]
 		public decimal? ActualPaymentAmount { get; set; }
 
-		/// <summary>
-		/// 授权时间
-		/// </summary>
-		[JsonProperty, Column(DbType = "timestamp", InsertValueSql = "0000-00-00 00:00:00")]
-		public DateTime? AuthorizationTime { get; set; }
+        /// <summary>
+        /// 授权时间
+        /// </summary>
+        [JsonProperty, Column(DbType = "timestamp", InsertValueSql = "CURRENT_TIMESTAMP")]
+        public DateTime? AuthorizationTime { get; set; }
 
 		[JsonProperty, Column(StringLength = 100)]
 		public string CreateBy { get; set; }
 
-		[JsonProperty, Column(DbType = "timestamp", InsertValueSql = "0000-00-00 00:00:00")]
-		public DateTime CreateTime { get; set; }
+        [JsonProperty, Column(DbType = "timestamp", InsertValueSql = "CURRENT_TIMESTAMP")]
+        public DateTime? CreateTime { get; set; }
 
 		/// <summary>
 		/// 挂枪时间
@@ -98,7 +98,7 @@ namespace FuelServer.Core.Entity
 		/// 支付方式
 		/// </summary>
 		[JsonProperty]
-		public long PaymentMethod { get; set; }
+		public long? PaymentMethod { get; set; }
 
 		/// <summary>
 		/// 油品名称
@@ -129,11 +129,11 @@ namespace FuelServer.Core.Entity
 		[JsonProperty, Column(StringLength = 50, IsNullable = false)]
 		public string TransactionNumber { get; set; }
 
-		/// <summary>
-		/// 交易时间
-		/// </summary>
-		[JsonProperty, Column(DbType = "timestamp", InsertValueSql = "0000-00-00 00:00:00")]
-		public DateTime TransactionTime { get; set; }
+        /// <summary>
+        /// 交易时间
+        /// </summary>
+        [JsonProperty, Column(DbType = "timestamp", InsertValueSql = "CURRENT_TIMESTAMP")]
+        public DateTime? TransactionTime { get; set; }
 
         /// <summary>
         /// 加密字符串,用于验证金额是否篡改
@@ -159,6 +159,10 @@ namespace FuelServer.Core.Entity
 		/// 是否授权
 		/// </summary>
 		public AuthorizationStatus authorizationStatus { get; set; }
+		/// <summary>
+		/// 单价
+		/// </summary>
+		public decimal? Price { get; set; }
     }
     public enum AuthorizationStatus
     {

+ 19 - 0
FuelCloud/src/FuelServer.Core/HttpRequestReader.cs

@@ -33,6 +33,25 @@ namespace Fuel.Core
             return Guid.Empty;
         }
         /// <summary>
+        /// 小程序用户id
+        /// </summary>
+        /// <returns></returns>
+        public static Guid GetWachatID()
+        {
+            if (_httpContextAccessor == null || _httpContextAccessor.HttpContext == null)
+            {
+                return Guid.Empty;
+            }
+            var httpContext = _httpContextAccessor.HttpContext;
+            var headerValue = httpContext.Request.Headers["WachatID"].ToString();
+
+            if (Guid.TryParse(headerValue, out Guid buId))
+            {
+                return buId;
+            }
+            return Guid.Empty;
+        }
+        /// <summary>
         /// 获取请求头值
         /// </summary>
         /// <param name="headerName"></param>

+ 14 - 15
FuelCloud/src/FuelServer.Core/Nozzle/Dto/UploadNozzle.cs

@@ -1,4 +1,5 @@
-using System;
+using Newtonsoft.Json;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -42,7 +43,7 @@ namespace Fuel.Core.Nozzle.Dto
         /// <summary>
         /// FCC油品id
         /// </summary>
-        public long ProductId { get; set; }
+        public long? ProductId { get; set; }
         public long TankID { get; set; }
     }
     public class UploadNozzle
@@ -61,25 +62,23 @@ namespace Fuel.Core.Nozzle.Dto
         public long ExternalGunNumber { get; set; }
         public long NozzleId { get; set; }
         /// <summary>
-        /// 油罐号
-        /// </summary>
-        public long TankNumber { get; set; }
-        /// <summary>
-        /// 油罐容量
+        /// 油品id
         /// </summary>
-        public decimal? TankCapacity { get; set; }
+        public long? ProductId { get; set; }
         /// <summary>
-        /// 油品名称
+        /// 油罐id
         /// </summary>
-        public string ProductName { get; set; }
+        public long? TankID { get; set; }
+    }
+    public class UploadNozzleStatus
+    {
         /// <summary>
-        /// 油品码
+        /// 油枪ID
         /// </summary>
-        public string ProductCode { get; set; }
+        public long NozzleId { get; set; }
         /// <summary>
-        /// 油品单价
+        /// 1:在线、2:离线、3:正在加
         /// </summary>
-        public decimal? ProductPrice { get; set; }
+        public long Status { get; set; }
     }
-
 }

+ 74 - 0
FuelCloud/src/FuelServer.Core/Sm4Encryptor.cs

@@ -0,0 +1,74 @@
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Fuel.Core
+{
+    public class Sm4Encryptor
+    {
+        // 加密方法
+        public static string Encrypt(string plainText, string hexKey)
+        {
+            byte[] keyBytes = HexStringToByteArray(hexKey);
+            if (keyBytes.Length != 16)
+            {
+                throw new ArgumentException("Key must be exactly 16 bytes in length.", nameof(hexKey));
+            }
+
+            byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
+
+            IBufferedCipher cipher = new PaddedBufferedBlockCipher(new SM4Engine(), new Pkcs7Padding());
+            KeyParameter keyParam = new KeyParameter(keyBytes);
+
+            cipher.Init(true, keyParam);
+            byte[] outputBytes = new byte[cipher.GetOutputSize(plainBytes.Length)];
+            int length = cipher.ProcessBytes(plainBytes, 0, plainBytes.Length, outputBytes, 0);
+            length += cipher.DoFinal(outputBytes, length); // Do the final block
+
+            // Convert to hex instead of base64
+            return ByteArrayToHexString(outputBytes);
+        }
+        private static string ByteArrayToHexString(byte[] bytes)
+        {
+            StringBuilder hexString = new StringBuilder(bytes.Length * 2);
+            foreach (byte b in bytes)
+            {
+                hexString.AppendFormat("{0:X2}", b);
+            }
+            return hexString.ToString();
+        }
+        private static byte[] HexStringToByteArray(string hex)
+        {
+            return Enumerable.Range(0, hex.Length)
+                             .Where(x => x % 2 == 0)
+                             .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
+                             .ToArray();
+        }
+        // 解密方法
+        public static string Decrypt(string cipherText, string key, string iv)
+        {
+            byte[] keyBytes = Encoding.UTF8.GetBytes(key);
+            byte[] ivBytes = Encoding.UTF8.GetBytes(iv);
+            byte[] cipherBytes = Convert.FromBase64String(cipherText);
+
+            IBufferedCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new SM4Engine()), new Pkcs7Padding());
+
+            KeyParameter keyParam = new KeyParameter(keyBytes);
+            ParametersWithIV parametersWithIV = new ParametersWithIV(keyParam, ivBytes);
+
+            cipher.Init(false, parametersWithIV);
+            byte[] outputBytes = new byte[cipher.GetOutputSize(cipherBytes.Length)];
+            int length = cipher.ProcessBytes(cipherBytes, 0, cipherBytes.Length, outputBytes, 0);
+            cipher.DoFinal(outputBytes, length); // Do the final block
+
+            return Encoding.UTF8.GetString(outputBytes, 0, length);
+        }
+    }
+}

+ 4 - 0
FuelCloud/src/FuelServer.Core/Transactions/Dto/TransactionsInput.cs

@@ -37,6 +37,10 @@ namespace Fuel.Core.Transactions.Dto
         /// 支付类型
         /// </summary>
         public string paytype { get; set; }
+        /// <summary>
+        /// 枪号
+        /// </summary>
+        public int? NozzleId { get; set; }
 
         public static transactionsORDERSTATUS ToTransactionsORDERSTATUS(int value)
         {

+ 13 - 11
FuelCloud/src/FuelServer.Core/Transactions/Dto/UploadTransactions.cs

@@ -13,7 +13,7 @@ namespace Fuel.Core.Transactions.Dto
         /// <summary>
         /// 油枪
         /// </summary>
-        public int NozzleId { get; set; }
+        public int?  ExternalGunNumber { get; set; }
         /// <summary>
         /// 实际加油金额
         /// </summary>
@@ -41,37 +41,39 @@ namespace Fuel.Core.Transactions.Dto
         /// <summary>
         /// 用户id
         /// </summary>
-        public int MiniProgramID { get; set; }
+        public int? MiniProgramID { get; set; }
         /// <summary>
         /// 订单流水号
         /// </summary>
         public string TransactionNumber { get; set; }
         /// <summary>
-        /// 1预支付、2后支付 
+        /// 支付方式
         /// </summary>
-        public int Type { get; set; }
+        public int? PaymentMethod { get; set; }
         /// <summary>
-        /// 支付方式
+        /// 单价
         /// </summary>
-        public int PaymentMethod { get; set; }
+        public decimal? Price { get; set; }
 
-        public transactions ToTransactions(UploadTransactions upload, Guid Buid, product product, nozzle nozzle)
+        public transactions ToTransactions(UploadTransactions upload, Guid Buid, product product, nozzle nozzle,int _OrderType)
         {
             return new transactions()
             {
                 Buid = Buid,
-                NozzleId = upload.NozzleId,
+                NozzleId = nozzle.NozzleId,
                 ProductId = product.Id,
                 ActualPaymentAmount = upload.ActualPaymentAmount,
                 FuelItemTransactionEndTime = upload.FuelItemTransactionEndTime,
                 OrderStatus = transactionsORDERSTATUS.Unpaid,
-                OrderType = ToTransactionsOrderType(upload.Type),
-                OriginalAmount = upload.ActualPaymentAmount,
+               OrderType = ToTransactionsOrderType(_OrderType),
+                OriginalAmount = upload.OriginalAmount,
                 PaymentMethod = upload.PaymentMethod,
                 ProductName = product.ProductName,
                 Qty = upload.Qty,
                 TransactionNumber = upload.TransactionNumber,
-                TransactionTime = DateTime.Now
+                TransactionTime = DateTime.Now,
+                Price = upload.Price,
+                CreateTime = DateTime.Now,
             };
         }
         public static transactionsORDERTYPE ToTransactionsOrderType(int value)

+ 14 - 0
FuelCloud/src/FuelServer.Core/WechatServer/WechatConstants.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Fuel.Core.WechatServer
+{
+    public class WechatConstants
+    {
+        public const string Jscode2sessionUrl =
+           "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
+    }
+}

+ 90 - 0
FuelCloud/src/FuelServer.Core/WechatServer/WechatUserSessionRepo.cs

@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Fuel.Core.WechatServer
+{
+    public class WechatUserSessionWrapper
+    {
+        public WechatUserSessionResponse UserSession { get; set; }
+        public DateTime InitTime { get; set; }
+    }
+
+    public static class WechatUserSessionRepo
+    {
+        private static Dictionary<string, WechatUserSessionWrapper> _userSessions =
+            new Dictionary<string, WechatUserSessionWrapper>();
+        private static readonly object _lockObj = new object();
+
+        private static TimeSpan SessionMaxTime = new TimeSpan(3, 0, 0, 0); // 3 days
+
+        public static void AddUserSession(string thirdSessionKey, WechatUserSessionResponse userSession)
+        {
+            CleanupUserSessions();
+
+            var userSessionWrapper = new WechatUserSessionWrapper { UserSession = userSession, InitTime = DateTime.Now };
+            lock (_lockObj)
+            {
+                if (_userSessions.ContainsKey(thirdSessionKey))
+                {
+                    _userSessions.Remove(thirdSessionKey);
+                }
+                _userSessions.Add(thirdSessionKey, userSessionWrapper);
+            }
+        }
+
+        public static WechatUserSessionResponse GetUserSession(string thirdSessionKey)
+        {
+            CleanupUserSessions();
+
+            lock (_lockObj)
+            {
+                try
+                {
+                    var userSessionWrapper = _userSessions[thirdSessionKey];
+                    return userSessionWrapper.UserSession;
+                }
+                catch (Exception)
+                {
+                    return null;
+                }
+            }
+        }
+
+        public static bool RemoveUserSession(string unionId)
+        {
+            CleanupUserSessions();
+
+            lock (_lockObj)
+            {
+                try
+                {
+                    foreach (var item in _userSessions.Where(p =>
+                        String.Compare(p.Value.UserSession.unionid, unionId, StringComparison.Ordinal) == 0).ToList())
+                    {
+                        _userSessions.Remove(item.Key);
+                        return true;
+                    }
+                    return false;
+                }
+                catch (Exception)
+                {
+                    return false;
+                }
+            }
+        }
+
+        private static void CleanupUserSessions()
+        {
+            lock (_lockObj)
+            {
+                foreach (var item in _userSessions.Where(p => DateTime.Now - p.Value.InitTime > SessionMaxTime).ToList())
+                {
+                    _userSessions.Remove(item.Key);
+                }
+            }
+        }
+    }
+}

+ 16 - 0
FuelCloud/src/FuelServer.Core/WechatServer/WechatUserSessionResponse.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Fuel.Core.WechatServer
+{
+    public class WechatUserSessionResponse
+    {
+        public string openid { get; set; }
+        public string session_key { get; set; }
+        public string unionid { get; set; }
+        public string buId { get; set; }
+    }
+}