using Castle.Core.Logging; using Dapper; using LifePayment.Application.Contracts; using LifePayment.Application.Contracts.Sync; using LifePayment.Domain.LifePay; using LifePayment.Domain.Models; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Nest; using NPOI.SS.Formula.Functions; using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Threading.Tasks; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; using ZeroD.Util; using ZeroD.Util.Fadd; namespace LifePayment.Application.Sync { public class SyncService : ApplicationService, ISyncService { private readonly ILogger logger; private readonly IConfiguration configuration; public SyncService( ILogger logger, IConfiguration configuration) { this.logger = logger; this.configuration = configuration; } private async Task> GetListDataAsync(string connName, string tableName) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { var data = await conn.QueryAsync(@$" SELECT * FROM [{tableName}] "); return data.ToList(); } } private async Task InsertLifePayChannles(string connName, SyncLifePayChannles item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" INSERT INTO LifePayChannles ( Id, ChannlesName, ChannlesNum, ChannlesRate, ChannlesRakeRate, ChannlesType, SwitchType, Status, CreationTime, CreatorId, LastModificationTime, LastModifierId, IsDeleted, DeleterId, DeletionTime ) VALUES ( @Id, @ChannlesName, @ChannlesNum, @ChannlesRate, @ChannlesRakeRate, @ChannlesType, @SwitchType, @Status, @CreationTime, @CreatorId, @LastModificationTime, @LastModifierId, @IsDeleted, @DeleterId, @DeletionTime ) ", item); } } private async Task InsertLifePayUser(string connName, SyncLifePayUser item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" INSERT INTO LifePayUser ( Id, PhoneNumber, OpenId, LastLoginTime, CreationTime, CreatorId, LastModificationTime, LastModifierId, IsDeleted, DeleterId, DeletionTime, UnionId, CreationChannleNum, LastLoginChannleNum, Name ) VALUES ( @Id, @PhoneNumber, @OpenId, @LastLoginTime, @CreationTime, @CreatorId, @LastModificationTime, @LastModifierId, @IsDeleted, @DeleterId, @DeletionTime, @UnionId, @CreationChannleNum, @LastLoginChannleNum, @Name ) ", item); } } private async Task InsertLifePayOrder(string connName, SyncLifePayOrder item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" INSERT INTO LifePayOrder ( Id, UserId, CreationTime, CreatorId, LastModificationTime, LastModifierId, IsDeleted, DeleterId, DeletionTime, ExtraProperties, ConcurrencyStamp, PhoneNumber, LifePayType, LifePayOrderType, OrderNo, RechargeAmount, DiscountAmount, PayAmount, PayTime, PayStatus, OutOrderNo, LifePayOrderStatus, FinishTime, RefundCredentialsImgUrl, OrderParamDetailJsonStr, OutRequestNo, ACOOLYOrderNo, RefundApplyRemark, RefundCheckRemark, RefundTime, RefundCheckUserId, ChannelId, RefundApplyTime, PlatformDeductionAmount, ACOOLYStatus, ActualRechargeAmount, LifePayRefundStatus, RefundPrice, RefundOrderNo, ElecBillUrl, RefundElecBillUrl, ActualReceivedAmount, PlatformRate, ChannleRate, ChannlesRakeRate, PremiumRate ) VALUES ( @Id, @UserId, @CreationTime, @CreatorId, @LastModificationTime, @LastModifierId, @IsDeleted, @DeleterId, @DeletionTime, @ExtraProperties, @ConcurrencyStamp, @PhoneNumber, @LifePayType, @LifePayOrderType, @OrderNo, @RechargeAmount, @DiscountAmount, @PayAmount, @PayTime, @PayStatus, @OutOrderNo, @LifePayOrderStatus, @FinishTime, @RefundCredentialsImgUrl, @OrderParamDetailJsonStr, @OutRequestNo, @ACOOLYOrderNo, @RefundApplyRemark, @RefundCheckRemark, @RefundTime, @RefundCheckUserId, @ChannelId, @RefundApplyTime, @PlatformDeductionAmount, @ACOOLYStatus, @ActualRechargeAmount, @LifePayRefundStatus, @RefundPrice, @RefundOrderNo, @ElecBillUrl, @RefundElecBillUrl, @ActualReceivedAmount, @PlatformRate, @ChannleRate, @ChannlesRakeRate, @PremiumRate ) ", item); } } private async Task InsertLifePayChannlesRake(string connName, SyncLifePayChannlesRake item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" INSERT INTO LifePayChannlesRake ( Id, UserId, CreationTime, CreatorId, LastModificationTime, LastModifierId, IsDeleted, DeleterId, DeletionTime, ExtraProperties, FinishTime, OrderNo, PayAmount, ChannlesRakeRate, ChannlesRakePrice, ChannelId ) VALUES ( @Id, @UserId, @CreationTime, @CreatorId, @LastModificationTime, @LastModifierId, @IsDeleted, @DeleterId, @DeletionTime, @ExtraProperties, @FinishTime, @OrderNo, @PayAmount, @ChannlesRakeRate, @ChannlesRakePrice, @ChannelId ) ", item); } } private async Task InsertLifePayConsumption(string connName, SyncLifePayConsumption item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" INSERT INTO LifePayConsumption ( Id, UserId, CreationTime, CreatorId, LastModificationTime, LastModifierId, IsDeleted, DeleterId, DeletionTime, ExtraProperties, OrderNo, AcoolyOrderNo, Amount, ACOOLYStatus, FrozenStatus, Flow, DeductionAmount, FinishTime, ChannelId, FrozenAmount ) VALUES ( @Id, @UserId, @CreationTime, @CreatorId, @LastModificationTime, @LastModifierId, @IsDeleted, @DeleterId, @DeletionTime, @ExtraProperties, @OrderNo, @AcoolyOrderNo, @Amount, @ACOOLYStatus, @FrozenStatus, @Flow, @DeductionAmount, @FinishTime, @ChannelId, @FrozenAmount ) ", item); } } private async Task InsertLifePayExpensesReceipts(string connName, SyncLifePayExpensesReceipts item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" INSERT INTO LifePayExpensesReceipts ( Id, UserId, CreationTime, CreatorId, LastModificationTime, LastModifierId, IsDeleted, DeleterId, DeletionTime, ExtraProperties, OrderNo, OutOrderNo, LifePayType, Amount, ExpensesReceiptsType, FinishTime ) VALUES ( @Id, @UserId, @CreationTime, @CreatorId, @LastModificationTime, @LastModifierId, @IsDeleted, @DeleterId, @DeletionTime, @ExtraProperties, @OrderNo, @OutOrderNo, @LifePayType, @Amount, @ExpensesReceiptsType, @FinishTime ) ", item); } } private async Task UpdateLifePayChannles(string connName, SyncLifePayChannles item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" UPDATE LifePayChannles SET ChannlesName = @ChannlesName, ChannlesNum = @ChannlesNum, ChannlesRate = @ChannlesRate, ChannlesRakeRate = @ChannlesRakeRate, ChannlesType = @ChannlesType, SwitchType = @SwitchType, Status = @Status, CreationTime = @CreationTime, CreatorId = @CreatorId, LastModificationTime = @LastModificationTime, LastModifierId = @LastModifierId, IsDeleted = @IsDeleted, DeleterId = @DeleterId, DeletionTime = @DeletionTime WHERE Id = @Id ", item); } } private async Task UpdateLifePayUser(string connName, SyncLifePayUser item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" UPDATE LifePayUser SET PhoneNumber = @PhoneNumber, OpenId = @OpenId, LastLoginTime = @LastLoginTime, CreationTime = @CreationTime, CreatorId = @CreatorId, LastModificationTime = @LastModificationTime, LastModifierId = @LastModifierId, IsDeleted = @IsDeleted, DeleterId = @DeleterId, DeletionTime = @DeletionTime, UnionId = @UnionId, CreationChannleNum = @CreationChannleNum, LastLoginChannleNum = @LastLoginChannleNum, Name = @Name WHERE Id = @Id ", item); } } private async Task UpdateLifePayOrder(string connName, SyncLifePayOrder item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" UPDATE LifePayOrder SET UserId = @UserId, CreationTime = @CreationTime, CreatorId = @CreatorId, LastModificationTime = @LastModificationTime, LastModifierId = @LastModifierId, IsDeleted = @IsDeleted, DeleterId = @DeleterId, DeletionTime = @DeletionTime, ExtraProperties = @ExtraProperties, ConcurrencyStamp = @ConcurrencyStamp, PhoneNumber = @PhoneNumber, LifePayType = @LifePayType, LifePayOrderType = @LifePayOrderType, OrderNo = @OrderNo, RechargeAmount = @RechargeAmount, DiscountAmount = @DiscountAmount, PayAmount = @PayAmount, PayTime = @PayTime, PayStatus = @PayStatus, OutOrderNo = @OutOrderNo, LifePayOrderStatus = @LifePayOrderStatus, FinishTime = @FinishTime, RefundCredentialsImgUrl = @RefundCredentialsImgUrl, OrderParamDetailJsonStr = @OrderParamDetailJsonStr, OutRequestNo = @OutRequestNo, ACOOLYOrderNo = @ACOOLYOrderNo, RefundApplyRemark = @RefundApplyRemark, RefundCheckRemark = @RefundCheckRemark, RefundTime = @RefundTime, RefundCheckUserId = @RefundCheckUserId, ChannelId = @ChannelId, RefundApplyTime = @RefundApplyTime, PlatformDeductionAmount = @PlatformDeductionAmount, ACOOLYStatus = @ACOOLYStatus, ActualRechargeAmount = @ActualRechargeAmount, LifePayRefundStatus = @LifePayRefundStatus, RefundPrice = @RefundPrice, RefundOrderNo = @RefundOrderNo, ElecBillUrl = @ElecBillUrl, RefundElecBillUrl = @RefundElecBillUrl, ActualReceivedAmount = @ActualReceivedAmount, PlatformRate = @PlatformRate, ChannleRate = @ChannleRate, ChannlesRakeRate = @ChannlesRakeRate, PremiumRate = @PremiumRate WHERE Id = @Id ", item); } } private async Task UpdateLifePayChannlesRake(string connName, SyncLifePayChannlesRake item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" UPDATE LifePayChannlesRake SET UserId = @UserId, CreationTime = @CreationTime, CreatorId = @CreatorId, LastModificationTime = @LastModificationTime, LastModifierId = @LastModifierId, IsDeleted = @IsDeleted, DeleterId = @DeleterId, DeletionTime = @DeletionTime, ExtraProperties = @ExtraProperties, FinishTime = @FinishTime, OrderNo = @OrderNo, PayAmount = @PayAmount, ChannlesRakeRate = @ChannlesRakeRate, ChannlesRakePrice = @ChannlesRakePrice, ChannelId = @ChannelId WHERE Id = @Id ", item); } } private async Task UpdateLifePayConsumption(string connName, SyncLifePayConsumption item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" UPDATE LifePayConsumption SET UserId = @UserId, CreationTime = @CreationTime, CreatorId = @CreatorId, LastModificationTime = @LastModificationTime, LastModifierId = @LastModifierId, IsDeleted = @IsDeleted, DeleterId = @DeleterId, DeletionTime = @DeletionTime, ExtraProperties = @ExtraProperties, OrderNo = @OrderNo, AcoolyOrderNo = @AcoolyOrderNo, Amount = @Amount, ACOOLYStatus = @ACOOLYStatus, FrozenStatus = @FrozenStatus, Flow = @Flow, DeductionAmount = @DeductionAmount, FinishTime = @FinishTime, ChannelId = @ChannelId, FrozenAmount = @FrozenAmount WHERE Id = @Id ", item); } } private async Task UpdateLifePayExpensesReceipts(string connName, SyncLifePayExpensesReceipts item) { var connString = configuration.GetConnectionString(connName); using (var conn = new SqlConnection(connString)) { return await conn.ExecuteAsync(@" UPDATE LifePayExpensesReceipts SET UserId = @UserId, CreationTime = @CreationTime, CreatorId = @CreatorId, LastModificationTime = @LastModificationTime, LastModifierId = @LastModifierId, IsDeleted = @IsDeleted, DeleterId = @DeleterId, DeletionTime = @DeletionTime, ExtraProperties = @ExtraProperties, OrderNo = @OrderNo, OutOrderNo = @OutOrderNo, LifePayType = @LifePayType, Amount = @Amount, ExpensesReceiptsType = @ExpensesReceiptsType, FinishTime = @FinishTime WHERE Id = @Id ", item); } } /// /// 同步测试订单数据 /// /// public async Task> SyncFromTest() { var messages = new List(); var sourceConnName = "SyncLifePaymentServices"; var targetConnName = "LifePaymentServices"; var sourceLifePayChannlesList = await GetListDataAsync(sourceConnName, "LifePayChannles"); var sourceLifePayUserList = await GetListDataAsync(sourceConnName, "LifePayUser"); var sourceLifePayOrderList = await GetListDataAsync(sourceConnName, "LifePayOrder"); var sourceLifePayChannlesRakeList = await GetListDataAsync(sourceConnName, "LifePayChannlesRake"); var sourceLifePayConsumptionList = await GetListDataAsync(sourceConnName, "LifePayConsumption"); var sourceLifePayExpensesReceiptsList = await GetListDataAsync(sourceConnName, "LifePayExpensesReceipts"); var targetLifePayChannlesList = await GetListDataAsync(targetConnName, "LifePayChannles"); var targetLifePayUserList = await GetListDataAsync(targetConnName, "LifePayUser"); var targetLifePayOrderList = await GetListDataAsync(targetConnName, "LifePayOrder"); var targetLifePayChannlesRakeList = await GetListDataAsync(targetConnName, "LifePayChannlesRake"); var targetLifePayConsumptionList = await GetListDataAsync(targetConnName, "LifePayConsumption"); var targetLifePayExpensesReceiptsList = await GetListDataAsync(targetConnName, "LifePayExpensesReceipts"); var dicUserIds = new Dictionary(); var dicChannleIds = new Dictionary(); var count = 0; logger.LogInformation($"准备同步{sourceLifePayUserList.Count}个用户数据"); foreach (var sourceLifePayUser in sourceLifePayUserList) { count++; logger.LogInformation($"正在同步第{count}个用户:{sourceLifePayUser.PhoneNumber}--------------------------------------------------------------------"); try { var targetLifePayUser = targetLifePayUserList.FirstOrDefault(it => it.PhoneNumber == sourceLifePayUser.PhoneNumber); if (targetLifePayUser == null) { logger.LogInformation("未匹配相同手机号"); targetLifePayUser = targetLifePayUserList.FirstOrDefault(it => it.Id == sourceLifePayUser.Id); } if (targetLifePayUser == null) { targetLifePayUser = new SyncLifePayUser(); ObjectMapper.Map(sourceLifePayUser, targetLifePayUser); await InsertLifePayUser(targetConnName, targetLifePayUser); dicUserIds.Add(sourceLifePayUser.Id, targetLifePayUser.Id); logger.LogInformation("未匹配相同Id,已插入用户"); } else { var updateTargetLifePayUser = new SyncLifePayUser(); ObjectMapper.Map(sourceLifePayUser, updateTargetLifePayUser); updateTargetLifePayUser.Id = targetLifePayUser.Id; await UpdateLifePayUser(targetConnName, updateTargetLifePayUser); targetLifePayUser = updateTargetLifePayUser; dicUserIds.Add(sourceLifePayUser.Id, targetLifePayUser.Id); logger.LogInformation("已更新用户"); } } catch (Exception ex) { messages.Add($"未能同步用户({sourceLifePayUser.PhoneNumber})发生服务器异常:{ex.Message}"); continue; } } foreach (var sourceLifePayChannles in sourceLifePayChannlesList) { try { var targetLifePayChannles = targetLifePayChannlesList.FirstOrDefault(it => it.ChannlesNum == sourceLifePayChannles.ChannlesNum); if (targetLifePayChannles == null) { logger.LogInformation("未匹配相同编号"); targetLifePayChannles = targetLifePayChannlesList.FirstOrDefault(it => it.Id == sourceLifePayChannles.Id); } if (targetLifePayChannles == null) { targetLifePayChannles = new SyncLifePayChannles(); ObjectMapper.Map(sourceLifePayChannles, targetLifePayChannles); await InsertLifePayChannles(targetConnName, targetLifePayChannles); dicChannleIds.Add(sourceLifePayChannles.Id, targetLifePayChannles.Id); logger.LogInformation($"已插入渠道:{targetLifePayChannles.ChannlesName}"); } else { var updateTargetLifePayChannles = new SyncLifePayChannles(); ObjectMapper.Map(sourceLifePayChannles, updateTargetLifePayChannles); updateTargetLifePayChannles.Id = targetLifePayChannles.Id; await UpdateLifePayChannles(targetConnName, updateTargetLifePayChannles); targetLifePayChannles = updateTargetLifePayChannles; dicChannleIds.Add(sourceLifePayChannles.Id, targetLifePayChannles.Id); logger.LogInformation($"已更新渠道:{targetLifePayChannles.ChannlesName}"); } } catch (Exception ex) { messages.Add($"未能同步渠道({sourceLifePayChannles.ChannlesName})发生服务器异常:{ex.Message}"); continue; } } foreach (var sourceLifePayChannlesRake in sourceLifePayChannlesRakeList) { try { var targetLifePayChannlesRake = targetLifePayChannlesRakeList.FirstOrDefault(it => it.Id == sourceLifePayChannlesRake.Id); if (targetLifePayChannlesRake == null) { targetLifePayChannlesRake = new SyncLifePayChannlesRake(); ObjectMapper.Map(sourceLifePayChannlesRake, targetLifePayChannlesRake); if (sourceLifePayChannlesRake.UserId.HasValue) { targetLifePayChannlesRake.UserId = dicUserIds[sourceLifePayChannlesRake.UserId]; } await InsertLifePayChannlesRake(targetConnName, targetLifePayChannlesRake); logger.LogInformation($"已插入分佣:{targetLifePayChannlesRake.OrderNo}"); } else { targetLifePayChannlesRake = new SyncLifePayChannlesRake(); ObjectMapper.Map(sourceLifePayChannlesRake, targetLifePayChannlesRake); if (sourceLifePayChannlesRake.UserId.HasValue) { targetLifePayChannlesRake.UserId = dicUserIds[sourceLifePayChannlesRake.UserId]; } await UpdateLifePayChannlesRake(targetConnName, targetLifePayChannlesRake); logger.LogInformation($"已更新分佣:{targetLifePayChannlesRake.OrderNo}"); } } catch (Exception ex) { messages.Add($"未能同步分佣({sourceLifePayChannlesRake.OrderNo})发生服务器异常:{ex.Message}"); continue; } } foreach (var sourceLifePayChannlesRake in sourceLifePayChannlesRakeList) { try { var targetLifePayChannlesRake = targetLifePayChannlesRakeList.FirstOrDefault(it => it.Id == sourceLifePayChannlesRake.Id); if (targetLifePayChannlesRake == null) { targetLifePayChannlesRake = new SyncLifePayChannlesRake(); ObjectMapper.Map(sourceLifePayChannlesRake, targetLifePayChannlesRake); if (sourceLifePayChannlesRake.UserId.HasValue) { targetLifePayChannlesRake.UserId = dicUserIds[sourceLifePayChannlesRake.UserId]; } await InsertLifePayChannlesRake(targetConnName, targetLifePayChannlesRake); logger.LogInformation($"已插入分佣:{targetLifePayChannlesRake.OrderNo}"); } else { targetLifePayChannlesRake = new SyncLifePayChannlesRake(); ObjectMapper.Map(sourceLifePayChannlesRake, targetLifePayChannlesRake); if (sourceLifePayChannlesRake.UserId.HasValue) { targetLifePayChannlesRake.UserId = dicUserIds[sourceLifePayChannlesRake.UserId]; } await UpdateLifePayChannlesRake(targetConnName, targetLifePayChannlesRake); logger.LogInformation($"已更新分佣:{targetLifePayChannlesRake.OrderNo}"); } } catch (Exception ex) { messages.Add($"未能同步分佣({sourceLifePayChannlesRake.OrderNo})发生服务器异常:{ex.Message}"); continue; } } foreach (var sourceLifePayConsumption in sourceLifePayConsumptionList) { try { var targetLifePayConsumption = targetLifePayConsumptionList.FirstOrDefault(it => it.Id == sourceLifePayConsumption.Id); if (targetLifePayConsumption == null) { targetLifePayConsumption = new SyncLifePayConsumption(); ObjectMapper.Map(sourceLifePayConsumption, targetLifePayConsumption); if (sourceLifePayConsumption.UserId.HasValue) { targetLifePayConsumption.UserId = dicUserIds[sourceLifePayConsumption.UserId]; } await InsertLifePayConsumption(targetConnName, targetLifePayConsumption); logger.LogInformation($"已插入消费流水:{targetLifePayConsumption.OrderNo}"); } else { targetLifePayConsumption = new SyncLifePayConsumption(); ObjectMapper.Map(sourceLifePayConsumption, targetLifePayConsumption); if (sourceLifePayConsumption.UserId.HasValue) { targetLifePayConsumption.UserId = dicUserIds[sourceLifePayConsumption.UserId]; } await UpdateLifePayConsumption(targetConnName, targetLifePayConsumption); logger.LogInformation($"已更新消费流水:{targetLifePayConsumption.OrderNo}"); } } catch (Exception ex) { messages.Add($"未能同步消费流水({sourceLifePayConsumption.OrderNo})发生服务器异常:{ex.Message}"); continue; } } foreach (var sourceLifePayExpensesReceipts in sourceLifePayExpensesReceiptsList) { try { if (sourceLifePayExpensesReceipts.FinishTime == DateTime.MinValue) { sourceLifePayExpensesReceipts.FinishTime = null; } var targetLifePayExpensesReceipts = targetLifePayExpensesReceiptsList.FirstOrDefault(it => it.Id == sourceLifePayExpensesReceipts.Id); if (targetLifePayExpensesReceipts == null) { targetLifePayExpensesReceipts = new SyncLifePayExpensesReceipts(); ObjectMapper.Map(sourceLifePayExpensesReceipts, targetLifePayExpensesReceipts); if (sourceLifePayExpensesReceipts.UserId.HasValue) { targetLifePayExpensesReceipts.UserId = dicUserIds[sourceLifePayExpensesReceipts.UserId]; } await InsertLifePayExpensesReceipts(targetConnName, targetLifePayExpensesReceipts); logger.LogInformation($"已插入收支流水:{targetLifePayExpensesReceipts.OrderNo}"); } else { targetLifePayExpensesReceipts = new SyncLifePayExpensesReceipts(); ObjectMapper.Map(sourceLifePayExpensesReceipts, targetLifePayExpensesReceipts); if (sourceLifePayExpensesReceipts.UserId.HasValue) { targetLifePayExpensesReceipts.UserId = dicUserIds[sourceLifePayExpensesReceipts.UserId]; } await UpdateLifePayExpensesReceipts(targetConnName, targetLifePayExpensesReceipts); logger.LogInformation($"已更新收支流水:{targetLifePayExpensesReceipts.OrderNo}"); } } catch (Exception ex) { messages.Add($"未能同步收支流水({sourceLifePayExpensesReceipts.OrderNo})发生服务器异常:{ex.Message}"); continue; } } return messages; } } }