最近在做webapp小項目的開發,涉及到微信的分享(分享到朋友圈/發送給朋友等)
元旦之前就基本上完成功能開發了,當時微信並未開放分享等API
於是用了網上找到的一些方法去實現,但是元旦左右就不能再正常使用了
前幾天微信官方上線了JS SDK以及文檔說明,地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
主要步驟如下:
1、通過appid和appsecret獲取access_token;
2、通過access_token獲取jsapi_ticket;
3、實現簽名算法;
4、初始化wx.config參數信息;
5、在wx.ready內進行相關API調用
雖然相比之前調用起來麻煩了一些,但是更安全穩定,於是馬上對之前的代碼做了調整,分享如下
【部分代碼基於項目的基類,如緩存和日志等,此處不貼出,比較簡單,可自己實現】
以下是後台代碼部分:
/* *nextuntil *微信JS SDK調用簡單封裝 *2015-01-12 */ using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Security.Cryptography; using System.Text; using System.Web; using KK.Utility; using KK.Utility.Extensions; namespace M { public static class WeixinHelper { #region Get請求的簡單封裝 /// <summary>發起GET請求</summary> /// <param name="url">請求URL</param> /// <param name="errmsg">錯誤信息</param> /// <param name="parameters">請求參數</param> /// <returns></returns> public static string Get(string url, out string errmsg, Dictionary<string, object> parameters) { errmsg = null; var strUrl = new StringBuilder(url); if (parameters != null && parameters.Count > 0) { //拼接參數 strUrl.Append("?"); foreach (KeyValuePair<string, object> keyValuePair in parameters) { strUrl.AppendFormat("{0}={1}&", HttpUtility.UrlEncode(keyValuePair.Key, Encoding.UTF8), HttpUtility.UrlEncode(keyValuePair.Value.ToString(), Encoding.UTF8)); } strUrl.Remove(strUrl.Length - 1, 1);//移除最後一位多出的“&” } var request = (HttpWebRequest)WebRequest.Create(strUrl.ToString()); request.Method = "GET"; request.Timeout = 10000; try { var response = (HttpWebResponse)request.GetResponse(); using (Stream stream = response.GetResponseStream()) { if (stream != null) { var reader = new StreamReader(stream); return reader.ReadToEnd(); } } } catch (Exception ex) { errmsg = "請求異常:" + ex.Message; } return null; } #endregion #region SHA1加密算法 /// <summary> /// SHA1加密算法 /// </summary> /// <param name="str">要加密的字符串</param> /// <returns></returns> public static string GetSha1Str(string str) { byte[] strRes = Encoding.UTF8.GetBytes(str); HashAlgorithm iSha = new SHA1CryptoServiceProvider(); strRes = iSha.ComputeHash(strRes); var enText = new StringBuilder(); foreach (byte iByte in strRes) { enText.AppendFormat("{0:x2}", iByte); } return enText.ToString(); } #endregion /// <summary> /// 獲取調用JS SDK時所需的access_token /// 文檔地址:http://mp.weixin.qq.com/wiki/15/54ce45d8d30b6bf6758f68d2e95bc627.html /// </summary> /// <returns></returns> public static string GetAccessToken() { //獲取access_token在2小時內有效,由於1天內獲取次數有限制(2000次),因此緩存2小時 return KK.Cache.MyCache.Instance.Get<string>("wxapi/jssdk/accesstoken", () => { string errmsg; string apiUrl = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", Utils.GetAppId(), Utils.GetAppSecret()); string responseStr = Get(apiUrl, out errmsg, null); if (responseStr == null) { KK.Core.Log.TraceLogger.Info("獲取access_token失敗,響應內容為空", null); } else { var dic = responseStr.JSONDeserialize<Dictionary<string, object>>(); if (dic.ContainsKey("access_token")) { return dic["access_token"]; } else { KK.Core.Log.TraceLogger.Info("獲取access_token失敗,響應內容:" + responseStr, null); } } return null; }, 120); } /// <summary> /// 獲取調用JS SDK時所需的票據 /// 文檔地址: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 /// </summary> /// <returns></returns> public static string GetJsApiTicket() { //獲取的ticket在2小時內有效,由於1天內獲取次數有限制(2000次),因此緩存2小時 return KK.Cache.MyCache.Instance.Get<string>("wxapi/jssdk/jsapiticket", () => { string errmsg; string apiUrl = string.Format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi", GetAccessToken()); string responseStr = Get(apiUrl, out errmsg, null); if (responseStr == null) { KK.Core.Log.TraceLogger.Info("獲取ticket失敗", null); } else { var dic = responseStr.JSONDeserialize<Dictionary<string, object>>(); if (dic.ContainsKey("ticket")) { return dic["ticket"]; } } return null; }, 120); } /// <summary> /// JS SDK使用權限簽名算法 /// </summary> /// <param name="jsapiTicket">The jsapi_ticket.</param> /// <param name="url">The URL.</param> /// <returns></returns> public static Dictionary<string, string> Sign(string jsapiTicket, string url) { string nonceStr = Guid.NewGuid().ToString().Replace("-", ""); string timestamp = ConvertHelper.DateToUnix(DateTime.Now,2).ToString(); string str = string.Format("jsapi_ticket={0}&noncestr={1}×tamp={2}&url={3}", jsapiTicket, nonceStr, timestamp, url); string signature = GetSha1Str(str);//SHA1加密 return new Dictionary<string, string>{ {"url", url}, {"jsapi_ticket", jsapiTicket}, {"noncestr", nonceStr}, {"timestamp", timestamp}, {"signature", signature} }; } } }
網頁代碼[我的項目是webform]:
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <script type="text/javascript"> <% string jsapiTicket = M.WeixinHelper.GetJsApiTicket(); Dictionary<string, string> dic = M.WeixinHelper.Sign(jsapiTicket, Request.Url.AbsoluteUri); %> wx.config({ debug: true, appId: '你的appid', timestamp: <%=dic["timestamp"]%>, nonceStr: '<%=dic["noncestr"]%>', signature: '<%=dic["signature"]%>', jsApiList: [ 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo' ] }); wx.ready(function() { wx.onMenuShareTimeline({ title: '分享標題', link: '鏈接地址', imgUrl: '圖片地址', success: function () { // 用戶確認分享後執行的回調函數 }, cancel: function () { // 用戶取消分享後執行的回調函數 } }); }); </script>
程序調試過程中也碰到一些小問題,不知道大家有沒有解決方案:
1、發送給好友的自定義內容中,描述信息是否能換行(一般是摘要,不考慮,如果是名片,希望可以分行顯示,已試過<br>和\r\n等,均無效);
2、分享的URL不能是重寫過的URL(開啟調試,提示簽名無效,調試多次發現是URL的問題)