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}";
}
}
}
}