使用 Senparc 完成自动回复功能

使用 Senparc 完成自动回复功能

通讯流程理解

通过自动回复功能,可以理解微信服务器与网站之间的通讯过程:

  1. 用户在微信客户端向公众号发送消息
  2. 微信服务器将消息以 POST 请求转发到开发者配置的 URL
  3. 网站接收请求,验证签名,处理消息内容,返回响应

Post 接口实现

在 Controller 中添加 Post 类型的 Action,同样通过 http://weixin.foxdevelop.com/ 访问(与 Get 验证共用同一路由,通过 HTTP 方法区分)。

处理流程:

  1. 接收 PostModel 参数(微信服务器传入的签名、时间戳、随机数等)
  2. 调用 CheckSignature.Check() 验证请求来源
  3. PostModel 补充敏感信息(Token、EncodingAESKey、AppId),这些信息不会在网络上传播
  4. 创建自定义 MessageHandler 实例,传入请求流、PostModel 和最大记录数
  5. 调用 Execute() 执行处理过程
  6. 返回响应内容

Post 方法完整代码:

/// <summary>
/// 处理和微信服务器交互的接口,Post 方式
/// </summary>
[HttpPost]
[ActionName("Index")]
public ActionResult Post(PostModel postModel)
{
    if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, token))
    {
        Writelog("参数错误");
        return Content("参数错误!");
    }

    //以下保密信息不会(不应该)在网络上传播,请注意
    postModel.Token = token;
    postModel.EncodingAESKey = encodingAESKey;
    postModel.AppId = appId;

    //v4.2.2之后的版本,可以设置每个人上下文消息储存的最大数量,防止内存占用过多,如果该参数小于等于0,则不限制
    var maxRecordCount = 10;
    var messageHandler = new CustomMessageHandler(Request.InputStream, postModel, maxRecordCount);
    messageHandler.OmitRepeatedMessage = true; //默认已开启,也可设为false停用

    try
    {
        //执行微信处理过程
        messageHandler.Execute();
        Writelog("执行微信处理过程");
        if (messageHandler.ResponseMessage != null)
        {
            Writelog(messageHandler.ResponseDocument.ToString());
            return Content(messageHandler.ResponseDocument.ToString());
        }
        return Content("");
    }
    catch (Exception ex)
    {
        Writelog(ex.Message);
        return Content("");
    }
}Code language: PHP (php)

自定义 MessageHandler

创建 CustomMessageHandler 类,继承 MessageHandler<CustomMessageContext>,重写对应请求类型的处理方法。

核心逻辑:

  • 构造函数中设置上下文过期时间(如 3 分钟)
  • OnExecuting() / OnExecuted() 可处理请求前后逻辑
  • OnTextRequest() 处理文字消息,调用 GetReponse() 生成回复
  • GetReponse() 根据消息类型创建对应的 ResponseMessage

文字消息处理示例:

public override IResponseMessageBase OnTextRequest(RequestMessageText requestMessage)
{
    IResponseMessageBase responseMessage = null;
    if (requestMessage != null)
    {
        responseMessage = GetReponse(requestMessage);
    }
    return responseMessage;
}

protected IResponseMessageBase GetReponse(IRequestMessageBase requestMessage)
{
    switch ((ResponseMsgType)requestMessage.MsgType)
    {
        case ResponseMsgType.Text:
            {
                RequestMessageText requestMessageText = requestMessage as RequestMessageText;
                var strongResponseMessage = CreateResponseMessage<ResponseMessageText>();
                strongResponseMessage.Content = "您发的内容是:" + requestMessageText.Content;
                return strongResponseMessage;
            }
    }
    return null;
}Code language: PHP (php)

其他消息类型(图片、语音、视频、位置、链接等)均有对应的重写方法,未重写时默认返回 null,即不回复。

默认回复:

DefaultResponseMessage() 处理所有未被覆盖的消息类型,返回兜底回复内容。

消息上下文(CustomMessageContext)

继承 MessageContext<IRequestMessageBase, IResponseMessageBase>,用于管理用户会话状态。

可订阅 MessageContextRemoved 事件,在上下文过期时执行清理逻辑(如通知用户会话已超时)。

public class CustomMessageContext : MessageContext<IRequestMessageBase, IResponseMessageBase>
{
    public CustomMessageContext()
    {
        base.MessageContextRemoved += CustomMessageContext_MessageContextRemoved;
    }

    void CustomMessageContext_MessageContextRemoved(object sender, WeixinContextRemovedEventArgs<IRequestMessageBase, IResponseMessageBase> e)
    {
        //TODO: 执行消息过期时的逻辑,如发送退出提示
    }
}Code language: HTML, XML (xml)

注意:上下文过期清除并非实时触发,而是在下一条请求到达前由算法统一清理,以提高效率。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注