zoukankan      html  css  js  c++  java
  • 微信小程序【消息推送服务器认证C# WebAPI】

    参考微信开发文档:

    https://developers.weixin.qq.com/miniprogram/dev/api/custommsg/callback_help.html

    代码可用

    /// <summary>
    /// 接口认证
    /// </summary>
    /// <param name="echostr"></param>
    /// <param name="signature"></param>
    /// <param name="timestamp"></param>
    /// <param name="nonce"></param>
    /// <returns></returns>
    [HttpGet]
    public async Task<HttpResponseMessage> wx(string echostr, string signature, string timestamp, string nonce)
    {
        string token = "token";
        if (!CheckSignature(token, signature, timestamp, nonce))
            echostr = "验证不正确";
        HttpResponseMessage responseMessage = new HttpResponseMessage { Content = new StringContent(echostr, Encoding.GetEncoding("UTF-8"), "text/plain") };
     
        return responseMessage;
    }
    /// <summary>
    /// 接收客服消息
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    public async Task<HttpResponseMessage> wx()
    {
        LogHelper log = new LogHelper();
        var content = await Request.Content.ReadAsStringAsync();
        log.LogError(content);
        HttpResponseMessage responseMessage = new HttpResponseMessage();
        return responseMessage;
    }
    /// <summary>
    /// 验证微信签名
    /// </summary>
    private bool CheckSignature(string token, string signature, string timestamp, string nonce)
    {
        string[] ArrTmp = { token, timestamp, nonce };
     
        Array.Sort(ArrTmp);
        string tmpStr = string.Join("", ArrTmp);
        var data = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(tmpStr));
        var sb = new StringBuilder();
        foreach (var t in data)
        {
            sb.Append(t.ToString("X2"));
        }
        tmpStr = sb.ToString();
        tmpStr = tmpStr.ToLower();
     
        if (tmpStr == signature)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

     推荐代码:使用 Senparc.Weixin SDK

    该版本是用一般处理程序做的,当初在微信配置中填的是此地址,没有修改成WebApi。大家可以参考做成WebApi的

    引用:

    using Senparc.Weixin;
    using Senparc.Weixin.MP;
    using Senparc.Weixin.MP.Entities.Request;
    public class wxapi : IHttpHandler
        {
            //public static readonly string Token = Config.SenparcWeixinSetting.Token;//与微信公众账号后台的Token设置保持一致,区分大小写。
            //public static readonly string EncodingAESKey = Config.SenparcWeixinSetting.EncodingAESKey;//与微信公众账号后台的EncodingAESKey设置保持一致,区分大小写。
            //public static readonly string AppId = Config.SenparcWeixinSetting.WeixinAppId;//与微信公众账号后台的AppId设置保持一致,区分大小写。
            public static string Token = CachedConfigContext.Current.SettingConfig.token;
            public static string EncodingAESKey = CachedConfigContext.Current.SettingConfig.EncodingAESKey;
            public static string AppId = CachedConfigContext.Current.SettingConfig.appId;
    
            readonly Func<string> _getRandomFileName = () => DateTime.Now.ToString("yyyyMMdd-HHmmss") + Guid.NewGuid().ToString("n").Substring(0, 6);
    
            public void ProcessRequest(HttpContext context)
            {
                string postString = string.Empty;
    
                PostModel postModel = new PostModel();
                postModel.Signature = HttpContext.Current.Request.QueryString["signature"];
                postModel.Timestamp = HttpContext.Current.Request.QueryString["timestamp"];
                postModel.Nonce = HttpContext.Current.Request.QueryString["nonce"];
                postModel.Msg_Signature = HttpContext.Current.Request.QueryString["msg_signature"];
                var openid = HttpContext.Current.Request.QueryString["openid"];
                var encrypt_type = HttpContext.Current.Request.QueryString["encrypt_type"];
    
                if (HttpContext.Current.Request.HttpMethod.ToUpper() == "POST")
                {
                    //using (Stream stream = HttpContext.Current.Request.InputStream)
                    //{
                    //    Byte[] postBytes = new Byte[stream.Length];
                    //    stream.Read(postBytes, 0, (Int32)stream.Length);
                    //    postString = Encoding.UTF8.GetString(postBytes);
                    //}
    
                    //if (!string.IsNullOrEmpty(postString))
                    //{
                    //    //Execute(postString);
                    //}
                    if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token))
                    {
                        HttpContext.Current.Response.Write("error");
                        HttpContext.Current.Response.End();
                    }
                    #region 打包 PostModel 信息
    
                    postModel.Token = Token;//根据自己后台的设置保持一致
                    postModel.EncodingAESKey = EncodingAESKey;//根据自己后台的设置保持一致
                    postModel.AppId = AppId;//根据自己后台的设置保持一致
    
                    #endregion
    
                    //v4.2.2之后的版本,可以设置每个人上下文消息储存的最大数量,防止内存占用过多,如果该参数小于等于0,则不限制
                    var maxRecordCount = 10;
    
                    //自定义MessageHandler,对微信请求的详细判断操作都在这里面。
                    var messageHandler = new CustomMessageHandler(HttpContext.Current.Request.InputStream, postModel, maxRecordCount);
    
                    #region 设置消息去重
    
                    /* 如果需要添加消息去重功能,只需打开OmitRepeatedMessage功能,SDK会自动处理。
                     * 收到重复消息通常是因为微信服务器没有及时收到响应,会持续发送2-5条不等的相同内容的RequestMessage*/
                    messageHandler.OmitRepeatedMessage = true;//默认已经开启,此处仅作为演示,也可以设置为false在本次请求中停用此功能
    
                    #endregion
    
                    try
                    {
    
                        #region 记录 Request 日志
    
                        var logPath = HttpContext.Current.Server.MapPath(string.Format("~/logs/MP/{0}/", DateTime.Now.ToString("yyyy-MM-dd")));
                        if (!Directory.Exists(logPath))
                        {
                            Directory.CreateDirectory(logPath);
                        }
    
                        //测试时可开启此记录,帮助跟踪数据,使用前请确保logs文件夹存在,且有读写权限。
                        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
    
                        //执行微信处理过程
                        messageHandler.Execute();
    
                        #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
    
                        //return Content(messageHandler.ResponseDocument.ToString());//v0.7-
                        //return new WeixinResult(messageHandler);//v0.8+
                        var res = new Senparc.Weixin.MP.MvcExtension.FixWeixinBugWeixinResult(messageHandler);//为了解决官方微信5.0软件换行bug暂时添加的方法,平时用下面一个方法即可
                        HttpContext.Current.Response.Write(res.Content);
                        HttpContext.Current.Response.End();
                    }
                    catch (Exception ex)
                    {
                        #region 异常处理
                        WeixinTrace.Log("MessageHandler错误:{0}", ex.Message);
    
                        using (TextWriter tw = new StreamWriter(HttpContext.Current.Server.MapPath("~/logs/Error_" + _getRandomFileName() + ".txt")))
                        {
                            tw.WriteLine("ExecptionMessage:" + ex.Message);
                            tw.WriteLine(ex.Source);
                            tw.WriteLine(ex.StackTrace);
                            //tw.WriteLine("InnerExecptionMessage:" + ex.InnerException.Message);
    
                            if (messageHandler.ResponseDocument != null)
                            {
                                tw.WriteLine(messageHandler.ResponseDocument.ToString());
                            }
    
                            if (ex.InnerException != null)
                            {
                                tw.WriteLine("========= InnerException =========");
                                tw.WriteLine(ex.InnerException.Message);
                                tw.WriteLine(ex.InnerException.Source);
                                tw.WriteLine(ex.InnerException.StackTrace);
                            }
    
                            tw.Flush();
                            tw.Close();
                        }
                        HttpContext.Current.Response.Write("");
                        HttpContext.Current.Response.End();
                        #endregion
                    }
    
                }
                else
                {
                    if (CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token))
                    {
                        string echostr = HttpContext.Current.Request.QueryString["echoStr"];
                        //返回随机字符串则表示验证通过
                        HttpContext.Current.Response.Write(echostr);
                        HttpContext.Current.Response.End();
                    }
                }
            }
    
            public bool IsReusable
            {
                get
                {
                    return false;
                }
            }
        }
  • 相关阅读:
    .NET Interop 工具集
    关于正弦波的算法
    Windows Phone 系列 本地数据存储
    Xaml cannot create an instance of “X”
    Windows Phone 系列 使用 MVVM绑定时无法获取当前值
    Windows Phone 系列 应用程序图标无法显示
    Windows Phone 系列 WPConnect无法上网的问题
    Windows Phone 系列 使用 Windows Phone 保存铃声任务
    WP7.5提交应用
    Windows Phone 系列 动态删除ObservableCollection
  • 原文地址:https://www.cnblogs.com/kennyliu/p/9553037.html
Copyright © 2011-2022 走看看