using Blog.Core.Common;
using Blog.Core.Common.Helper;
using Blog.Core.IRepository.Base;
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
using Blog.Core.Model.ViewModels;
using Blog.Core.Services.BASE;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Blog.Core.Repository.UnitOfWorks;
namespace Blog.Core.Services
{
///
/// WeChatConfigServices
///
public class WeChatConfigServices : BaseServices, IWeChatConfigServices
{
readonly IUnitOfWorkManage _unitOfWorkManage;
readonly ILogger _logger;
public WeChatConfigServices(IUnitOfWorkManage unitOfWorkManage, ILogger logger)
{
this._unitOfWorkManage = unitOfWorkManage;
this._logger = logger;
}
public async Task> GetToken(string publicAccount)
{
var config = await this.QueryById(publicAccount);
if (config == null) MessageModel.Success($"公众号{publicAccount}未维护至系统");//还没过期,直接返回
if (config.tokenExpiration > DateTime.Now)
{
//再次判断token在微信服务器是否正确
var wechatIP = await WeChatHelper.GetWechatIP(config.token);
if (wechatIP.errcode == 0)
MessageModel.Success("", new WeChatApiDto { access_token = config.token });//还没过期,直接返回
}
//过期了,重新获取
var data = await WeChatHelper.GetToken(config.appid, config.appsecret);
if (data.errcode.Equals(0))
{
config.token = data.access_token;
config.tokenExpiration = DateTime.Now.AddSeconds(data.expires_in);
await this.Update(config);
return MessageModel.Success("",data);
}
else
{
return MessageModel.Fail($"\r\n获取Token失败\r\n错误代码:{data.errcode}\r\n错误信息:{data.errmsg}");
}
}
public async Task> RefreshToken(string publicAccount)
{
var config = await this.QueryById(publicAccount);
if (config == null) MessageModel.Success($"公众号{publicAccount}未维护至系统");//还没过期,直接返回
//过期了,重新获取
var data = await WeChatHelper.GetToken(config.appid, config.appsecret);
if (data.errcode.Equals(0))
{
config.token = data.access_token;
config.tokenExpiration = DateTime.Now.AddSeconds(data.expires_in);
await this.Update(config);
return MessageModel.Success("", data);
}
else
{
return MessageModel.Fail($"\r\n获取Token失败\r\n错误代码:{data.errcode}\r\n错误信息:{data.errmsg}");
}
}
public async Task> GetTemplate(string id)
{
var res = await GetToken(id);
if (!res.success) return res;
var data = await WeChatHelper.GetTemplate(res.response.access_token);
if (data.errcode.Equals(0))
{
return MessageModel.Success("", data);
}
else
{
return MessageModel.Success($"\r\n获取模板失败\r\n错误代码:{data.errcode}\r\n错误信息:{data.errmsg}", data);
}
}
///
/// 获取菜单
///
///
///
public async Task> GetMenu(string id)
{
var res = await GetToken(id);
if (!res.success) return res;
var data = await WeChatHelper.GetMenu(res.response.access_token);
if (data.errcode.Equals(0))
{
return MessageModel.Success("", data);
}
else
{
return MessageModel.Success($"\r\n获取菜单失败\r\n错误代码:{data.errcode}\r\n错误信息:{data.errmsg}", data);
}
}
public async Task> GetSubUsers(string id)
{
var res = await GetToken(id);
if (!res.success) return res;
var data = await WeChatHelper.GetUsers(res.response.access_token);
if (data.errcode.Equals(0))
{
data.users = new List();
foreach (var openid in data.data.openid)
{
data.users.Add(await WeChatHelper.GetUserInfo(res.response.access_token, openid));
}
return MessageModel.Success("", data);
}
else
{
return MessageModel.Success($"\r\n获取订阅用户失败\r\n错误代码:{data.errcode}\r\n错误信息:{data.errmsg}", data);
}
}
public async Task> GetSubUser(string id,string openid)
{
var res = await GetToken(id);
if (!res.success) return res;
var data = await WeChatHelper.GetUserInfo(res.response.access_token,openid);
if (data.errcode.Equals(0))
{
return MessageModel.Success("", data);
}
else
{
return MessageModel.Success($"\r\n获取订阅用户失败\r\n错误代码:{data.errcode}\r\n错误信息:{data.errmsg}", data);
}
}
public async Task Valid(WeChatValidDto validDto,string body)
{
WeChatXMLDto weChatData = null;
string objReturn = null;
try
{
_logger.LogInformation("会话开始");
if (string.IsNullOrEmpty(validDto.publicAccount)) throw new Exception("没有微信公众号唯一标识id数据");
var config = await QueryById(validDto.publicAccount);
if (config == null) throw new Exception($"公众号不存在=>{validDto.publicAccount}");
_logger.LogInformation(JsonHelper.GetJSON(validDto));
var token = config.interactiveToken;//验证用的token 和access_token不一样
string[] arrTmp = { token, validDto.timestamp, validDto.nonce };
Array.Sort(arrTmp);
string combineString = string.Join("", arrTmp);
string encryption = MD5Helper.Sha1(combineString).ToLower();
_logger.LogInformation(
$"来自公众号:{validDto.publicAccount}\r\n" +
$"微信signature:{validDto.signature}\r\n" +
$"微信timestamp:{validDto.timestamp}\r\n" +
$"微信nonce:{validDto.nonce}\r\n" +
$"合并字符串:{combineString}\r\n" +
$"微信服务器signature:{validDto.signature}\r\n" +
$"本地服务器signature:{encryption}"
);
if (encryption == validDto.signature)
{
//判断是首次验证还是交互?
if (string.IsNullOrEmpty(validDto.echoStr))
{
//非首次验证
weChatData = XmlHelper.ParseFormByXml(body, "xml");
weChatData.publicAccount = validDto.publicAccount;
objReturn = await HandleWeChat(weChatData);
}
else
{
//首次接口地址验证
objReturn = validDto.echoStr;
}
}
else
{
objReturn = "签名验证失败";
}
}
catch (Exception ex)
{
_logger.LogInformation($"会话出错(信息)=>\r\n{ex.Message}");
_logger.LogInformation($"会话出错(堆栈)=>\r\n{ex.StackTrace}");
//返回错误给用户
objReturn = string.Format(@$"
{DateTime.Now.Ticks.ToString()}
");
}
finally
{
_logger.LogInformation($"微信get数据=>\r\n{JsonHelper.GetJSON(validDto)}");
_logger.LogInformation($"微信post数据=>\r\n{body}");
_logger.LogInformation($"返回微信数据=>\r\n{objReturn}");
_logger.LogInformation($"会话结束");
}
return objReturn;
}
public async Task> GetQRBind(WeChatUserInfo info)
{
var res = await GetToken(info?.id);
if (!res.success) return MessageModel.Fail(res.msg);
var push = new WeChatQRDto
{
expire_seconds = 604800,
action_name = "QR_STR_SCENE",
action_info = new WeChatQRActionDto
{
scene = new WeChatQRActionInfoDto
{
scene_str = $"bind_{info?.id}"
}
}
};
WeChatResponseUserInfo reData = new WeChatResponseUserInfo();
reData.companyCode = info.companyCode;
reData.id = info.id;
var pushJosn = JsonHelper.GetJSON(push);
var data = await WeChatHelper.GetQRCode(res.response.access_token, pushJosn);
WeChatQR weChatQR = new WeChatQR
{
QRbindCompanyID = info.companyCode,
QRbindJobID = info.userID,
QRbindJobNick = info.userNick,
QRcrateTime = DateTime.Now,
QRpublicAccount = info.id,
QRticket = data.ticket
};
data.id = info.userID;
await this.BaseDal.Db.Insertable(weChatQR).ExecuteCommandAsync();
reData.usersData= data;
return MessageModel.Success("获取二维码成功", reData);
}
public async Task> PushCardMsg(WeChatCardMsgDataDto msg,string ip)
{
var bindUser = await BaseDal.Db.Queryable().Where(t => t.SubFromPublicAccount == msg.info.id && t.CompanyID == msg.info.companyCode && t.IsUnBind == false && msg.info.userID.Contains(t.SubJobID)).SingleAsync();
if (bindUser == null)
return MessageModel.Fail("用户不存在或者已经解绑!");
var res = await GetToken(msg?.info?.id);
if(!res.success)
return MessageModel.Fail(res.msg);
WeChatResponseUserInfo reData = new WeChatResponseUserInfo();
reData.companyCode = msg.info.companyCode;
reData.id = msg.info.id;
try
{
var pushData = new WeChatPushCardMsgDto
{
template_id = msg.cardMsg.template_id,
url = msg.cardMsg.url,
touser = bindUser.SubUserOpenID,
data = new WeChatPushCardMsgDetailDto
{
first = new WeChatPushCardMsgValueColorDto
{
value = msg.cardMsg.first,
color = msg.cardMsg.color1
},
keyword1 = new WeChatPushCardMsgValueColorDto
{
value = msg.cardMsg.keyword1,
color = msg.cardMsg.color1
},
keyword2 = new WeChatPushCardMsgValueColorDto
{
value = msg.cardMsg.keyword2,
color = msg.cardMsg.color2
},
keyword3 = new WeChatPushCardMsgValueColorDto
{
value = msg.cardMsg.keyword3,
color = msg.cardMsg.color3
},
keyword4 = new WeChatPushCardMsgValueColorDto
{
value = msg.cardMsg.keyword4,
color = msg.cardMsg.color4
},
keyword5 = new WeChatPushCardMsgValueColorDto
{
value = msg.cardMsg.keyword5,
color = msg.cardMsg.color5
},
remark = new WeChatPushCardMsgValueColorDto
{
value = msg.cardMsg.remark,
color = msg.cardMsg.colorRemark
}
}
};
var pushJson = JsonHelper.GetJSON(pushData);
var data = await WeChatHelper.SendCardMsg(res.response.access_token, pushJson);
reData.usersData = data;
try
{
var pushLog = new WeChatPushLog
{
PushLogCompanyID = msg.info.companyCode,
PushLogPublicAccount = msg.info.id,
PushLogContent = pushJson,
PushLogOpenid = bindUser.SubUserOpenID,
PushLogToUserID = bindUser.SubJobID,
PushLogStatus = data.errcode == 0 ? "Y" : "N",
PushLogRemark = data.errmsg,
PushLogTime = DateTime.Now,
PushLogTemplateID = msg.cardMsg.template_id,
PushLogIP = ip
};
await BaseDal.Db.Insertable(pushLog).ExecuteCommandAsync();
}
catch (Exception ex)
{
_logger.LogInformation($"记录失败\r\n{ex.Message}\r\n{ex.StackTrace}");
}
if (reData.usersData.errcode.Equals(0))
{
return MessageModel.Success("卡片消息推送成功", reData);
}
else
{
return MessageModel.Success("卡片消息推送失败", reData);
}
}
catch (Exception ex)
{
return MessageModel.Success($"卡片消息推送错误=>{ex.Message}", reData);
}
}
public async Task> PushTxtMsg(WeChatPushTestDto msg) {
var res = await GetToken(msg.selectWeChat);
if (!res.success) return res;
var token = res.response.access_token;
if (msg.selectBindOrSub.Equals("sub"))
{
return await PushText(token, msg);
}
else
{
MessageModel messageModel = new MessageModel();
messageModel.success = true;
//绑定用户
if (msg.selectOperate.Equals("one"))
{
//发送单个
var usrs = BaseDal.Db.Queryable().Where(t => t.SubFromPublicAccount.Equals(msg.selectWeChat) && t.CompanyID.Equals(msg.selectCompany) && t.SubJobID.Equals(msg.selectUser)).ToList();
foreach (var item in usrs)
{
msg.selectUser = item.SubUserOpenID;
var info = await PushText(token, msg);
if (!info.success)
{
messageModel.success = false;
}
messageModel.msg += info.msg;
}
}
else
{
//发送所有
var usrs = BaseDal.Db.Queryable().Where(t => t.SubFromPublicAccount.Equals(msg.selectWeChat) && t.CompanyID.Equals(msg.selectCompany)).ToList();
foreach (var item in usrs)
{
msg.selectUser = item.SubUserOpenID;
var info = await PushText(token, msg);
if (!info.success)
{
messageModel.success = false;
}
messageModel.msg += info.msg;
}
}
return messageModel;
}
}
public async Task> PushText(string token,WeChatPushTestDto msg) {
object data = null; ;
WeChatApiDto pushres = null; ;
//订阅用户
switch (msg.selectMsgType)
{
case "text":
//发送文本
data = new
{
filter = new
{
is_to_all = msg.selectOperate.Equals("one") ? false : true,
tag_id = 0,
},
touser = msg.selectUser,
msgtype = msg.selectMsgType,
text = new
{
content = msg.textContent.text
}
};
if (msg.selectOperate.Equals("one"))
{
pushres = await WeChatHelper.SendMsg(token, JsonHelper.ObjToJson(data));
}
else
{
pushres = await WeChatHelper.SendMsgToAll(token, JsonHelper.ObjToJson(data));
}
break;
case "image":
//发送图片
data = new
{
filter = new
{
is_to_all = msg.selectOperate.Equals("one") ? false : true,
tag_id = 0,
},
touser = msg.selectUser,
msgtype = msg.selectMsgType,
images = new
{
media_ids = new List {
msg.pictureContent.pictureMediaID
},
recommend = "xxx",
need_open_comment = 1,
only_fans_can_comment = 0
}
};
if (msg.selectOperate.Equals("one"))
{
pushres = await WeChatHelper.SendMsg(token, JsonHelper.ObjToJson(data));
}
else
{
pushres = await WeChatHelper.SendMsgToAll(token, JsonHelper.ObjToJson(data));
}
break;
case "voice":
//发送音频
data = new
{
filter = new
{
is_to_all = msg.selectOperate.Equals("one") ? false : true,
tag_id = 0,
},
touser = msg.selectUser,
msgtype = msg.selectMsgType,
voice = new
{
media_id = msg.voiceContent.voiceMediaID
}
};
if (msg.selectOperate.Equals("one"))
{
pushres = await WeChatHelper.SendMsg(token, JsonHelper.ObjToJson(data));
}
else
{
pushres = await WeChatHelper.SendMsgToAll(token, JsonHelper.ObjToJson(data));
}
break;
case "mpvideo":
//发送视频
data = new
{
filter = new
{
is_to_all = msg.selectOperate.Equals("one") ? false : true,
tag_id = 0,
},
touser = msg.selectUser,
msgtype = msg.selectMsgType,
mpvideo = new
{
media_id = msg.videoContent.videoMediaID,
}
};
if (msg.selectOperate.Equals("one"))
{
pushres = await WeChatHelper.SendMsg(token, JsonHelper.ObjToJson(data));
}
else
{
pushres = await WeChatHelper.SendMsgToAll(token, JsonHelper.ObjToJson(data));
}
break;
default:
pushres = new WeChatApiDto() { errcode = -1, errmsg = $"未找到推送类型{msg.selectMsgType}" };
break;
}
if (pushres.errcode.Equals(0))
{
return MessageModel.Success("推送成功", pushres);
}
else
{
return MessageModel.Fail($"\r\n推送失败\r\n错误代码:{pushres.errcode}\r\n错误信息:{pushres.errmsg}", pushres);
}
}
public async Task> UpdateMenu(WeChatApiDto menu)
{
WeChatHelper.ConverMenuButtonForEvent(menu);
var res = await GetToken(menu.id);
if (!res.success) return res;
var data = await WeChatHelper.SetMenu(res.response.access_token, JsonHelper.ObjToJson(menu.menu));
if (data.errcode.Equals(0))
{
return MessageModel.Success("更新成功", data);
}
else
{
return MessageModel.Success("更新失败", data);
}
}
public async Task> GetBindUserInfo(WeChatUserInfo info)
{
var bindUser = await BaseDal.Db.Queryable().Where(t => t.SubFromPublicAccount == info.id && t.CompanyID == info.companyCode && info.userID.Equals(t.SubJobID) && t.IsUnBind == false ).FirstAsync();
if (bindUser == null) return MessageModel.Fail("用户不存在或者已经解绑!");
var res = await GetToken(info.id);
if(!res.success) return MessageModel.Fail(res.msg);
var token = res.response.access_token;
WeChatResponseUserInfo reData = new WeChatResponseUserInfo();
reData.companyCode = info.companyCode;
reData.id = info.id;
var data = await WeChatHelper.GetUserInfo(token, bindUser.SubUserOpenID);
reData.usersData = data;
if (data.errcode.Equals(0))
{
return MessageModel.Success("用户信息获取成功", reData);
}
else
{
return MessageModel.Fail("用户信息获取失败", reData);
}
}
public async Task> UnBind(WeChatUserInfo info)
{
var bindUser = await BaseDal.Db.Queryable().Where(t => t.SubFromPublicAccount == info.id && t.CompanyID == info.companyCode && info.userID.Equals(t.SubJobID) && t.IsUnBind == false ).FirstAsync();
if (bindUser == null) return MessageModel.Fail("用户不存在或者已经解绑!");
WeChatResponseUserInfo reData = new WeChatResponseUserInfo();
reData.companyCode = info.companyCode;
reData.id = info.id;
bindUser.IsUnBind = true;
bindUser.SubUserRefTime = DateTime.Now;
await BaseDal.Db.Updateable(bindUser).UpdateColumns(t=> new{ t.IsUnBind,t.SubUserRefTime}).ExecuteCommandAsync();
return MessageModel.Success("用户解绑成功", reData);
}
public async Task HandleWeChat(WeChatXMLDto weChat)
{
switch (weChat.MsgType)
{
case "text":
return await HandText(weChat);
case "image":
return await HandImage(weChat);
case "voice":
return await HandVoice(weChat);
case "shortvideo":
return await HandShortvideo(weChat);
case "location":
return await HandLocation(weChat);
case "link":
return await HandLink(weChat);
case "event":
return await HandEvent(weChat);
default:
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
{weChat.MsgType}]]>";
});
}
}
///
/// 处理文本
///
///
///
private async Task HandText(WeChatXMLDto weChat)
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
{weChat.Content}]]>";
});
}
///
/// 处理图片
///
///
///
private async Task HandImage(WeChatXMLDto weChat)
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
{weChat.PicUrl}]]>";
});
}
///
/// 处理声音
///
///
///
private async Task HandVoice(WeChatXMLDto weChat)
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
{weChat.MediaId}]]>";
});
}
///
/// 处理小视频
///
///
///
private async Task HandShortvideo(WeChatXMLDto weChat)
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
{weChat.MediaId}]]>";
});
}
///
/// 处理地理位置
///
///
///
private async Task HandLocation(WeChatXMLDto weChat)
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
{weChat.Label}]]>";
});
}
///
/// 处理链接消息
///
///
///
private async Task HandLink(WeChatXMLDto weChat)
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
{weChat.Url}]]>";
});
}
///
/// 处理事件
///
///
///
private async Task HandEvent(WeChatXMLDto weChat)
{
switch (weChat.Event)
{
case "subscribe":
return await EventSubscribe(weChat);
case "unsubscribe":
return await EventUnsubscribe(weChat);
case "SCAN":
return await EventSCAN(weChat);
case "LOCATION":
return await EventLOCATION(weChat);
case "CLICK":
return await EventCLICK(weChat);
case "VIEW":
return await EventVIEW(weChat);
default:
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
{weChat.Event}]]>";
});
}
}
///
/// 关注事件
///
///
///
private async Task EventSubscribe(WeChatXMLDto weChat)
{
if (weChat.EventKey != null && (weChat.EventKey.Equals("bind") || weChat.EventKey.Equals("qrscene_bind")))
{
return await QRBind(weChat);
}
else
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
key:{weChat.EventKey}=>ticket:{weChat.Ticket}]]>";
});
}
}
///
/// 取消关注事件
///
///
///
private async Task EventUnsubscribe(WeChatXMLDto weChat)
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
{weChat.Event}]]>";
});
}
///
/// 已关注扫码事件
///
///
///
private async Task EventSCAN(WeChatXMLDto weChat)
{
if (weChat.EventKey != null && (weChat.EventKey.StartsWith("bind_") || weChat.EventKey.StartsWith("qrscene_bind_")))
{
return await QRBind(weChat);
}
else
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
key:{weChat.EventKey}=>ticket:{weChat.Ticket}]]>";
});
}
}
///
/// 扫码绑定
///
///
///
private async Task QRBind(WeChatXMLDto weChat)
{
var ticket = await BaseDal.Db.Queryable().InSingleAsync(weChat.Ticket);
if (ticket == null) throw new Exception("ticket未找到");
if (ticket.QRisUsed) throw new Exception("ticket已被使用");
if (!ticket.QRpublicAccount.Equals(weChat.publicAccount)) throw new Exception($"公众号错误 need:{ticket.QRpublicAccount} but:{weChat.publicAccount}");
var bindUser = await BaseDal.Db.Queryable().Where(t => t.SubFromPublicAccount == ticket.QRpublicAccount && t.CompanyID == ticket.QRbindCompanyID && t.SubJobID == ticket.QRbindJobID).SingleAsync();
bool isNewBind;
if (bindUser == null )
{
isNewBind = true;
bindUser = new WeChatSub
{
SubFromPublicAccount = ticket.QRpublicAccount,
CompanyID = ticket.QRbindCompanyID,
SubJobID = ticket.QRbindJobID,
SubUserOpenID = weChat.FromUserName,
SubUserRegTime = DateTime.Now,
};
}
else
{
isNewBind = false;
//订阅过的就更新
if (bindUser.SubUserOpenID != weChat.FromUserName)
{
//记录上一次的订阅此工号的微信号
bindUser.LastSubUserOpenID = bindUser.SubUserOpenID;
}
bindUser.SubUserOpenID = weChat.FromUserName;
bindUser.SubUserRefTime = DateTime.Now;
bindUser.IsUnBind = false;
}
ticket.QRisUsed = true;
ticket.QRuseTime = DateTime.Now;
ticket.QRuseOpenid = weChat.FromUserName;
try
{
_unitOfWorkManage.BeginTran();
await BaseDal.Db.Updateable(ticket).ExecuteCommandAsync();
if (isNewBind)
await BaseDal.Db.Insertable(bindUser).ExecuteCommandAsync();
else
await BaseDal.Db.Updateable(bindUser).ExecuteCommandAsync();
_unitOfWorkManage.CommitTran();
}
catch
{
_unitOfWorkManage.RollbackTran();
throw;
}
return @$"
{DateTime.Now.Ticks.ToString()}
";
}
///
/// 上报位置地理事件
///
///
///
private async Task EventLOCATION(WeChatXMLDto weChat)
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
维度:{weChat.Latitude}经度:{weChat.Longitude}位置精度:{weChat.Precision}]]>";
});
}
///
/// 点击菜单按钮事件
///
///
///
private async Task EventCLICK(WeChatXMLDto weChat)
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
{weChat.EventKey}]]>";
});
}
///
/// 点击菜单网址事件
///
///
///
private async Task EventVIEW(WeChatXMLDto weChat)
{
return await Task.Run(() =>
{
return @$"
{DateTime.Now.Ticks.ToString()}
{weChat.EventKey}]]>";
});
}
}
}