using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Text; using WMS.Web.Domain.IService; using Aliyun.Acs.Core; using Aliyun.Acs.Core.Profile; using Aliyun.Acs.Dysmsapi.Model.V20170525; using Aliyun.Acs.Core.Exceptions; using WMS.Web.Core.Internal.Results; using System.Threading.Tasks; using WMS.Web.Domain.Options; using Microsoft.Extensions.Options; using MimeKit; using MailKit.Net.Smtp; using MailKit.Security; using Newtonsoft.Json; using WMS.Web.Domain.Infrastructure; using WMS.Web.Core.Dto; using System.Linq; using WMS.Web.Domain.IService.Public; using WMS.Web.Core.Dto.Erp; using WMS.Web.Domain.Entitys; namespace WMS.Web.Domain.Services { /// /// 阿里云短息服务 /// public class SendMessageService : ISendMessageService { private readonly ILogger _logger; private readonly IClientProfile profile; private readonly DefaultAcsClient client; private readonly EmailOptions _emailOptions; private readonly SmsOptions _smsOptions; private readonly IInStockRepositories _inStockRepositories; private readonly IInStockTaskRepositories _inStockTaskRepositories; private readonly IErpBasicDataExtendService _erpBasicDataExtendService; private readonly ISubscribeNotificationRepositories _subscribeNotificationRepositories; private readonly IErpService _erpService; public SendMessageService(ILogger logger, IOptions emailOptions, IOptions smsOptions, IInStockRepositories inStockRepositories, IErpService erpService, IErpBasicDataExtendService erpBasicDataExtendService, IInStockTaskRepositories inStockTaskRepositories, ISubscribeNotificationRepositories subscribeNotificationRepositories) { _logger = logger; _erpService = erpService; _inStockRepositories = inStockRepositories; _erpBasicDataExtendService = erpBasicDataExtendService; _inStockTaskRepositories = inStockTaskRepositories; _subscribeNotificationRepositories = subscribeNotificationRepositories; _emailOptions = emailOptions?.Value; _smsOptions = smsOptions?.Value; profile = DefaultProfile.GetProfile("cn-hangzhou", _smsOptions.AccessKeyId, _smsOptions.AccessKeySecret); client = new DefaultAcsClient(profile); } /// /// 短信发送 /// /// /// /// public Result SendSms(string phoneNumbers, string content) { // 构造短信请求 SendSmsRequest request = new SendSmsRequest(); request.PhoneNumbers = phoneNumbers; // 目标手机号 request.SignName = _smsOptions.SignName; // 短信签名 //request.SignName = "深圳市元创时代"; // 短信签名 request.TemplateCode = _smsOptions.TemplateCode; // 短信模板编号 request.TemplateParam = "{\"material\":\"" + content + "\"}"; // 模板参数,根据实际情况填写 try { // 发送短信 SendSmsResponse response = client.GetAcsResponse(request); //isv.PARAM_LENGTH_LIMIT if (response.Code == "OK") { _logger.LogInformation($"短信发送消息:成功->短信签名:{_smsOptions.SignName}->手机号码:" + phoneNumbers + " 内容:" + content); return Result.ReSuccess(); } else { _logger.LogInformation($"短信发送消息:失败->原因:{response.Message}->短信签名:{_smsOptions.SignName}->手机号码:" + phoneNumbers + " 内容:" + content); return Result.ReFailure(response.Code, 6000); } } catch (ServerException e) { _logger.LogInformation($"短信发送消息:Server失败:{e.ErrorMessage}->手机号码:" + phoneNumbers + " 内容:" + content); return Result.ReFailure(e.ErrorMessage, 6000); } catch (ClientException e) { _logger.LogInformation($"短信发送消息:Client失败:{e.ErrorMessage}->手机号码:" + phoneNumbers + " 内容:" + content); return Result.ReFailure(e.ErrorMessage, 6000); } } /// /// 邮箱发送消息 /// /// /// /// public async Task SendEmail(string mailAddress, string textBody, string coustomerName) { // 创建 MimeMessage 实例 MimeMessage message = new MimeMessage(); //message.From.Add(new MailboxAddress( _emailOptions.SenderName, _emailOptions.SenderEmail)); // 设置发件人姓名和邮箱地址 message.From.Add(new MailboxAddress("深圳市元创时代", _emailOptions.SenderEmail)); // 设置发件人姓名和邮箱地址 message.To.Add(new MailboxAddress(coustomerName, mailAddress)); // 设置收件人姓名和邮箱地址 //message.To.AddRange(toMailList); //message.Subject = _emailOptions.SendTitle+$"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"; // 设置邮件主题 message.Subject = $"【深圳市元创时代】-产品入库通知{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"; // 设置邮件主题 // 创建邮件正文 BodyBuilder bodyBuilder = new BodyBuilder(); //bodyBuilder.TextBody = textBody; // 设置纯文本内容 bodyBuilder.HtmlBody = $"

尊敬的{coustomerName},您好,您的以下产品已入库/可安排发货:\r\n

{textBody}

"; // 设置 HTML 内容 message.Body = bodyBuilder.ToMessageBody(); try { // 连接 SMTP 服务器并发送邮件 using (SmtpClient client = new SmtpClient()) { await client.ConnectAsync(_emailOptions.SmtpServer, _emailOptions.SmtpPort, SecureSocketOptions.StartTls); // 连接 SMTP 服务器 await client.AuthenticateAsync(_emailOptions.SenderEmail, _emailOptions.SenderEmailPwd); // 进行身份验证 await client.SendAsync(message); // 发送邮件 await client.DisconnectAsync(true); // 断开连接 } _logger.LogInformation("邮箱发送消息:成功->收件方:" + mailAddress + " 内容:" + textBody); return Result.ReSuccess(); } catch (Exception ex) { _logger.LogInformation("邮箱发送消息:失败->收件方:" + mailAddress + " 内容:" + textBody); return Result.ReFailure("邮箱发送:失败->收件方:"+mailAddress+",错误内容:" + ex.Message, 50006); } } /// /// 获取数据 /// /// public async Task<(List sendDataList, List updateDetails)> GetSendContent() { //1.获取物料集合和组织集合和供应商的集合 var materials = new List(); var materials_result = await _erpService.BillQueryForMaterial(); if (materials_result.IsSuccess) materials = materials_result.Data.ToList(); //客户 var customerList = await _subscribeNotificationRepositories.GetList(); //要处理发送的明细 //var notSendDetails = await _inStockTaskRepositories.GetNotSendErpDetails(); var notSendDetails = await _inStockRepositories.GetNotSendDetails(); _logger.LogInformation("发送消息:要处理发送的明细->:" + JsonConvert.SerializeObject(notSendDetails)); var sendDataList = new List(); if (customerList != null && customerList.Count != 0) { if (notSendDetails != null && notSendDetails.Count != 0) { //var taskIds = notSendDetails.GroupBy(x => x.Fid).Select(x => x.Key).ToList(); //var instockTotalDetails = await _inStockRepositories.GetInStockTotalDetails(taskIds); var instockTotalDetails = notSendDetails.GroupBy(x => new { x.CustomerCode, x.MaterialNumber }).Select(x => new { CustomerCode = x.Key.CustomerCode, MaterialNumber = x.Key.MaterialNumber, TotalQty = x.Sum(t => t.Qty) }).ToList(); foreach (var item in customerList) { //var current_notSendDetails = notSendDetails.Where(x => x.CustomerCode == item.CustomerNumber).ToList(); //var current_notSendDetails = instockTotalDetails.Where(x => x.CustomerCode == item.CustomerNumber).ToList(); var current_notSendDetails = instockTotalDetails.Where(x => x.CustomerCode == item.CustomerNumber).ToList(); if (current_notSendDetails != null && current_notSendDetails.Count != 0) { var data = new SendDataDto(); data.CustomerCode = item.CustomerNumber; data.CustomerName = item.CustomerName; data.PhoneNumbers = string.Join(",", item.Telephones); data.Emails = string.Join(",", item.Emails); foreach (var ema in item.Emails) { if (!string.IsNullOrEmpty(ema)) data.EmailList.Add(new MailAddress(item.CustomerName, ema)); } foreach (var current_det in current_notSendDetails) { var det = new SendDataDetailsDto(); //det.TaskDetailId = current_det.Id; det.MaterialName = _erpBasicDataExtendService.GetMaterialName(materials, current_det.MaterialNumber); det.Specifications = _erpBasicDataExtendService.GetMaterialSpecifications(materials, current_det.MaterialNumber); det.MaterialNumber = current_det.MaterialNumber; //det.Qty = instockTotalDetails.Where(x => x.TaskId == current_det.Fid && x.MaterialNumber == current_det.MaterialNumber).Sum(x => x.Qty); det.Qty = current_det.TotalQty; data.Details.Add(det); //if (det.Qty > 0) // data.Details.Add(det); } if (data.Details.Count != 0) sendDataList.Add(data); } } } } return (sendDataList, notSendDetails); } /// /// 执行 /// /// public async Task Execute() { try { var update_DetailsIds = new List(); var update_InstockIds = new List(); var (sendContentList,updateList) = await this.GetSendContent(); if (sendContentList != null && sendContentList.Count != 0) { foreach (var item in sendContentList) { var content = ""; int i = 1; foreach (var det in item.Details) { if (i == item.Details.Count) content = content+ det.Specifications + " 数量" + Convert.ToInt32(det.Qty); else content = content + det.Specifications + " 数量" + Convert.ToInt32(det.Qty) + ","; i = i + 1; } foreach (var email in item.EmailList) { //邮箱 await this.SendEmail(email.Email, content, email.Name); } //短信 var sms_result = this.SendSms(item.PhoneNumbers, content); //内容过长-分段发送 if (!sms_result.IsSuccess && sms_result.Message == "isv.PARAM_LENGTH_LIMIT") { //分段发送:以字数480长度分段 //var contentParts = this.SplitContent(content, 480); //foreach (var partContent in contentParts) //{ // this.SendSms(item.PhoneNumbers, partContent); //} //1.先合并属性:规格和数量 var materials= this.MergeProperties(item.Details); //2.按450个字分组成多个字符串集合 var contentParts = this.MergeStrings(materials); foreach (var partContent in contentParts) { this.SendSms(item.PhoneNumbers, partContent); } } } update_DetailsIds = updateList.GroupBy(x=>x.Id).Select(x => x.Key).ToList(); //var inStockDetails = await _inStockRepositories.GetDetailsList(update_DetailsIds); //if (inStockDetails != null && inStockDetails.Count != 0) //{ // inStockDetails.ForEach(x => { x.IsHasSend = true; }); // var update_Result = await _inStockRepositories.UpdateRange(inStockDetails); // if (!update_Result) // { // _logger.LogInformation("发送消息:失败-修改入库明细->:" + JsonConvert.SerializeObject(inStockDetails)); // } // else // { // _logger.LogInformation("发送消息:成功-修改入库明细->:" + JsonConvert.SerializeObject(inStockDetails)); // } //} update_InstockIds = updateList.GroupBy(x => x.Fid).Select(x => x.Key).ToList(); var inStocks = await _inStockRepositories.GetList(update_InstockIds); if (inStocks != null && inStocks.Count != 0) { inStocks.SelectMany(x => x.Details).Where(x=> update_DetailsIds.Contains(x.Id)).ToList().ForEach(x => { x.IsHasSend = true; }); var isSuccess = await _inStockRepositories.UpdateRange(inStocks); if (!isSuccess) { _logger.LogInformation("发送消息:失败-修改入库明细->:" + JsonConvert.SerializeObject(inStocks.SelectMany(x => x.Details).Where(x => update_DetailsIds.Contains(x.Id)).ToList())); } else { _logger.LogInformation("发送消息:成功-修改入库明细->:" + JsonConvert.SerializeObject(inStocks.SelectMany(x => x.Details).Where(x => update_DetailsIds.Contains(x.Id)).ToList())); } } } else _logger.LogInformation("发送消息:暂无可发送的通知明细"); return Result.ReSuccess(); } catch (Exception ex) { return Result.ReFailure("发送失败:" + ex.Message, 50006); } } // 将消息分割成多个部分 public List SplitContent(string content, int maxLength) { List parts = new List(); for (int i = 0; i < content.Length; i += maxLength) { parts.Add(content.Substring(i, Math.Min(maxLength, content.Length - i))); } return parts; } /// /// 合并属性 /// /// /// public List MergeProperties(List details) { List result = new List(); foreach (var det in details) { result.Add($"{det.Specifications} 数量{Convert.ToInt32(det.Qty)}"); } return result; } /// /// 按450个字开始分组 /// /// /// public List MergeStrings(List strings) { List result = new List(); StringBuilder currentGroup = new StringBuilder(); foreach (var str in strings) { if (currentGroup.Length + str.Length > 450) { // 当前字符串超过50个字符,将当前分组加入结果集并重置currentGroup result.Add(currentGroup.ToString()); currentGroup.Clear(); } // 添加当前字符串到当前分组 currentGroup.Append(str); } // 添加最后一个分组 if (currentGroup.Length > 0) { result.Add(currentGroup.ToString()); } return result; } } }