using Fake.Application; using Fake.Domain.Exceptions; using Fake.UnitOfWork; using Microsoft.AspNetCore.Mvc; using Oms.Application.Dtos.Orders; using Oms.Application.Integrations.Itfx; using Oms.Application.Shared; namespace Oms.Application.Services.Orders; public partial class OrderService { private OrderDownstreamCredentialResolver OrderDownstreamCredentialResolver => LazyServiceProvider.GetRequiredService(); private IItfxForwardClient ItfxForwardClient => LazyServiceProvider.GetRequiredService(); /// /// 按订单 Id 从数据库组装 createOrderOne 请求体(预览,不调用下游)。 /// [HttpGet("/order/downstream-create-one-body")] public async Task GetDownstreamCreateOneBodyAsync([FromQuery] int id) { var (order, body) = await LoadDownstreamCreateOneContextAsync(id); var creds = await OrderDownstreamCredentialResolver.ResolveAsync(order); return new OrderDownstreamCreateOneBodyOutput { OrderId = order.Id, ServiceNo = order.ServiceNo, SupplierCode = creds.SupplierCode, Body = body }; } /// /// 按订单 Id 组装 createOrderOne 并转发至 itfx 下游。 /// [HttpPost("/order/downstream-forward-create-one")] [UnitOfWork(IsTransactional = true)] public async Task DownstreamForwardCreateOneAsync([FromBody] OrderActionInput input) { var (order, body) = await LoadDownstreamCreateOneContextAsync(input.Id); if (string.IsNullOrWhiteSpace(order.ServiceNo)) { throw new BusinessException("订单运单号为空,无法预报下游"); } var creds = await OrderDownstreamCredentialResolver.ResolveAsync(order); var forward = await ItfxForwardClient.ForwardCreateOrderOneAsync( creds.SupplierCode, creds.AppKey, creds.AppSecret, body); if (forward.Success && ItfxCreateOrderOneDataParser.TryParse(forward.ResponseBody, out var data) && data != null) { var previousTrackNo = order.TrackNo; if (ItfxCreateOrderOneDataParser.ApplyToOrder(order, data)) { await OrderRepository.UpdateAsync(order); await EnqueueSmallBagTrackUpsertWhenTrackNoChangedAsync(order, previousTrackNo); } if (!string.IsNullOrWhiteSpace(data.LabelUrl)) { await OrderFileManager.AddOrReplaceDownstreamLabelAsync( order.Id, data.LabelUrl!, CurrentUser.IsAuthenticated ? CurrentUser.GetId() : 0); } } return new OrderDownstreamForwardResult { Success = forward.Success, SupplierCode = creds.SupplierCode, Url = forward.Url, RequestJson = forward.RequestJson, StatusCode = forward.StatusCode, ResponseBody = forward.ResponseBody, DownstreamServiceNo = order.DownstreamServiceNo, TrackNo = order.TrackNo, }; } /// /// 按订单 Id 组装 getFile 并转发至 itfx 下游;成功时转存文件并回写单号。 /// [HttpPost("/order/downstream-forward-get-file")] public async Task DownstreamForwardGetFileAsync( [FromBody] OrderDownstreamGetFileInput input) { if (!ItfxGetFileDataParser.TryResolveFileType(input.Type, out var fileType)) { throw new BusinessException("不支持的文件类型,请选择下游面单/末端面单/POD"); } var order = await GetOrderOrThrowAsync(input.Id); var creds = await OrderDownstreamCredentialResolver.ResolveAsync(order); var body = new ItfxGetFileBody { ClientNo = order.ClientNo?.Trim() ?? string.Empty, TrackNo = order.TrackNo?.Trim() ?? string.Empty, ServiceNo = order.DownstreamServiceNo?.Trim() ?? string.Empty, Type = input.Type }; var forward = await ItfxForwardClient.ForwardWithSubscribeAsync( ItfxGetFileDataParser.StandardCode, creds.SupplierCode, creds.AppKey, creds.AppSecret, body); string? storedFileUrl = null; if (forward.Success && ItfxGetFileDataParser.TryParse(forward.ResponseBody, out var data) && data != null) { var previousTrackNo = order.TrackNo; if (ItfxGetFileDataParser.ApplyToOrder(order, data)) { await OrderRepository.UpdateAsync(order); await EnqueueSmallBagTrackUpsertWhenTrackNoChangedAsync(order, previousTrackNo); } if (!string.IsNullOrWhiteSpace(data.Url)) { var saved = await OrderFileManager.AddOrReplaceFromRemoteUrlAsync( order.Id, fileType, data.Url!, CurrentUser.IsAuthenticated ? CurrentUser.GetId() : 0); storedFileUrl = saved.FileUrl; } } return new OrderDownstreamGetFileResult { Success = forward.Success, SupplierCode = creds.SupplierCode, Type = input.Type, FileType = fileType, Url = forward.Url, RequestJson = forward.RequestJson, StatusCode = forward.StatusCode, ResponseBody = forward.ResponseBody, StoredFileUrl = storedFileUrl, DownstreamServiceNo = order.DownstreamServiceNo, TrackNo = order.TrackNo, }; } private async Task<(Domain.OrdersAggregate.Entities.Order order, ItfxCreateOrderOneBody body)> LoadDownstreamCreateOneContextAsync( int orderId) { var bundles = await OrderRepository.GetDownstreamCreateOneBundlesAsync([orderId]); if (!bundles.TryGetValue(orderId, out var bundle)) { throw new BusinessException("订单不存在"); } var body = await OrderDownstreamCreateOneBodyBuilder.BuildAsync( bundle.Order, bundle.Sender, bundle.Recipient, bundle.Declarations, bundle.Weights, CountryRepository, ServiceChannelRepository, FileStorage); return (bundle.Order, body); } }