在进行微信公众号配置时,会需要进行服务器配置,通过比对获取的签名和服务器计算的签名,以便验证签名的正确性。
1、服务器上需要配置服务器地址、Token、消息加解密秘钥。服务器地址为验证签名的地址、Token为自定义的令牌(一经启用最好不要更改,因为验证签名的接口代码中会使用到这个令牌)、EncodingAESkey为用户生成的秘钥,用于服务器消息加解密。消息加解密方式建议使用兼容模式。修改完成后不要急于点击启用,这个时候接口没有写好、调通,启用是会失败的。等下面接口写好、调通,再点击启用,即完成了服务器配置。
在配置好服务器后,我们需要实现两个接口:获取签名接口、验证签名接口。
1、引入微信SDK:Senparc.Weixin.MP.dll,Senparc.Weixin.dll。可使用NuGet搜索WeiXin查找安装。
2、获取签名接口。
private static string appId = ConfigurationManager.AppSettings["appid"];//微信公众号AppID private static string secret = ConfigurationManager.AppSettings["appsecret"];//微信公众号AppSecret public static string token = "";//为服务器配置中的Token /// <summary> /// 微信公众号获取签名 /// </summary> /// <param name="url">移动端获取的url</param> /// <returns>成功时,返回签名信息</returns> [AnonymousAttribute] [HttpGet] public JsonResult WXGetSign(string url) { Result result = new Result(); result.page = null; try { string ticket = ""; //查看缓存中的ticket object objTicket = CacheHelper.GetCache("WXRecruitmentTicket"); if (objTicket == null)//缓存中不存在ticket { //获取微信ticket JsApiTicketResult TicketResult = CommonApi.GetTicket(appId, secret); //将获取到的ticket存入缓存 CacheHelper.AddCache("WXRecruitmentTicket", TicketResult.ticket, TicketResult.expires_in / 60 - 10); } else//缓存中存在ticket ticket = objTicket.ToString(); if (ticket != "") { string noncestr = DDHelper.GetRandomString(20, true, true, true, false, ""); string jsUrl = System.Web.HttpUtility.UrlDecode(url); int timeStamp = Convert.ToInt32((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds); string signature = JSSDKHelper.GetSignature(ticket, noncestr, timeStamp.ToString(), jsUrl); object SignObj = new object(); SignObj = new { appId = ConfigurationManager.AppSettings["appId"], nonceStr = noncestr, timeStamp = timeStamp, signature = signature }; result.code = 0; result.message = "获取成功!"; result.result = SignObj; } else { result.code = 101; result.message = "Ticket获取失败,无法计算签名!"; result.result = null; } } catch (Exception ex) { Log4Helper.WriteErrorLog(StoreType.TextFile, ex); result.code = 100; result.message = "计算签名发生异常!"; result.result = null; } return Json(result, JsonRequestBehavior.AllowGet); }
3、验证签名接口。
加密/校验流程如下:
1. 将token、timestamp、nonce三个参数进行字典序排序
2. 将三个参数字符串拼接成一个字符串进行sha1加密
3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
/// <summary> /// 微信公众号服务器地址验证 /// </summary> /// <param name="signature">微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。</param> /// <param name="timestamp">时间戳</param> /// <param name="nonce">随机数</param> /// <param name="echostr">随机字符串</param> /// <returns>成功时,验证通过</returns> [AnonymousAttribute] [HttpGet] public string checkSignature(string signature, string timestamp, string nonce, string echostr) { List<string> list = new List<string>(); list.Add(token); list.Add(timestamp); list.Add(nonce); list.Sort(); string res = string.Join("", list.ToArray()); Byte[] dataToHash = Encoding.ASCII.GetBytes(res); byte[] hashvalue = ((HashAlgorithm)CryptoConfig.CreateFromName("SHA1")).ComputeHash(dataToHash); StringBuilder sb = new StringBuilder(); foreach (byte b in hashvalue) { sb.Append(b.ToString("x2")); } if (signature == sb.ToString()) return echostr; else return null; }
验证公众号消息来源于服务器地址相比较于微信网页授权要简单许多,调试起来也比较容易。获取签名使用微信封装好的SDK,验证签名使用微信规范好的排序、计算方法,基本调试通过。