using Furion; using Furion.EventBus; using Furion.FriendlyException; using Furion.JsonSerialization; using Furion.RemoteRequest.Extensions; using Google.Protobuf.WellKnownTypes; using Mapster; using Microsoft.AspNetCore.JsonPatch.Internal; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Myshipping.Application.ConfigOption; using Myshipping.Application.Entity; using Myshipping.Application.Service.BookingOrder.Dto; using Myshipping.Core; using Myshipping.Core.Entity; using Myshipping.Core.Helper; using Myshipping.Core.Service; using Newtonsoft.Json.Linq; using NPOI.SS.Formula.Functions; using NPOI.SS.Formula.PTG; using StackExchange.Profiling.Internal; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Security.Policy; using System.Text; using System.Threading.Tasks; using Yitter.IdGenerator; namespace Myshipping.Application.Event { /// /// 扣费 /// public class BookingFeeSubscriber : IEventSubscriber { private IServiceProvider _services { get; } private readonly ILogger _logger; public BookingFeeSubscriber(IServiceProvider services , ILogger logger) { _services = services; _logger = logger; } //扣费 [EventSubscribe("Booking:DoFeeRecord")] public async Task DoFeeRecord(EventHandlerExecutingContext context) { _logger.LogInformation($"收到订舱扣费请求:{context.Source.Payload}"); var batchId = DateTime.Now.Ticks.ToString(); var paraObj = context.Source.Payload as dynamic; int bsType = paraObj.bsType; int sendType = paraObj.sendtype; List idList = paraObj.idList; idList = idList.Distinct().ToList(); _logger.LogInformation($"{batchId}-准备处理扣费,bsType:{bsType},sendType:{sendType},id列表:{string.Join(',', idList)}"); using var scope = _services.CreateScope(); var repoUser = scope.ServiceProvider.GetRequiredService>(); var repoBooking = scope.ServiceProvider.GetRequiredService>(); var repoFeeRecord = scope.ServiceProvider.GetRequiredService>(); var repoTenantParamValue = scope.ServiceProvider.GetRequiredService>(); var cache = scope.ServiceProvider.GetRequiredService(); var feeOrderList = await repoBooking .AsQueryable() .Filter(null, true) .Where(x => idList.Contains(x.Id)) .Select(x => new { x.Id, x.MBLNO, x.HBLNO, x.OPID, x.CreatedUserId, x.TenantId, x.VESSEL, x.VOYNO, x.ETD, x.CARRIER, x.ATD }) .ToListAsync(); var typeStr = $"{bsType}_{sendType}"; var sysCfg = await cache.GetAllSysConfig(); var feeUrl = sysCfg.FirstOrDefault(x => x.Code == "djyFeeApiUrl"); if (feeUrl == null || string.IsNullOrEmpty(feeUrl.Value)) { var errMsg = "大简云扣费URL未配置"; _logger.LogError(errMsg); DingTalkGroupHelper.SendDingTalkGroupMessage("bookingFeeNotify", "扣费失败提醒", errMsg); return; } foreach (var order in feeOrderList) { var iptId = string.IsNullOrEmpty(order.OPID) ? order.CreatedUserId.Value : Convert.ToInt64(order.OPID); var user = await repoUser.AsQueryable().Filter(null, true).FirstAsync(x => x.Id == iptId); var keyList = await repoTenantParamValue.AsQueryable() .Filter(null, true) .Where(x => x.TenantId == order.TenantId && (x.ParaCode == "BOOKING_FEE_USERID" || x.ParaCode == "BOOKING_FEE_USERKEY")) .ToListAsync(); if (keyList.Count < 2) { var errMsg = $"未找到{order.MBLNO}({order.Id})所在租户的授权userid和key,无法调用扣费"; _logger.LogError(errMsg); DingTalkGroupHelper.SendDingTalkGroupMessage("bookingFeeNotify", "扣费失败提醒", errMsg); continue; } var feeUserId = keyList.First(x => x.ParaCode == "BOOKING_FEE_USERID").ItemCode; var feeUserKey = keyList.First(x => x.ParaCode == "BOOKING_FEE_USERKEY").ItemCode; if (user == null || string.IsNullOrEmpty(user.DjyUserId)) { var errMsg = $"未找到{order.MBLNO}({order.Id})的用户信息,无法调用扣费"; _logger.LogError(errMsg); DingTalkGroupHelper.SendDingTalkGroupMessage("bookingFeeNotify", "扣费失败提醒", errMsg); continue; } var c = repoFeeRecord.AsQueryable().Filter(null, true).Count(x => x.TenantId == order.TenantId && x.MBLNO == order.MBLNO); if (c > 0) { _logger.LogInformation($"{batchId}-已存在扣费记录,id:{order.Id},提单号:{order.MBLNO},租户:{order.TenantId}"); continue; } var seconds = DateTime.Now.ToTimeStamp(); var runId = Guid.NewGuid().ToString(); var srcBeforMD5 = $"{runId}{feeUserId}expend{bsType}{sendType}{order.Id}{order.MBLNO}{seconds}{feeUserKey}"; var postObj = new { runId, userId = feeUserId, module = "expend",//固定 bsType = $"{bsType}", sendType = $"{sendType}", timestamp = seconds,//秒级时间戳 md5 = srcBeforMD5.ToMd5(),// 加密字符串小写 RunId + UserId + Module + BsType + SendType+Timestamp+ Key Data = new { BSNO = order.Id.ToString(), MBLNO = order.MBLNO, HBLNO = order.HBLNO, CtnrInfo = "", CtnrCount = 1, IsCredit = 1,//是否是信用支付 1 信用支付 0不允许信用支付默认值为0, LURURENID = user.DjyUserId, SENDUSERID = user.DjyUserId, VESSEL = order.VESSEL, VOYNO = order.VOYNO, ETD = order.ATD, CARRIER = order.CARRIER } }; _logger.LogInformation($"{batchId}-调用扣费:{postObj.ToJsonString()}"); var apiRtn = await feeUrl.Value .SetHttpMethod(HttpMethod.Post) .SetBody(postObj) .SetRetryPolicy(3, 5000) .OnException((c, m, errMsg) => { _logger.LogError($"扣费失败:{errMsg}"); DingTalkGroupHelper.SendDingTalkGroupMessage("bookingFeeNotify", "扣费失败提醒", errMsg); }) .SendAsStringAsync(); _logger.LogInformation($"{batchId}-调用扣费返回:{apiRtn}"); var jobjApiRtn = JObject.Parse(apiRtn); var code = jobjApiRtn.GetIntValue("code"); var jobjApiRtnData = jobjApiRtn.GetValue("data") as JObject; if (code == 200 || code == 450) { var jobjApiRtnDataPayInfo = jobjApiRtnData.GetValue("payInfo") as JObject; var price = Convert.ToDecimal(jobjApiRtnDataPayInfo.GetValue("price").ToString()); var total = Convert.ToDecimal(jobjApiRtnDataPayInfo.GetValue("total").ToString()); //记录扣费 var fr = new BookingFeeRecord(); fr.Id = YitIdHelper.NextId(); fr.BillId = order.Id; fr.MBLNO = order.MBLNO; fr.TenantId = order.TenantId.Value; fr.Type = typeStr; fr.Amount = total; await repoFeeRecord.InsertAsync(fr); } else { var errMsg = jobjApiRtn.GetValue("message").ToString(); _logger.LogError($"{batchId}-扣费失败:{errMsg}"); DingTalkGroupHelper.SendDingTalkGroupMessage("bookingFeeNotify", "扣费失败提醒", errMsg); } } _logger.LogInformation($"{batchId}-扣费处理完成"); } } }