using BotSharp.Channel.Weixin.Models;
using BotSharp.Platform.Abstraction;
using BotSharp.Platform.Dialogflow.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Senparc.CO2NET.HttpUtility;
using Senparc.Weixin.MP;
using Senparc.Weixin.MP.Entities.Request;
using Senparc.Weixin.MP.MvcExtension;
using System;
using System.IO;
using System.Threading.Tasks;
namespace BotSharp.Channel.Weixin.Controllers
{
///
/// 此Controller为异步Controller(Action),使用异步线程处理并发请求。
/// 为了方便演示,此Controller中没有加入多余的日志记录等示例,保持了最简单的Controller写法。日志等其他操作可以参考WeixinController.cs。
/// 提示:异步Controller并不是在任何情况下都能提升效率(响应时间),当请求量非常小的时候反而会增加一定的开销。
///
[Route("weixin")]
public class WeixinAsyncController : ControllerBase
{
readonly Func _getRandomFileName = () => DateTime.Now.ToString("yyyyMMdd-HHmmss") + "_Async_" + Guid.NewGuid().ToString("n").Substring(0, 6);
readonly IConfiguration config;
private IPlatformBuilder builder;
public WeixinAsyncController(IPlatformBuilder platform, IConfiguration configuration)
{
config = configuration;
builder = platform;
}
[HttpGet]
public Task Get(string signature, string timestamp, string nonce, string echostr)
{
var token = config.GetValue("weixinChannel:token");
return Task.Factory.StartNew(() =>
{
if (CheckSignature.Check(signature, timestamp, nonce, token))
{
return echostr; //返回随机字符串则表示验证通过
}
else
{
return "failed:" + signature + "," + Senparc.Weixin.MP.CheckSignature.GetSignature(timestamp, nonce, token) + "。" +
"如果你在浏览器中看到这句话,说明此地址可以被作为微信公众账号后台的Url,请注意保持Token一致。";
}
}).ContinueWith(task => Content(task.Result));
}
public CustomMessageHandler MessageHandler = null;//开放出MessageHandler是为了做单元测试,实际使用过程中不需要
///
/// 最简化的处理流程
///
[HttpPost]
public async Task Post(PostModel postModel)
{
var token = config.GetValue("weixinChannel:token");
if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, token))
{
return new WeixinResult("参数错误!");
}
postModel.Token = token;
postModel.EncodingAESKey = config.GetValue("weixinChannel:encodingAESKey");
postModel.AppId = config.GetValue("weixinChannel:appId");
var messageHandler = new CustomMessageHandler(builder, config, Request.GetRequestMemoryStream(), postModel, 10);
messageHandler.DefaultMessageHandlerAsyncEvent = Senparc.NeuChar.MessageHandlers.DefaultMessageHandlerAsyncEvent.SelfSynicMethod;//没有重写的异步方法将默认尝试调用同步方法中的代码(为了偷懒)
#region 设置消息去重
/* 如果需要添加消息去重功能,只需打开OmitRepeatedMessage功能,SDK会自动处理。
* 收到重复消息通常是因为微信服务器没有及时收到响应,会持续发送2-5条不等的相同内容的RequestMessage*/
messageHandler.OmitRepeatedMessage = true;//默认已经开启,此处仅作为演示,也可以设置为false在本次请求中停用此功能
#endregion
#region 记录 Request 日志
var logPath = Server.GetMapPath(string.Format("~/App_Data/MP/{0}/", DateTime.Now.ToString("yyyy-MM-dd")));
if (!Directory.Exists(logPath))
{
Directory.CreateDirectory(logPath);
}
//测试时可开启此记录,帮助跟踪数据,使用前请确保App_Data文件夹存在,且有读写权限。
messageHandler.RequestDocument.Save(Path.Combine(logPath, string.Format("{0}_Request_{1}_{2}.txt", _getRandomFileName(),
messageHandler.RequestMessage.FromUserName,
messageHandler.RequestMessage.MsgType)));
if (messageHandler.UsingEcryptMessage)
{
messageHandler.EcryptRequestDocument.Save(Path.Combine(logPath, string.Format("{0}_Request_Ecrypt_{1}_{2}.txt", _getRandomFileName(),
messageHandler.RequestMessage.FromUserName,
messageHandler.RequestMessage.MsgType)));
}
#endregion
await messageHandler.ExecuteAsync(new System.Threading.CancellationToken()); //执行微信处理过程
#region 记录 Response 日志
//测试时可开启,帮助跟踪数据
//if (messageHandler.ResponseDocument == null)
//{
// throw new Exception(messageHandler.RequestDocument.ToString());
//}
if (messageHandler.ResponseDocument != null)
{
messageHandler.ResponseDocument.Save(Path.Combine(logPath, string.Format("{0}_Response_{1}_{2}.txt", _getRandomFileName(),
messageHandler.ResponseMessage.ToUserName,
messageHandler.ResponseMessage.MsgType)));
}
if (messageHandler.UsingEcryptMessage && messageHandler.FinalResponseDocument != null)
{
//记录加密后的响应信息
messageHandler.FinalResponseDocument.Save(Path.Combine(logPath, string.Format("{0}_Response_Final_{1}_{2}.txt", _getRandomFileName(),
messageHandler.ResponseMessage.ToUserName,
messageHandler.ResponseMessage.MsgType)));
}
#endregion
MessageHandler = messageHandler;//开放出MessageHandler是为了做单元测试,实际使用过程中不需要
return new FixWeixinBugWeixinResult(messageHandler);
}
}
}