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 paraObj = context.Source.Payload as dynamic;
int bsType = paraObj.bsType;
int sendType = paraObj.sendtype;
List idList = paraObj.idList;
idList = idList.Distinct().ToList();
_logger.LogInformation($"准备处理扣费,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.OPID, x.CreatedUserId, x.TenantId })
.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($"已存在扣费记录,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,
CtnrInfo = "",
CtnrCount = 1,
IsCredit = 1,//是否是信用支付 1 信用支付 0不允许信用支付默认值为0,
LURURENID = user.DjyUserId,
SENDUSERID = user.DjyUserId
}
};
_logger.LogInformation($"调用扣费:{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($"调用扣费返回:{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($"扣费失败:{errMsg}");
DingTalkGroupHelper.SendDingTalkGroupMessage("bookingFeeNotify", "扣费失败提醒", errMsg);
}
}
_logger.LogInformation($"扣费处理完成");
}
}
}