using System.Diagnostics; using Microsoft.AspNetCore.DataProtection.KeyManagement; using Newtonsoft.Json; namespace SA.Domain.XFYun.XFYunDomains { /// /// 讯飞处理 /// public class XFYunDomain : IXFYunDomain { private readonly SystemConfig _systemConfig; private readonly IXFYunApi _xfyunApi; private readonly IZXDApi _zxdApi; /// /// 讯飞处理 /// /// /// public XFYunDomain( IXFYunApi xfyunApi, IZXDApi zxdApi) { _xfyunApi = xfyunApi; _zxdApi = zxdApi; _systemConfig = InitConfiguration.GetSection("SystemConfig").Get(); } /// /// 发送信息 /// /// public async Task SendSms() { try { var tasks = await InitDB.zxdcrmDb.Queryable() .Where(x => x.Sms == 1 && x.Smstime <= DateTime.Now) .ToListAsync(); if (tasks == null || !tasks.Any()) return; var mobiles = tasks.Select(x => x.Resid).Distinct().ToList(); var request = new ZXDEntity.SmsMessage { Message = SerializeHelper.ToJson(new { _systemConfig.SmsConfig.TypeCode, _systemConfig.SmsConfig.SubTypeCode, Para = "" }), Mobile = mobiles }; var taskIds = tasks.Select(x => x.Id).ToList(); var orders = await InitDB.zxdcrmDb.Queryable() .LeftJoin((t1, t2) => t1.Orderid == t2.Orderid) .Where((t1, t2) => taskIds.Contains(t2.Taskid.Value)) .ToListAsync(); // 判断订单是否已开通,如果已开通则不执行外呼 if (orders.Any(x => x.Orderstatus == "220" || x.AiHgrecordStatus == -1)) { LogHelper.Info($"订单[{string.Join(",", orders.Select(x => x.Orderid).ToList())}]已忽略外呼,不执行[短信发送任务]"); tasks.ForEach(x => { x.Sms = 2; x.Smstime = DateTime.Now; }); } else { var result = await _zxdApi.PutSms(request); if (result.Result) { tasks.ForEach(x => { x.Sms = 2; x.Smstime = DateTime.Now; }); } } await InitDB.zxdcrmDb.Updateable(tasks).ExecuteCommandAsync(); } catch (Exception ex) { LogHelper.Error(ex, "短信任务报错!"); } } /// /// 订单外呼 /// /// public async Task OrderOutbound() { try { var time = DateTime.Now.AddMinutes(_systemConfig.IntervalMinutes); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); var key = "singleAdd"; var accessKey = _systemConfig.ClientKey.Where(x => x.Id == _systemConfig.CRMClientKey).Select(x => x.AccessKey).First(); List userStatus = new List { 8, 9 }; var list = await InitDB.zxdcrmDb.Queryable() .LeftJoin((t1, t2) => t1.Resid == t2.Resid) .Where(t1 => (t1.Sms == 0 || (t1.Sms == 2 && t1.Smstime <= time)) && t1.Status == 0 && t1.Exetime <= DateTime.Now && !userStatus.Contains(t1.AiHgrecordStatus.Value)) //排除人工操作的任务 .Select((t1, t2) => new SingleAddRequest { ExtTaskId = t1.Id.ToString(), AppId = t1.AppId, CallNo = t1.CallNo, Priority = t1.Priority, Robot = t1.Robot, Phone = t2.Mobile, PropsStr = t1.Props, Ext = _systemConfig.Ext }) .ToListAsync(); stopwatch.Stop(); LogHelper.Info($"订单外呼查询【{stopwatch.ElapsedMilliseconds}ms】"); if (list == null || !list.Any()) return; var tasks = await InitDB.zxdcrmDb.Queryable() .Where(x => list.Select(y => int.Parse(y.ExtTaskId ?? "0")).Contains(x.Id)) .ToListAsync(); var taskIds = tasks.Select(x => x.Id).ToList(); LogHelper.Info($"任务[{string.Join(",", taskIds)}]正在执行[外呼任务],任务数量[{taskIds.Count}]"); foreach (var param in list) { var task = tasks.First(x => x.Id.ToString() == param.ExtTaskId); await CallOrder(param, task); } } catch (Exception ex) { LogHelper.Error(ex, "定时任务报错!"); } } public async Task CallOrder(SingleAddRequest param, CsvrAiCalltask task) { var key = "singleAdd"; var accessKey = _systemConfig.ClientKey.Where(x => x.Id == _systemConfig.CRMClientKey).Select(x => x.AccessKey).First(); try { param.Phone = SecurityHelper.DecyptData(param.Phone, accessKey); } catch (Exception ex) { Log.Warning("手机号解密失败,尝试[gd_crm]进行解密" + ex.Message); var ordAccessKey = _systemConfig.ClientKey.Where(x => x.Id == "gd_crm").Select(x => x.AccessKey).First(); try { param.Phone = SecurityHelper.DecyptData(param.Phone, ordAccessKey); } catch (Exception ex2) { LogHelper.Error("手机号解密失败!", ex2); } } param.Props = string.IsNullOrEmpty(param.PropsStr) ? new Dictionary() : SerializeHelper.FromJson>(param.PropsStr); var orders = await InitDB.zxdcrmDb.Queryable() .LeftJoin((t1, t2) => t1.Orderid == t2.Orderid) .Where((t1, t2) => task.Id == t2.Taskid) .ToListAsync(); // 生成唯一id task.ExtTaskId = CreateExTaskId(task.Id); param.ExtTaskId = task.ExtTaskId; var request = new XFYunRequest( param.AppId, key, _systemConfig.XFYunGroudId, param); List containStatus = new List { 82243656,82243655,82243649,82243646,82243525,82243515,82243504,82243469,82243393,82243351,82243330,82243276,82243265,82243246,82242374,82243488,82244062 }; // 判断订单是否已开通,如果已开通则不执行外呼 if (orders.Any(x => x.Orderstatus == "220" || x.AiHgrecordStatus == -1)) { LogHelper.Info($"订单[{string.Join(",", orders.Select(x => x.Orderid).ToList())}]已忽略外呼,不执行[外呼任务]"); task.Status = 2; orders.ForEach(x => x.AiHgrecordStatus = -1); } else { // 执行外呼 var result = await _xfyunApi.SingleAdd(request); task.Utime = DateTime.Now; if (result.Ret == 0 && result.Data.Success) { task.Status = 1; orders.ForEach(x => x.AiHgrecordStatus = 2); } else { task.Status = 2; task.RetDesc = result.Ret != 0 ? result.Msg : result.Data.Desc; orders.ForEach(x => x.AiHgrecordStatus = 4); } } if (orders.Any(x => containStatus.Contains(x.Orderid))) { LogHelper.Info($"订单[{string.Join(",", orders.Select(x => x.Orderid).ToList())}]忽略订单状态,直接外呼"); var result = await _xfyunApi.SingleAdd(request); task.Utime = DateTime.Now; if (result.Ret == 0 && result.Data.Success) { task.Status = 1; orders.ForEach(x => x.AiHgrecordStatus = 2); } else { task.Status = 2; task.RetDesc = result.Ret != 0 ? result.Msg : result.Data.Desc; orders.ForEach(x => x.AiHgrecordStatus = 4); } } task.AiHgrecordStatus = orders.FirstOrDefault() == null ? task.AiHgrecordStatus : orders.FirstOrDefault()?.AiHgrecordStatus; try { InitDB.zxdcrmDb.BeginTran(); await InitDB.zxdcrmDb.Updateable(orders).UpdateColumns(x => new { x.AiHgrecordStatus, x.AiHgrecordStatusname }).ExecuteCommandAsync(); await InitDB.zxdcrmDb.Updateable(task).ExecuteCommandAsync(); InitDB.zxdcrmDb.CommitTran(); } catch (Exception ex) { InitDB.zxdcrmDb.RollbackTran(); LogHelper.Error(ex, "[外呼任务]报错!"); } } /// /// 生成唯一id /// /// /// private static string CreateExTaskId(int taksId) { var unixTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds(); var randomString = CreateRandomNumber(4); return $"{unixTime}{taksId}{randomString}"; } /// /// 生成随机数字 /// /// 生成长度 /// 是否要在生成前将当前线程阻止以避免重复 /// private static string CreateRandomNumber(int Length, bool Sleep = true) { if (Sleep) Thread.Sleep(3); string result = ""; Random random = new(); for (int i = 0; i < Length; i++) { result += random.Next(10).ToString(); } return result; } /// /// 回调函数 /// /// /// public async Task Callback(CallDetail detail) { try { var task = await InitDB.zxdcrmDb.Queryable() .Where(x => x.ExtTaskId == detail.ExtTaskId) .OrderByDescending(x => x.Id) .FirstAsync(); var orders = await InitDB.zxdcrmDb.Queryable() .LeftJoin((t1, t2) => t1.Orderid == t2.Orderid) .Where((t1, t2) => task.Id == t2.Taskid) .ToListAsync(); // 不明文显示 //detail.Phone = SecurityHelper.EncyptData(detail.Phone, "UPWEBSITE"); LogHelper.Info($"讯飞回调刷新 {string.Join(",", orders.Select(n => n.Orderid))} 讯飞结果:{JsonConvert.SerializeObject(detail)}"); await UpdateTask(task, orders, detail, true); } catch (Exception ex) { LogHelper.Error(ex, "更新回调信息报错!"); } return new { rc = "000000", desc = "" }; } /// /// 更新任务状态 /// /// /// /// /// /// /// private static async Task UpdateTask(CsvrAiCalltask? task, List orders, CallDetail detail, bool result = false, string error = "") { if (task == null) return; task.Status = 2; task.Exetime = DateTime.Now; task.CallRet = detail.CallRet; task.Audio = detail.Audio; task.Labels = detail.Labels; task.Content = detail.Content; task.EndTime = string.IsNullOrEmpty(detail.EndTime) ? null : DateTime.Parse(detail.EndTime); task.StartTime = string.IsNullOrEmpty(detail.StartTime) ? null : DateTime.Parse(detail.StartTime); task.PlatSingleTaskId = detail.PlatTaskId; task.SvcTime = detail.SvcTime; task.Interact = detail.Interact == null || !detail.Interact.Any() ? "" : SerializeHelper.ToJson(detail.Interact); task.Rounds = detail.Interact == null || !detail.Interact.Any() ? 0 : detail.Interact.Where(n => n.Type == "1").Count(); // 判断对话信息是否完整 var full = false; var labels = new Dictionary(); orders.ForEach(x => x.Hasaiaudio = string.IsNullOrEmpty(task.Audio) ? 0 : 1); //人工操作的不刷新状态 List userStatus = new List { 8,9 }; orders = orders.Where(n => !userStatus.Contains(n.AiHgrecordStatus.Value)).ToList(); var updateStatus = 0; if (!string.IsNullOrEmpty(detail.Labels)) { labels = SerializeHelper.FromJson>(detail.Labels); if (labels.Any() && labels.TryGetValue("访问结果", out string? label) && label == "正常访问") { full = true; } } if (result && detail.Status == 3 && full) { task.RetDesc = detail.RetDesc; updateStatus = string.IsNullOrEmpty(detail.RetDesc) ? 4 : detail.RetDesc == "外呼成功" ? 5 : 3; } else { task.RetDesc = !string.IsNullOrEmpty(error) ? error : !string.IsNullOrEmpty(detail.RetDesc) ? detail.RetDesc : "外呼失败"; if (detail.Interact == null || !detail.Interact.Any()) { updateStatus = 4; } else { // 如果不存在人为回答,需要把状态改为AI外呼失败(挂断) if (!detail.Interact.Any(x => x.Type == "1")) { updateStatus = 7; } else { updateStatus = 3; } } } task.AiHgrecordStatus = updateStatus; var genOrderCallConfig = GenOrderCall.GetConfig(); var ReCallMin = genOrderCallConfig.ReCallMins; //找出是否存在其他任务 if (orders.Count > 0) { var taskids = InitDB.zxdcrmDb.Queryable().Where(d => d.Orderid == orders.FirstOrDefault().Orderid).Select(d => d.Taskid).ToList(); //如果 任务外呼 失败 且 大于重拨次数 直接刷为 ai重拨失败 List failStatus = new List { 3, 4, 7 }; if (taskids.Count > ReCallMin.Count && failStatus.Contains(updateStatus)) { updateStatus = -2; LogHelper.Info($"订单【{string.Join(",", orders.Select(n => n.Orderid))}】刷新状态为【AI重拨失败】"); } orders.ForEach(x => x.AiHgrecordStatus = updateStatus); } LogHelper.Info($"任务编号【{task.Id}】订单为【{string.Join(",", orders.Select(n => n.Orderid))}】刷新状态为【{task.AiHgrecordStatusname}】"); try { InitDB.zxdcrmDb.BeginTran(); await InitDB.zxdcrmDb.Updateable(orders).UpdateColumns(x => new { x.AiHgrecordStatus, x.AiHgrecordStatusname, x.Hasaiaudio }).ExecuteCommandAsync(); await InitDB.zxdcrmDb.Updateable(task).ExecuteCommandAsync(); InitDB.zxdcrmDb.CommitTran(); } catch (Exception ex) { InitDB.zxdcrmDb.RollbackTran(); LogHelper.Error(ex, "定时任务报错!"); } } /// /// 轮询获取结果 /// /// public async Task UpdateCallbackResult() { try { var time = DateTime.Now.AddMinutes(_systemConfig.CallbackMinutes); var key = "singleQuery"; var accessKey = _systemConfig.ClientKey.Where(x => x.Id == _systemConfig.CRMClientKey).Select(x => x.AccessKey).First(); var tasks = await InitDB.zxdcrmDb.Queryable() .Where(t1 => t1.Status == 1 && t1.Utime <= time) .ToListAsync(); if (tasks == null || !tasks.Any()) return; foreach (var task in tasks) { if (task == null) continue; var taskId = task?.Id; var param = new SingleQueryRequest() { ExtTaskId = task?.ExtTaskId ?? task?.Id.ToString(), AppId = task?.AppId, }; var request = new XFYunRequest( param.AppId, key, _systemConfig.XFYunGroudId, param); // 获取结果 var result = await _xfyunApi.SingleQuery(request); var orders = await InitDB.zxdcrmDb.Queryable() .LeftJoin((t1, t2) => t1.Orderid == t2.Orderid) .Where((t1, t2) => taskId == t2.Taskid) .ToListAsync(); LogHelper.Info($"任务自动刷新时间,任务id: {taskId} {string.Join(",", orders.Select(n => n.Orderid))}讯飞结果:{JsonConvert.SerializeObject(result)}"); if (result.Ret == 0 && result?.Data?.Result != null) { //录音不为空才做更新 if (!string.IsNullOrWhiteSpace(result.Data.Result.Audio)) { await UpdateTask(task, orders, result.Data.Result, result.Data.Success, result.Error ?? ""); } } else { LogHelper.Error($"定时任务获取结果出错,任务id: {taskId}, 错误信息: {result?.Msg}"); } } } catch (Exception ex) { LogHelper.Error(ex, "定时任务报错!"); } } /// /// /// /// /// public async Task GetCallbackResult(int taskId) { try { var key = "singleQuery"; var task = await InitDB.zxdcrmDb.Queryable() .Where(t1 => t1.Id == taskId) .FirstAsync(); if (task == null) return task; var param = new SingleQueryRequest() { ExtTaskId = task?.ExtTaskId ?? task?.Id.ToString(), AppId = task?.AppId, }; var request = new XFYunRequest( param.AppId, key, _systemConfig.XFYunGroudId, param); // 获取结果 var result = await _xfyunApi.SingleQuery(request); var orders = await InitDB.zxdcrmDb.Queryable() .LeftJoin((t1, t2) => t1.Orderid == t2.Orderid) .Where((t1, t2) => taskId == t2.Taskid) .ToListAsync(); if (result.Ret == 0 && result?.Data?.Result != null) { await UpdateTask(task, orders, result.Data.Result, result.Data.Success, result.Error ?? ""); } else { LogHelper.Error($"定时任务获取结果出错,任务id: {taskId}, 错误信息: {result?.Msg}"); } return task; } catch (Exception ex) { LogHelper.Error(ex, "更新回调信息报错!"); return null; } } /// /// 单纯获取讯飞结果 /// /// /// public async Task GetCallbackResultByXunFei(int taskId) { try { var key = "singleQuery"; var task = await InitDB.zxdcrmDb.Queryable() .Where(t1 => t1.Id == taskId) .FirstAsync(); if (task == null) return ""; var param = new SingleQueryRequest() { ExtTaskId = task?.ExtTaskId ?? task?.Id.ToString(), AppId = task?.AppId, }; var request = new XFYunRequest( param.AppId, key, _systemConfig.XFYunGroudId, param); // 获取结果 var result = await _xfyunApi.SingleQuery(request); var res = JsonConvert.SerializeObject(result); return res.ToString(); } catch (Exception ex) { LogHelper.Info($"获取讯飞结果出错{ex.Message}"); return $"获取讯飞结果出错{ex.Message}"; } } } }