/*----------------------------------------------------------------
Copyright (C) 2023 Senparc
文件名:CustomMessageHandler.cs
文件功能描述:微信公众号自定义MessageHandler
创建标识:Senparc - 20150312
修改标识:Senparc - 20171027
修改描述:v14.8.3 添加OnUnknownTypeRequest()方法Demo
修改标识:Senparc - 20191002
修改描述:v16.9.102 提供 MessageHandler 中间件
----------------------------------------------------------------*/
//DPBMARK_FILE MP
using Senparc.CO2NET.Helpers;
using Senparc.CO2NET.Utilities;
using Senparc.NeuChar.Agents;
using Senparc.NeuChar.Entities;
using Senparc.NeuChar.Entities.Request;
using Senparc.NeuChar.Helpers;
using Senparc.Weixin.Exceptions;
using Senparc.Weixin.MP.AdvancedAPIs;
using Senparc.Weixin.MP.Entities;
using Senparc.Weixin.MP.Entities.Request;
using Senparc.Weixin.MP.MessageHandlers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using Senparc.CO2NET.Cache;
using Senparc.Weixin.MP;
#if NET462
using System.Web;
using System.Configuration;
using System.Web.Configuration;
#else
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
#endif
namespace Senparc.Weixin.Sample.CommonService.CustomMessageHandler
{
///
/// 自定义MessageHandler
/// 把MessageHandler作为基类,重写对应请求的处理方法
///
public partial class CustomMessageHandler : MessageHandler /*如果不需要自定义,可以直接使用:MessageHandler */
{
/*
* 重要提示:v1.5起,MessageHandler提供了一个DefaultResponseMessage的抽象方法,
* DefaultResponseMessage必须在子类中重写,用于返回没有处理过的消息类型(也可以用于默认消息,如帮助信息等);
* 其中所有原OnXX的抽象方法已经都改为虚方法,可以不必每个都重写。若不重写,默认返回DefaultResponseMessage方法中的结果。
*/
#if !DEBUG || NETSTANDARD2_0_OR_GREATER || NETCOREAPP2_1_OR_GREATER || NET6_0_OR_GREATER
string agentUrl = "http://localhost:12222/App/Weixin/4";
string agentToken = "27C455F496044A87";
string wiweihiKey = "CNadjJuWzyX5bz5Gn+/XoyqiqMa5DjXQ";
#else
//下面的Url和Token可以用其他平台的消息,或者到www.weiweihi.com注册微信用户,将自动在“微信营销工具”下得到
private string agentUrl = Config.SenparcWeixinSetting.AgentUrl;//这里使用了www.weiweihi.com微信自动托管平台
private string agentToken = Config.SenparcWeixinSetting.AgentToken;//Token
private string wiweihiKey = Config.SenparcWeixinSetting.SenparcWechatAgentKey;//WeiweihiKey专门用于对接www.Weiweihi.com平台,获取方式见:http://www.weiweihi.com/ApiDocuments/Item/25#51
#endif
private string appId = Config.SenparcWeixinSetting.WeixinAppId;
private string appSecret = Config.SenparcWeixinSetting.WeixinAppSecret;
///
/// 为中间件提供生成当前类的委托
///
public static Func GenerateMessageHandler = (stream, postModel, maxRecordCount, serviceProvider)
=> new CustomMessageHandler(stream, postModel, maxRecordCount, false /* 是否只允许处理加密消息,以提高安全性 */, serviceProvider: serviceProvider);
///
/// 自定义 MessageHandler
///
/// .NET Framework 可忽略
///
///
///
///
public CustomMessageHandler(Stream inputStream, PostModel postModel, int maxRecordCount = 0, bool onlyAllowEncryptMessage = false, IServiceProvider serviceProvider = null)
: base(inputStream, postModel, maxRecordCount, onlyAllowEncryptMessage, serviceProvider: serviceProvider)
{
//这里设置仅用于测试,实际开发可以在外部更全局的地方设置,
//比如MessageHandler.GlobalGlobalMessageContext.ExpireMinutes = 3。
GlobalMessageContext.ExpireMinutes = 3;
OnlyAllowEncryptMessage = true;//是否只允许接收加密消息,默认为 false
if (!string.IsNullOrEmpty(postModel.AppId))
{
appId = postModel.AppId;//通过第三方开放平台发送过来的请求
}
//在指定条件下,不使用消息去重
base.OmitRepeatedMessageFunc = requestMessage =>
{
var textRequestMessage = requestMessage as RequestMessageText;
if (textRequestMessage != null && textRequestMessage.Content == "容错")
{
return false;
}
return true;
};
}
///
/// 处理文字请求
///
/// 请求消息
///
public override async Task OnTextRequestAsync(RequestMessageText requestMessage)
{
//说明:实际项目中这里的逻辑可以交给Service处理具体信息,参考OnLocationRequest方法或/Service/LocationSercice.cs
#region 书中例子
//if (requestMessage.Content == "你好")
//{
// var responseMessage = base.CreateResponseMessage();
// var title = "Title";
// var description = "Description";
// var picUrl = "PicUrl";
// var url = "Url";
// responseMessage.Articles.Add(new Article()
// {
// Title = title,
// Description = description,
// PicUrl = picUrl,
// Url = url
// });
// return responseMessage;
//}
//else if (requestMessage.Content == "Senparc")
//{
// //相似处理逻辑
//}
//else
//{
// //...
//}
#endregion
#region 历史方法
//方法一(v0.1),此方法调用太过繁琐,已过时(但仍是所有方法的核心基础),建议使用方法二到四
//var responseMessage =
// ResponseMessageBase.CreateFromRequestMessage(RequestMessage, ResponseMsgType.Text) as
// ResponseMessageText;
//方法二(v0.4)
//var responseMessage = ResponseMessageBase.CreateFromRequestMessage(RequestMessage);
//方法三(v0.4),扩展方法,需要using Senparc.Weixin.MP.Helpers;
//var responseMessage = RequestMessage.CreateResponseMessage();
//方法四(v0.6+),仅适合在HandlerMessage内部使用,本质上是对方法三的封装
//注意:下面泛型ResponseMessageText即返回给客户端的类型,可以根据自己的需要填写ResponseMessageNews等不同类型。
#endregion
var defaultResponseMessage = base.CreateResponseMessage();
var requestHandler = await requestMessage.StartHandler()
//关键字不区分大小写,按照顺序匹配成功后将不再运行下面的逻辑
.Keyword("约束", () =>
{
defaultResponseMessage.Content =
@"您正在进行微信内置浏览器约束判断测试。您可以:
点击这里进行客户端约束测试(地址:https://sdk.weixin.senparc.com/FilterTest/),如果在微信外打开将直接返回文字。
或:
点击这里进行客户端约束测试(地址:https://sdk.weixin.senparc.com/FilterTest/Redirect),如果在微信外打开将重定向一次URL。";
return defaultResponseMessage;
}).
//匹配任一关键字
Keywords(new[] { "托管", "代理" }, () =>
{
//开始用代理托管,把请求转到其他服务器上去,然后拿回结果
//甚至也可以将所有请求在DefaultResponseMessage()中托管到外部。
var dt1 = SystemTime.Now; //计时开始
var agentXml = RequestDocument.ToString();
#region 暂时转发到SDK线上Demo
agentUrl = "https://sdk.weixin.senparc.com/weixin";
//agentToken = WebConfigurationManager.AppSettings["WeixinToken"];//Token
//修改内容,防止死循环
var agentDoc = XDocument.Parse(agentXml);
agentDoc.Root.Element("Content").SetValue("代理转发文字:" + requestMessage.Content);
agentDoc.Root.Element("CreateTime").SetValue(DateTimeHelper.GetUnixDateTime(SystemTime.Now));//修改时间,防止去重
agentDoc.Root.Element("MsgId").SetValue("123");//防止去重
agentXml = agentDoc.ToString();
#endregion
var responseXml = MessageAgent.RequestXml(this,
#if NET462
null,
#else
Senparc.CO2NET.SenparcDI.GetServiceProvider(),
#endif
agentUrl, agentToken, agentXml);
//获取返回的XML
//上面的方法也可以使用扩展方法:this.RequestResponseMessage(this,agentUrl, agentToken, RequestDocument.ToString());
/* 如果有WeiweihiKey,可以直接使用下面的这个MessageAgent.RequestWeiweihiXml()方法。
* WeiweihiKey专门用于对接www.weiweihi.com平台,获取方式见:https://www.weiweihi.com/ApiDocuments/Item/25#51
*/
//var responseXml = MessageAgent.RequestWeiweihiXml(weiweihiKey, RequestDocument.ToString());//获取Weiweihi返回的XML
var dt2 = SystemTime.Now; //计时结束
//转成实体。
/* 如果要写成一行,可以直接用:
* responseMessage = MessageAgent.RequestResponseMessage(agentUrl, agentToken, RequestDocument.ToString());
* 或
*
*/
var msg = string.Format("\r\n\r\n代理过程总耗时:{0}毫秒", (dt2 - dt1).Milliseconds);
var agentResponseMessage = responseXml.CreateResponseMessage(this.MessageEntityEnlightener);
if (agentResponseMessage is ResponseMessageText)
{
(agentResponseMessage as ResponseMessageText).Content += msg;
}
else if (agentResponseMessage is ResponseMessageNews)
{
(agentResponseMessage as ResponseMessageNews).Articles[0].Description += msg;
}
return agentResponseMessage;//可能出现多种类型,直接在这里返回
})
.Keywords(new[] { "测试", "退出" }, () =>
{
/*
* 这是一个特殊的过程,此请求通常来自于微微嗨(http://www.weiweihi.com)的“盛派网络小助手”应用请求(https://www.weiweihi.com/User/App/Detail/1),
* 用于演示微微嗨应用商店的处理过程,由于微微嗨的应用内部可以单独设置对话过期时间,所以这里通常不需要考虑对话状态,只要做最简单的响应。
*/
if (defaultResponseMessage.Content == "测试")
{
//进入APP测试
defaultResponseMessage.Content = "您已经进入【盛派网络小助手】的测试程序,请发送任意信息进行测试。发送文字【退出】退出测试对话。10分钟内无任何交互将自动退出应用对话状态。";
}
else
{
//退出APP测试
defaultResponseMessage.Content = "您已经退出【盛派网络小助手】的测试程序。";
}
return defaultResponseMessage;
})
.Keyword("AsyncTest", () =>
{
//异步并发测试(提供给单元测试使用)
#if NET462
var begin = SystemTime.Now;
int t1, t2, t3;
System.Threading.ThreadPool.GetAvailableThreads(out t1, out t3);
System.Threading.ThreadPool.GetMaxThreads(out t2, out t3);
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(4));
var end = SystemTime.Now;
var thread = System.Threading.Thread.CurrentThread;
defaultResponseMessage.Content = string.Format("TId:{0}\tApp:{1}\tBegin:{2:mm:ss,ffff}\tEnd:{3:mm:ss,ffff}\tTPool:{4}",
thread.ManagedThreadId,
HttpContext.Current != null ? HttpContext.Current.ApplicationInstance.GetHashCode() : -1,
begin,
end,
t2 - t1
);
#endif
return defaultResponseMessage;
})
.Keyword("OPEN", () =>
{
var openResponseMessage = requestMessage.CreateResponseMessage();
openResponseMessage.Articles.Add(new Article()
{
Title = "开放平台微信授权测试!",
Description = @"点击进入Open授权页面。
授权之后,您的微信所收到的消息将转发到第三方(盛派网络小助手)的服务器上,并获得对应的回复。
测试完成后,您可以登陆公众号后台取消授权。",
Url = "https://sdk.weixin.senparc.com/OpenOAuth/JumpToMpOAuth"
});
return openResponseMessage;
})
.Keyword("错误", () =>
{
var errorResponseMessage = requestMessage.CreateResponseMessage();
//因为没有设置errorResponseMessage.Content,所以这小消息将无法正确返回。
return errorResponseMessage;
})
.Keyword("容错", () =>
{
Thread.Sleep(4900);//故意延时1.5秒,让微信多次发送消息过来,观察返回结果
var faultTolerantResponseMessage = requestMessage.CreateResponseMessage();
faultTolerantResponseMessage.Content = string.Format("测试容错,MsgId:{0},Ticks:{1}", requestMessage.MsgId,
SystemTime.Now.Ticks);
return faultTolerantResponseMessage;
})
.Keyword("TM", () =>
{
var openId = requestMessage.FromUserName;
var checkCode = Guid.NewGuid().ToString("n").Substring(0, 3);//为了防止openId泄露造成骚扰,这里启用验证码
Task.Factory.StartNew(async () =>
{
var currentCache = CacheStrategyFactory.GetObjectCacheStrategyInstance();
await currentCache.SetAsync($"TestCheckCode:{checkCode}", openId, TimeSpan.FromHours(1));//使用缓存,如果多台服务器可以使用分布式缓存共享
}).Wait();
defaultResponseMessage.Content = string.Format(@"新的验证码为:{0},请在网页上输入。网址:https://sdk.weixin.senparc.com/AsyncMethods", checkCode);
return defaultResponseMessage;
})
.Keyword("OPENID", () =>
{
var openId = requestMessage.FromUserName;//获取OpenId
var userInfo = MP.AdvancedAPIs.UserApi.Info(appId, openId, Language.zh_CN);
defaultResponseMessage.Content = string.Format(
"您的OpenID为:{0}\r\n昵称:{1}\r\n性别:{2}\r\n地区(国家/省/市):{3}/{4}/{5}\r\n关注时间:{6}\r\n关注状态:{7}\r\n\r\n说明:从2021年12月27日起,公众号无法直接获取用户昵称、性别、地区等信息,如需获取相关信息,需要使用OAuth 2.0 接口。",
requestMessage.FromUserName, userInfo.nickname, (WeixinSex)userInfo.sex, userInfo.country, userInfo.province, userInfo.city, DateTimeHelper.GetDateTimeFromXml(userInfo.subscribe_time), userInfo.subscribe);
return defaultResponseMessage;
})
.Keyword("EX", () =>
{
var ex = new WeixinException("openid:" + requestMessage.FromUserName + ":这是一条测试异常信息");//回调过程在global的ConfigWeixinTraceLog()方法中
defaultResponseMessage.Content = "请等待异步模板消息发送到此界面上(自动延时数秒)。\r\n当前时间:" + SystemTime.Now.ToString();
return defaultResponseMessage;
})
.Keyword("MUTE", () => //不回复任何消息
{
//方案一:
return new SuccessResponseMessage();
//方案二:
var muteResponseMessage = base.CreateResponseMessage();
return muteResponseMessage;
//方案三:
base.TextResponseMessage = "success";
return null;
//方案四:
return null;//在 Action 中结合使用 return new FixWeixinBugWeixinResult(messageHandler);
})
.Keyword("JSSDK", () =>
{
defaultResponseMessage.Content = "点击打开:https://sdk.weixin.senparc.com/WeixinJsSdk";
return defaultResponseMessage;
})
//选择菜单,关键字:101(微信服务器端最终格式:id="s:101",content="满意")
.SelectMenuKeyword("101", () =>
{
defaultResponseMessage.Content = $"感谢您的评价({requestMessage.Content})!我们会一如既往为提高企业和开发者生产力而努力!";
return defaultResponseMessage;
})
//选择菜单,关键字:102(微信服务器端最终格式:id="s:102",content="一般")
.SelectMenuKeyword("102", () =>
{
defaultResponseMessage.Content = $"感谢您的评价({requestMessage.Content})!希望我们的服务能让您越来越满意!";
return defaultResponseMessage;
})
//选择菜单,关键字:103(微信服务器端最终格式:id="s:103",content="不满意")
.SelectMenuKeyword("103", () =>
{
defaultResponseMessage.Content = $"感谢您的评价({requestMessage.Content})!我们需要您的意见或建议,欢迎向我们反馈! 点击这里";
return defaultResponseMessage;
})
.SelectMenuKeywords(new[] { "110", "111" }, () =>
{
defaultResponseMessage.Content = $"这里只是演示,可以同时支持多个选择菜单";
return defaultResponseMessage;
})
//“一次订阅消息”接口测试
.Keyword("订阅", () =>
{
defaultResponseMessage.Content = "点击打开:https://sdk.weixin.senparc.com/SubscribeMsg";
return defaultResponseMessage;
})
//正则表达式
.Regex(@"^\d+#\d+$", () =>
{
defaultResponseMessage.Content = string.Format("您输入了:{0},符合正则表达式:^\\d+#\\d+$", requestMessage.Content);
return defaultResponseMessage;
})
//ServiceProvider
.Keyword("SP", () =>
{
if (base.ServiceProvider == null)
{
defaultResponseMessage.Content = "ServiceProvider 为 null";
}
else
{
#if !NET462
var httpContextAccessor = base.ServiceProvider.GetService();
defaultResponseMessage.Content = $"ServiceProvider 载入成功,从 IHttpContextAccessor 读取当前服务器协议:{httpContextAccessor.HttpContext.Request.Scheme}";
#endif
}
return defaultResponseMessage;
})
//企业微信审批
.Keyword("审批", () =>
{
MP.AdvancedAPIs.CustomApi.SendText(appId, OpenId, "请将下方地址在企业微信内打开(如果您还没有加入企业微信测试账号,可在QQ群内联系管理员申请):");
defaultResponseMessage.Content = "https://sdk.weixin.senparc.com/Work/Approval";
return defaultResponseMessage;
})
//当 Default 使用异步方法时,需要写在最后一个,且 requestMessage.StartHandler() 前需要使用 await 等待异步方法执行;
//当 Default 使用同步方法,不一定要在最后一个,并且不需要使用 await
.Default(async () =>
{
var result = new StringBuilder();
result.AppendFormat("您刚才发送了文字信息:{0}\r\n\r\n", requestMessage.Content);
var currentMessageContext = await base.GetCurrentMessageContext();
if (currentMessageContext.RequestMessages.Count > 1)
{
result.AppendFormat("您此前还发送了如下消息({0}/{1}):\r\n", currentMessageContext.RequestMessages.Count,
currentMessageContext.StorageData);
for (int i = currentMessageContext.RequestMessages.Count - 2; i >= 0; i--)
{
var historyMessage = currentMessageContext.RequestMessages[i];
result.AppendFormat("{0} 【{1}】{2}\r\n",
historyMessage.CreateTime.ToString("HH:mm:ss"),
historyMessage.MsgType.ToString(),
(historyMessage is RequestMessageText)
? (historyMessage as RequestMessageText).Content
: $"[非文字类型{((historyMessage is IRequestMessageEventKey eventKey) ? $"-{eventKey.EventKey}" : "")}]"
);
}
result.AppendLine("\r\n");
}
result.AppendFormat("如果您在{0}分钟内连续发送消息,记录将被自动保留(当前设置:最多记录{1}条)。过期后记录将会自动清除。\r\n",
GlobalMessageContext.ExpireMinutes, GlobalMessageContext.MaxRecordCount);
result.AppendLine("\r\n");
result.AppendLine(
"您还可以发送【位置】【图片】【语音】【视频】等类型的信息(注意是这几种类型,不是这几个文字),查看不同格式的回复。\r\nSDK官方地址:https://sdk.weixin.senparc.com");
defaultResponseMessage.Content = result.ToString();
return defaultResponseMessage;
});
return requestHandler.GetResponseMessage() as IResponseMessageBase;
}
///
/// 处理位置请求
///
///
///
public override async Task OnLocationRequestAsync(RequestMessageLocation requestMessage)
{
var locationService = new LocationService();
var responseMessage = locationService.GetResponseMessage(requestMessage as RequestMessageLocation);
return responseMessage;
}
public override async Task OnShortVideoRequestAsync(RequestMessageShortVideo requestMessage)
{
var responseMessage = this.CreateResponseMessage();
responseMessage.Content = "您刚才发送的是小视频";
return responseMessage;
}
///
/// 处理图片请求
///
///
///
public override async Task OnImageRequestAsync(RequestMessageImage requestMessage)
{
//一隔一返回News或Image格式
if (base.GlobalMessageContext.GetMessageContext(requestMessage).RequestMessages.Count() % 2 == 0)
{
var responseMessage = CreateResponseMessage();
responseMessage.Articles.Add(new Article()
{
Title = "您刚才发送了图片信息",
Description = "您发送的图片将会显示在边上",
PicUrl = requestMessage.PicUrl,
Url = "https://sdk.weixin.senparc.com"
});
responseMessage.Articles.Add(new Article()
{
Title = "第二条",
Description = "第二条带连接的内容",
PicUrl = requestMessage.PicUrl,
Url = "https://sdk.weixin.senparc.com"
});
return responseMessage;
}
else
{
var responseMessage = CreateResponseMessage();
responseMessage.Image.MediaId = requestMessage.MediaId;
return responseMessage;
}
}
///
/// 处理语音请求
///
///
///
public override async Task OnVoiceRequestAsync(RequestMessageVoice requestMessage)
{
var responseMessage = CreateResponseMessage();
//上传缩略图
//var accessToken = Containers.AccessTokenContainer.TryGetAccessToken(appId, appSecret);
var uploadResult = MP.AdvancedAPIs.MediaApi.UploadTemporaryMedia(appId, UploadMediaFileType.image,
ServerUtility.ContentRootMapPath("~/Images/Logo.jpg"));
//设置音乐信息
responseMessage.Music.Title = "天籁之音";
responseMessage.Music.Description = "播放您上传的语音";
responseMessage.Music.MusicUrl = "https://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId;
responseMessage.Music.HQMusicUrl = "https://sdk.weixin.senparc.com/Media/GetVoice?mediaId=" + requestMessage.MediaId;
responseMessage.Music.ThumbMediaId = uploadResult.media_id;
//推送一条客服消息
try
{
CustomApi.SendText(appId, OpenId, "本次上传的音频MediaId:" + requestMessage.MediaId);
}
catch
{
}
return responseMessage;
}
///
/// 处理视频请求
///
///
///
public override async Task OnVideoRequestAsync(RequestMessageVideo requestMessage)
{
var responseMessage = CreateResponseMessage();
responseMessage.Content = "您发送了一条视频信息,ID:" + requestMessage.MediaId;
#region 上传素材并推送到客户端
_ = Task.Factory.StartNew(async () =>
{
//上传素材
var dir = ServerUtility.ContentRootMapPath("~/App_Data/TempVideo/");
var file = await MediaApi.GetAsync(appId, requestMessage.MediaId, dir);
var uploadResult = await MediaApi.UploadTemporaryMediaAsync(appId, UploadMediaFileType.video, file, 50000);
await CustomApi.SendVideoAsync(appId, base.OpenId, uploadResult.media_id, "这是您刚才发送的视频", "这是一条视频消息");
}).ContinueWith(async task =>
{
if (task.Exception != null)
{
WeixinTrace.Log("OnVideoRequest()储存Video过程发生错误:", task.Exception.Message);
var msg = string.Format("上传素材出错:{0}\r\n{1}",
task.Exception.Message,
task.Exception.InnerException != null
? task.Exception.InnerException.Message
: null);
await CustomApi.SendTextAsync(appId, base.OpenId, msg);
}
});
#endregion
return responseMessage;
}
///
/// 处理链接消息请求
///
///
///
public override async Task OnLinkRequestAsync(RequestMessageLink requestMessage)
{
var responseMessage = ResponseMessageBase.CreateFromRequestMessage(requestMessage);
responseMessage.Content = string.Format(@"您发送了一条连接信息:
Title:{0}
Description:{1}
Url:{2}", requestMessage.Title, requestMessage.Description, requestMessage.Url);
return responseMessage;
}
public override async Task OnFileRequestAsync(RequestMessageFile requestMessage)
{
var responseMessage = requestMessage.CreateResponseMessage();
responseMessage.Content = string.Format(@"您发送了一个文件:
文件名:{0}
说明:{1}
大小:{2}
MD5:{3}", requestMessage.Title, requestMessage.Description, requestMessage.FileTotalLen, requestMessage.FileMd5);
return responseMessage;
}
///
/// 处理事件请求(这个方法一般不用重写,这里仅作为示例出现。除非需要在判断具体Event类型以外对Event信息进行统一操作
///
///
///
public override async Task OnEventRequestAsync(IRequestMessageEventBase requestMessage)
{
var eventResponseMessage = await base.OnEventRequestAsync(requestMessage);//对于Event下属分类的重写方法,见:CustomerMessageHandler_Events.cs
//TODO: 对Event信息进行统一操作
return eventResponseMessage;
}
public override IResponseMessageBase DefaultResponseMessage(IRequestMessageBase requestMessage)
{
/* 所有没有被处理的消息会默认返回这里的结果,
* 因此,如果想把整个微信请求委托出去(例如需要使用分布式或从其他服务器获取请求),
* 只需要在这里统一发出委托请求,如:
* var responseMessage = MessageAgent.RequestResponseMessage(agentUrl, agentToken, RequestDocument.ToString());
* return responseMessage;
*/
var responseMessage = this.CreateResponseMessage();
responseMessage.Content = $"这条消息来自DefaultResponseMessage。\r\n您收到这条消息,表明该公众号没有对【{requestMessage.MsgType}】类型做处理。";
return responseMessage;
}
public override async Task OnUnknownTypeRequestAsync(RequestMessageUnknownType requestMessage)
{
/*
* 此方法用于应急处理SDK没有提供的消息类型,
* 原始XML可以通过requestMessage.RequestDocument(或this.RequestDocument)获取到。
* 如果不重写此方法,遇到未知的请求类型将会抛出异常(v14.8.3 之前的版本就是这么做的)
*/
var msgType = Senparc.NeuChar.Helpers.MsgTypeHelper.GetRequestMsgTypeString(requestMessage.RequestDocument);
var responseMessage = this.CreateResponseMessage();
responseMessage.Content = "未知消息类型:" + msgType;
WeixinTrace.SendCustomLog("未知请求消息类型", requestMessage.RequestDocument.ToString());//记录到日志中
return responseMessage;
}
}
}