You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

671 lines
34 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*----------------------------------------------------------------
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
{
/// <summary>
/// 自定义MessageHandler
/// 把MessageHandler作为基类重写对应请求的处理方法
/// </summary>
public partial class CustomMessageHandler : MessageHandler<CustomMessageContext> /*如果不需要自定义可以直接使用MessageHandler<DefaultMpMessageContext> */
{
/*
* 重要提示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;
/// <summary>
/// 为中间件提供生成当前类的委托
/// </summary>
public static Func<Stream, PostModel, int, IServiceProvider, CustomMessageHandler> GenerateMessageHandler = (stream, postModel, maxRecordCount, serviceProvider)
=> new CustomMessageHandler(stream, postModel, maxRecordCount, false /* 是否只允许处理加密消息,以提高安全性 */, serviceProvider: serviceProvider);
/// <summary>
/// 自定义 MessageHandler
/// </summary>
/// <param name="provider">.NET Framework 可忽略</param>
/// <param name="inputStream"></param>
/// <param name="postModel"></param>
/// <param name="maxRecordCount"></param>
/// <param name="onlyAllowEncryptMessage"></param>
public CustomMessageHandler(Stream inputStream, PostModel postModel, int maxRecordCount = 0, bool onlyAllowEncryptMessage = false, IServiceProvider serviceProvider = null)
: base(inputStream, postModel, maxRecordCount, onlyAllowEncryptMessage, serviceProvider: serviceProvider)
{
//这里设置仅用于测试,实际开发可以在外部更全局的地方设置,
//比如MessageHandler<MessageContext>.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;
};
}
/// <summary>
/// 处理文字请求
/// </summary>
/// <param name="requestMessage">请求消息</param>
/// <returns></returns>
public override async Task<IResponseMessageBase> OnTextRequestAsync(RequestMessageText requestMessage)
{
//说明实际项目中这里的逻辑可以交给Service处理具体信息参考OnLocationRequest方法或/Service/LocationSercice.cs
#region 书中例子
//if (requestMessage.Content == "你好")
//{
// var responseMessage = base.CreateResponseMessage<ResponseMessageNews>();
// 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<ResponseMessageText>(RequestMessage);
//方法三v0.4扩展方法需要using Senparc.Weixin.MP.Helpers;
//var responseMessage = RequestMessage.CreateResponseMessage<ResponseMessageText>();
//方法四v0.6+仅适合在HandlerMessage内部使用本质上是对方法三的封装
//注意下面泛型ResponseMessageText即返回给客户端的类型可以根据自己的需要填写ResponseMessageNews等不同类型。
#endregion
var defaultResponseMessage = base.CreateResponseMessage<ResponseMessageText>();
var requestHandler = await requestMessage.StartHandler()
//关键字不区分大小写,按照顺序匹配成功后将不再运行下面的逻辑
.Keyword("约束", () =>
{
defaultResponseMessage.Content =
@"您正在进行微信内置浏览器约束判断测试。您可以:
<a href=""https://sdk.weixin.senparc.com/FilterTest/"">点击这里</a>进行客户端约束测试地址https://sdk.weixin.senparc.com/FilterTest/),如果在微信外打开将直接返回文字。
或:
<a href=""https://sdk.weixin.senparc.com/FilterTest/Redirect"">点击这里</a>进行客户端约束测试地址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<ResponseMessageNews>();
openResponseMessage.Articles.Add(new Article()
{
Title = "开放平台微信授权测试!",
Description = @"点击进入Open授权页面。
授权之后,您的微信所收到的消息将转发到第三方(盛派网络小助手)的服务器上,并获得对应的回复。
测试完成后,您可以登陆公众号后台取消授权。",
Url = "https://sdk.weixin.senparc.com/OpenOAuth/JumpToMpOAuth"
});
return openResponseMessage;
})
.Keyword("错误", () =>
{
var errorResponseMessage = requestMessage.CreateResponseMessage<ResponseMessageText>();
//因为没有设置errorResponseMessage.Content所以这小消息将无法正确返回。
return errorResponseMessage;
})
.Keyword("容错", () =>
{
Thread.Sleep(4900);//故意延时1.5秒,让微信多次发送消息过来,观察返回结果
var faultTolerantResponseMessage = requestMessage.CreateResponseMessage<ResponseMessageText>();
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日起公众号无法直接获取用户昵称、性别、地区等信息如需获取相关信息需要使用<a href=\"https://sdk.weixin.senparc.com/oauth2?returnUrl=%2FOAuth2%2FTestReturnUrl\">OAuth 2.0 接口</a>。",
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<ResponseMessageNoResponse>();
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})!我们需要您的意见或建议,欢迎向我们反馈! <a href=\"https://weixin.senparc.com/QA\">点击这里</a>";
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<IHttpContextAccessor>();
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;
}
/// <summary>
/// 处理位置请求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override async Task<IResponseMessageBase> OnLocationRequestAsync(RequestMessageLocation requestMessage)
{
var locationService = new LocationService();
var responseMessage = locationService.GetResponseMessage(requestMessage as RequestMessageLocation);
return responseMessage;
}
public override async Task<IResponseMessageBase> OnShortVideoRequestAsync(RequestMessageShortVideo requestMessage)
{
var responseMessage = this.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = "您刚才发送的是小视频";
return responseMessage;
}
/// <summary>
/// 处理图片请求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override async Task<IResponseMessageBase> OnImageRequestAsync(RequestMessageImage requestMessage)
{
//一隔一返回News或Image格式
if (base.GlobalMessageContext.GetMessageContext(requestMessage).RequestMessages.Count() % 2 == 0)
{
var responseMessage = CreateResponseMessage<ResponseMessageNews>();
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<ResponseMessageImage>();
responseMessage.Image.MediaId = requestMessage.MediaId;
return responseMessage;
}
}
/// <summary>
/// 处理语音请求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override async Task<IResponseMessageBase> OnVoiceRequestAsync(RequestMessageVoice requestMessage)
{
var responseMessage = CreateResponseMessage<ResponseMessageMusic>();
//上传缩略图
//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;
}
/// <summary>
/// 处理视频请求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override async Task<IResponseMessageBase> OnVideoRequestAsync(RequestMessageVideo requestMessage)
{
var responseMessage = CreateResponseMessage<ResponseMessageText>();
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;
}
/// <summary>
/// 处理链接消息请求
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override async Task<IResponseMessageBase> OnLinkRequestAsync(RequestMessageLink requestMessage)
{
var responseMessage = ResponseMessageBase.CreateFromRequestMessage<ResponseMessageText>(requestMessage);
responseMessage.Content = string.Format(@"您发送了一条连接信息:
Title{0}
Description:{1}
Url:{2}", requestMessage.Title, requestMessage.Description, requestMessage.Url);
return responseMessage;
}
public override async Task<IResponseMessageBase> OnFileRequestAsync(RequestMessageFile requestMessage)
{
var responseMessage = requestMessage.CreateResponseMessage<ResponseMessageText>();
responseMessage.Content = string.Format(@"您发送了一个文件:
文件名:{0}
说明:{1}
大小:{2}
MD5:{3}", requestMessage.Title, requestMessage.Description, requestMessage.FileTotalLen, requestMessage.FileMd5);
return responseMessage;
}
/// <summary>
/// 处理事件请求这个方法一般不用重写这里仅作为示例出现。除非需要在判断具体Event类型以外对Event信息进行统一操作
/// </summary>
/// <param name="requestMessage"></param>
/// <returns></returns>
public override async Task<IResponseMessageBase> 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<ResponseMessageText>();
responseMessage.Content = $"这条消息来自DefaultResponseMessage。\r\n您收到这条消息表明该公众号没有对【{requestMessage.MsgType}】类型做处理。";
return responseMessage;
}
public override async Task<IResponseMessageBase> 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<ResponseMessageText>();
responseMessage.Content = "未知消息类型:" + msgType;
WeixinTrace.SendCustomLog("未知请求消息类型", requestMessage.RequestDocument.ToString());//记录到日志中
return responseMessage;
}
}
}