微信jssdk 認證簽名,微信官方建議在後臺獲取,而且要緩存獲取過程當中使用的access_token 和 jsapiticket,緣由是微信官方限制了天天獲取的次數(2000次),因此要在後臺緩存,html
access_token 和 jsapiticket都是兩小時內有效,可根據本身的需求設定緩存的時間。算法
下面的代碼是認證簽名類api
1 using LitJson; 2 using System; 3 using System.Collections.Generic; 4 using System.IO; 5 using System.Net; 6 using System.Security.Cryptography; 7 using System.Text; 8 using System.Web; 9 10 namespace Components.Helper 11 { 12 public static class WxJsSdkHelper 13 { 14 private static string m_CacheKey_accesstoken = "wxapi/jssdk/accesstoken"; 15 private static string m_CacheKey_jsapiticket = "wxapi/jssdk/jsapiticket"; 16 17 #region Get請求的簡單封裝 18 19 /// <summary>發起GET請求</summary> 20 /// <param name="url">請求URL</param> 21 /// <param name="errmsg">錯誤信息</param> 22 /// <param name="parameters">請求參數</param> 23 /// <returns></returns> 24 public static string Get(string url, out string errmsg, Dictionary<string, object> parameters) 25 { 26 errmsg = null; 27 var strUrl = new StringBuilder(url); 28 if (parameters != null && parameters.Count > 0) 29 { 30 //拼接參數 31 strUrl.Append("?"); 32 foreach (KeyValuePair<string, object> keyValuePair in parameters) 33 { 34 strUrl.AppendFormat("{0}={1}&",keyValuePair.Key,keyValuePair.Value.ToString()); 35 } 36 strUrl.Remove(strUrl.Length - 1, 1);//移除最後一位多出的「&」 37 } 38 var request = (HttpWebRequest)WebRequest.Create(strUrl.ToString()); 39 request.Method = "GET"; 40 request.Timeout = 10000; 41 try 42 { 43 var response = (HttpWebResponse)request.GetResponse(); 44 using (Stream stream = response.GetResponseStream()) 45 { 46 if (stream != null) 47 { 48 var reader = new StreamReader(stream); 49 return reader.ReadToEnd(); 50 } 51 } 52 } 53 catch (Exception ex) 54 { 55 errmsg = "請求異常:" + ex.Message; 56 } 57 return null; 58 } 59 60 #endregion 61 62 #region SHA1加密算法 63 64 /// <summary> 65 /// SHA1加密算法 66 /// </summary> 67 /// <param name="str">要加密的字符串</param> 68 /// <returns></returns> 69 public static string GetSha1Str(string str) 70 { 71 byte[] strRes = Encoding.UTF8.GetBytes(str); 72 HashAlgorithm iSha = new SHA1CryptoServiceProvider(); 73 strRes = iSha.ComputeHash(strRes); 74 var enText = new StringBuilder(); 75 foreach (byte iByte in strRes) 76 { 77 enText.AppendFormat("{0:x2}", iByte); 78 } 79 return enText.ToString(); 80 } 81 82 #endregion 83 84 #region 獲取access_token 85 /// <summary> 86 /// 獲取調用JS SDK時所需的access_token 87 /// 文檔地址:http://mp.weixin.qq.com/wiki/15/54ce45d8d30b6bf6758f68d2e95bc627.html 88 /// </summary> 89 /// <returns></returns> 90 public static string GetAccessToken(string appid,string appSecret) 91 { 92 //獲取access_token在2小時內有效,因爲1天內獲取次數有限制(2000次),所以緩存100分鐘 93 string errmsg; 94 string access_token = string.Empty; 95 // 從緩存中獲取token 96 //string temp = CacheHelper.GetCache(m_CacheKey_accesstoken).IString(); 97 string temp = MemcachHelper.Get(m_CacheKey_accesstoken).IString(); 98 //Functions.Write("緩存測試,當前緩存內容:token" + temp + ",時間:" + DateTime.Now.IString()); 99 if (!temp.IsEmpty()) 100 { 101 return access_token = temp; 102 } 103 else 104 { 105 string apiUrl = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appid, appSecret); 106 string responseStr = Get(apiUrl, out errmsg, null); 107 if (responseStr == null) 108 { 109 return errmsg; 110 } 111 else 112 { 113 JsonData jd = JsonMapper.ToObject(responseStr); 114 access_token = (string)jd["access_token"]; 115 if (!access_token.IsEmpty()) 116 { 117 //CacheHelper.AddCache(m_CacheKey_accesstoken, access_token, 1); 118 DateTime m_expiryTime = DateTime.Now.AddMilliseconds(60000); 119 MemcachHelper.Add(m_CacheKey_accesstoken, access_token, m_expiryTime); 120 //Functions.Write("緩存測試,添加緩存操做,內容:token" + access_token + ",時間:" + DateTime.Now.IString()); 121 return access_token; 122 } 123 else 124 { 125 return errmsg = "取得access_token失敗"; 126 } 127 } 128 } 129 } 130 #endregion 131 132 #region 獲取調用JS SDK時所需的票據 133 /// <summary> 134 /// 獲取調用JS SDK時所需的票據 135 /// 文檔地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95 136 /// </summary> 137 /// <returns></returns> 138 public static string GetJsApiTicket(string appid, string appSecret) 139 { 140 //獲取的ticket在2小時內有效,因爲1天內獲取次數有限制(2000次),所以緩存100分鐘 141 string errmsg; 142 string jsapiticket = string.Empty; 143 // 從緩存中獲取ticket 144 //string temp = CacheHelper.GetCache(m_CacheKey_jsapiticket).IString(); 145 string temp = MemcachHelper.Get(m_CacheKey_jsapiticket).IString(); 146 //Functions.Write("緩存測試,當前緩存內容:票據" + temp + ",時間:" + DateTime.Now.IString()); 147 if (!temp.IsEmpty()) 148 { 149 return jsapiticket = temp; 150 } 151 else { 152 string apiUrl = string.Format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi", GetAccessToken(appid, appSecret)); 153 string responseStr = Get(apiUrl, out errmsg, null); 154 if (responseStr == null) 155 { 156 return null; 157 } 158 else 159 { 160 JsonData jd = JsonMapper.ToObject(responseStr); 161 jsapiticket = (string)jd["ticket"]; 162 if (!jsapiticket.IsEmpty()) 163 { 164 //CacheHelper.AddCache(m_CacheKey_jsapiticket, jsapiticket, 1); 165 DateTime m_expiryTime = DateTime.Now.AddMilliseconds(60000); 166 MemcachHelper.Add(m_CacheKey_jsapiticket, jsapiticket, m_expiryTime); 167 //Functions.Write("緩存測試,添加緩存操做,內容:票據" + jsapiticket + ",時間:" + DateTime.Now.IString()); 168 return jsapiticket; 169 } 170 else 171 { 172 return null; 173 } 174 } 175 } 176 } 177 #endregion 178 179 #region JS SDK使用權限簽名算法 180 /// <summary> 181 /// JS SDK使用權限簽名算法 182 /// </summary> 183 /// <param name="jsapiTicket">The jsapi_ticket.</param> 184 /// <param name="url">The URL.</param> 185 /// <returns></returns> 186 public static Dictionary<string, string> Sign(string jsapiTicket, string url, string appid) 187 { 188 string nonceStr = Guid.NewGuid().ToString().Replace("-", ""); 189 string timestamp = GenerateTimeStamp(); 190 string str = string.Format("jsapi_ticket={0}&noncestr={1}×tamp={2}&url={3}", jsapiTicket, nonceStr, timestamp, url); 191 string signature = GetSha1Str(str);//SHA1加密 192 return new Dictionary<string, string>{ 193 {"appid", appid}, 194 {"jsapi_ticket", jsapiTicket}, 195 {"noncestr", nonceStr}, 196 {"timestamp", timestamp}, 197 {"signature", signature} 198 }; 199 } 200 public static string GenerateTimeStamp() 201 { 202 TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); 203 return Convert.ToInt64(ts.TotalSeconds).ToString(); 204 } 205 #endregion 206 } 207 }
當中用到了分佈式緩存幫助類,代碼以下緩存
1 using Memcached.ClientLibrary; 2 using System; 3 using System.Collections; 4 using System.Collections.Generic; 5 using System.Configuration; 6 using System.Linq; 7 using System.Text; 8 9 namespace Components.Helper 10 { 11 /// <summary>分佈式緩存Memcach幫助類</summary> 12 public class MemcachHelper 13 { 14 private static MemcachedClient _client; 15 /// <summary>默認緩存時間(默認20分鐘)</summary> 16 public static int DefaultCacheTime = (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["DefaultCacheTime"]) ? Convert.ToInt32(ConfigurationManager.AppSettings["DefaultCacheTime"]) : 1200000); 17 18 /// <summary> 19 /// 是否啓用分佈式緩存 20 /// </summary> 21 public static bool IsEnableScatteredCache = (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["IsEnableScatteredCache"]) ? Convert.ToBoolean(ConfigurationManager.AppSettings["IsEnableScatteredCache"]) : true); 22 static MemcachHelper() 23 { 24 string[] serverlist = (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["Memcached.ServerList"]) ? ConfigurationManager.AppSettings["Memcached.ServerList"].Split(',') : null); 25 26 if (null == serverlist) 27 { 28 serverlist = new string[] { "127.0.0.1:11211" }; 29 } 30 31 SockIOPool pool = SockIOPool.GetInstance("First"); 32 pool.SetServers(serverlist); 33 pool.Initialize(); 34 35 //初始化 36 _client = new MemcachedClient(); 37 _client.PoolName = "First"; 38 _client.EnableCompression = false; 39 } 40 41 #region Add 42 public static bool Add(string key, object value) 43 { 44 DateTime m_expiryTime = DateTime.Now.AddMilliseconds(DefaultCacheTime); 45 return _client.Add(key, value, m_expiryTime); 46 } 47 public static bool Add(string key, object value, DateTime expiry) 48 { 49 return _client.Add(key, value, expiry); 50 } 51 public static bool Add(string key, object value, int hashCode) 52 { 53 return _client.Add(key, value, hashCode); 54 } 55 public static bool Add(string key, object value, DateTime expiry, int hashCode) 56 { 57 return _client.Add(key, value, expiry, hashCode); 58 } 59 #endregion 60 61 #region Delete 62 /// <summary>刪除緩存</summary> 63 /// <param name="key"></param> 64 /// <returns></returns> 65 public static bool Delete(string key) 66 { 67 return _client.Delete(key); 68 } 69 70 /// <summary>刪除緩存</summary> 71 /// <param name="key"></param> 72 /// <param name="expiry"></param> 73 /// <returns></returns> 74 public static bool Delete(string key, DateTime expiry) 75 { 76 return _client.Delete(key, expiry); 77 } 78 79 /// <summary>刪除緩存</summary> 80 /// <param name="key"></param> 81 /// <param name="hashCode"></param> 82 /// <param name="expiry"></param> 83 /// <returns></returns> 84 public static bool Delete(string key, object hashCode, DateTime expiry) 85 { 86 return _client.Delete(key, hashCode, expiry); 87 } 88 89 #endregion 90 91 #region Get 92 /// <summary>獲取緩存</summary> 93 /// <param name="key"></param> 94 /// <returns></returns> 95 public static object Get(string key) 96 { 97 return _client.Get(key); 98 } 99 /// <summary>獲取緩存</summary> 100 /// <param name="key"></param> 101 /// <param name="hashCode"></param> 102 /// <returns></returns> 103 public static object Get(string key, int hashCode) 104 { 105 return _client.Get(key, hashCode); 106 } 107 /// <summary>獲取緩存</summary> 108 /// <param name="key"></param> 109 /// <param name="hashCode"></param> 110 /// <param name="asString"></param> 111 /// <returns></returns> 112 public static object Get(string key, object hashCode, bool asString) 113 { 114 return _client.Get(key, hashCode, asString); 115 } 116 #endregion 117 118 #region Replace 119 /// <summary> 120 /// 替換更新 121 /// </summary> 122 /// <param name="key"></param> 123 /// <param name="value"></param> 124 /// <returns></returns> 125 public static bool Replace(string key, object value) 126 { 127 return _client.Replace(key, value); 128 } 129 /// <summary> 130 /// 替換更新 131 /// </summary> 132 /// <param name="key"></param> 133 /// <param name="value"></param> 134 /// <param name="expiry"></param> 135 /// <returns></returns> 136 public static bool Replace(string key, object value, DateTime expiry) 137 { 138 return _client.Replace(key, value, expiry); 139 } 140 /// <summary> 141 /// 替換更新 142 /// </summary> 143 /// <param name="key"></param> 144 /// <param name="value"></param> 145 /// <param name="hashCode"></param> 146 /// <returns></returns> 147 public static bool Replace(string key, object value, int hashCode) 148 { 149 return _client.Replace(key, value, hashCode); 150 } 151 /// <summary> 152 /// 替換更新 153 /// </summary> 154 /// <param name="key"></param> 155 /// <param name="value"></param> 156 /// <param name="expiry"></param> 157 /// <param name="hashCode"></param> 158 /// <returns></returns> 159 public static bool Replace(string key, object value, DateTime expiry, int hashCode) 160 { 161 return _client.Replace(key, value, expiry, hashCode); 162 } 163 #endregion 164 165 #region Set 166 public static bool Set(string key, object value) 167 { 168 return _client.Set(key, value); 169 } 170 public static bool Set(string key, object value, DateTime expiry) 171 { 172 return _client.Set(key, value, expiry); 173 } 174 public static bool Set(string key, object value, int hashCode) 175 { 176 return _client.Set(key, value, hashCode); 177 } 178 public static bool Set(string key, object value, DateTime expiry, int hashCode) 179 { 180 return _client.Set(key, value, expiry, hashCode); 181 } 182 #endregion 183 184 #region Stats 185 public static Hashtable Stats() 186 { 187 return _client.Stats(); 188 } 189 190 public static Hashtable Stats(ArrayList servers) 191 { 192 return _client.Stats(servers); 193 } 194 #endregion 195 196 /// <summary>判斷指定Key的緩存是否存在</summary> 197 /// <param name="key"></param> 198 /// <returns></returns> 199 public static bool KeyExists(string key) 200 { 201 return _client.KeyExists(key); 202 } 203 204 /// <summary> 205 /// 移除緩存,針對空間 206 /// </summary> 207 /// <param name="key"></param> 208 public static void RemoveRegionCache(string regionName) 209 { 210 211 } 212 } 213 }
簽名的實現:三個參數 ①url ②微信appid ③微信 AppSecret,注意微信官方要求url是取「#」前邊的部分做爲參數。微信
下面是示例代碼,僅供參考。app
1 Dictionary<string, string> dic = new Dictionary<string, string>(); 2 string url = postData["url"].IString(); 3 string[] urlarray = url.Split('#'); 4 url = urlarray[0].IString(); 5 string appid = "wx12344566778"; 6 string AppSecret = "testtest12345678test"; 7 string ticket = WxJsSdkHelper.GetJsApiTicket(appid, AppSecret); 8 if (!ticket.IsEmpty()) 9 { 10 dic = WxJsSdkHelper.Sign(ticket, url, appid); 11 result.Result = JsonMapper.ToJson(dic); 12 }