微信小程序【消息推送服务器认证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; } } }
版权声明:本文为kennyliu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。