1.需要微信服务号的appid,密钥
2.微信公众平台添加白名单,配置js安全域名
3.需要把配置安全js域名时提供的文件放在网站的根目录下
4.前端调用后台接口,获取ticket
5.后台根据appid、密钥来调微信接口获取token、ticket
下面是js里的函数,功能是从接口获取ticket,然后自定义分享
function weixin_share(wxTitle,wxCon,wxIMg){ var wxurl = location.href.split('#')[0].toString(); // wxurl=encodeURIComponent(wxurl); var ua = navigator.userAgent.toLowerCase(); //if (ua.match(/MicroMessenger/i) == "micromessenger") { $.ajax({ type: "POST", url: "/api/GetWeXinData", dataType: "json", async: false, data: { wxurl: wxurl }, success: function (data) { console.log(data) if (data.status == "ok") { wx.config({ debug: false, appId: data.appid, timestamp: data.timestamp, nonceStr: data.nonceStr, signature: data.signature, jsApiList: [ 'checkJsApi', 'onMenuShareTimeline',//分享朋友圈 'onMenuShareAppMessage',//分享微信好友 'onMenuShareQQ',//分享QQ好友 'onMenuShareWeibo',//分享腾讯微博 'onMenuShareQZone'//分享QQ空间 ] }); } }, error: function (xhr, status, error) { console.log(status); console.log(xhr.responseText); }, }); function checkJsApi() { wx.checkJsApi({ jsApiList: ['checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage',//分享微信好友 'onMenuShareQQ',//分享QQ好友 'onMenuShareWeibo',//分享腾讯微博 'onMenuShareQZone'//分享QQ空间 ], success: function (res) { // 以键值对的形式返回,可用的api值true,不可用为false // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"} //var jon = $.parseJSON(res); console.log("判断接口是否被支持:" + jon.errMsg.checkJsApi); } }); } //分享微信朋友圈 function onMenuShareTimeline() { wx.onMenuShareTimeline({ title: wxTitle, link: wxurl, imgUrl: wxIMg, trigger: function (res) { console.log('click shared'); }, success: function (res) { console.log('分享成功!'); console.log(res); }, cancel: function (res) { console.log('shared cancle'); console.log(res); }, fail: function (res) { console.log("分享失败"+res); console.log(JSON.stringify(res)); } }); } //分享微信好友 function onMenuShareAppMessage() { wx.onMenuShareAppMessage({ title: wxTitle, desc: wxCon, link: wxurl, imgUrl: wxIMg, trigger: function (res) { // 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回 console.log('用户点击发送给朋友'); }, success: function (res) { console.log('已分享'); }, cancel: function (res) { console.log('已取消'); }, fail: function (res) { console.log(JSON.stringify(res)); } }); } function onMenuShareQQ() { wx.onMenuShareQQ({ title: wxTitle, desc: wxCon, link: wxurl, imgUrl: wxIMg, trigger: function (res) { console.log('用户点击分享到QQ'); }, complete: function (res) { console.log(JSON.stringify(res)); }, success: function (res) { console.log('已分享'); }, cancel: function (res) { console.log('已取消'); }, fail: function (res) { console.log('分享成功!'); console.log(JSON.stringify(res)); } }); } function onMenuShareQZone() { wx.onMenuShareQZone({ title: wxTitle, desc: wxCon, link: wxurl, imgUrl: wxIMg, trigger: function (res) { console.log('用户点击分享到QZone'); }, complete: function (res) { console.log(JSON.stringify(res)); }, success: function (res) { console.log('已分享'); }, cancel: function (res) { console.log('已取消'); }, fail: function (res) { console.log(JSON.stringify(res)); console.log('分享失败!'); } }); } wx.ready(function () { checkJsApi(); onMenuShareTimeline(); onMenuShareQZone(); onMenuShareQQ(); onMenuShareAppMessage(); }); wx.error(function (res) { console.log(res.errMsg); }); //} }
js部分就是上面的。不要忘了,html中应引用js和自定义标题,图片等
<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> <script src="~/js/WX_share.js"></script> <script>weixin_share('描述', '标题', '/图片/weixin.jpg')</script>
接下来就是后台接口的实现了:
public ActionResult GetWeXinData() { Signature sg = new Signature(); long timeout = 7200;//过期时间7200s try { String url = Request["wxurl"]; if (string.IsNullOrEmpty(url)) { sg.status = "error"; } sg.appid = ConfigurationManager.AppSettings["wx_appid"];//获取appid string secret= ConfigurationManager.AppSettings["wx_secret"];//获取密钥 sg.wxurl = url; sg.nonceStr = WXJsJdkHelper.GetNonceStr(); sg.timestamp = WXJsJdkHelper.GetTimestamp(); var accesstoken = CacheHelper.GetCache("accesstoken_");//从缓存中获取,不能频繁的调用微信服务器接口,一天有次数限制 string token = ""; if (accesstoken == null) { WXJsJdkHelper.GetAccessToken(sg.appid, secret, out token); CacheHelper.SetCacheDateTime("accesstoken_", token, timeout); }else { token = accesstoken.ToString(); } var wxticket = CacheHelper.GetCache("wxticket_"); if (wxticket == null) { sg.wxticket = WXJsJdkHelper.GetJsAPITicket(token); CacheHelper.SetCacheDateTime("wxticket_", sg.wxticket, timeout); }else { sg.wxticket = wxticket.ToString(); } LogHelper.WriteLog("获取微信token:"+ accesstoken+ "ticket" + sg.wxticket); sg.status = "ok"; sg.signature = WXJsJdkHelper.GetSHA1Value(WXJsJdkHelper.GetNonSHA1HashSignature(sg.nonceStr, sg.wxticket, sg.timestamp, sg.wxurl)); return Json(sg, JsonRequestBehavior.AllowGet); } catch (Exception ex) { LogHelper.WriteLog("获取微信签名配置信息时错误:", ex); sg.status = "error"; sg.nonceStr = string.Empty; sg.signature = string.Empty; sg.timestamp = string.Empty; sg.wxurl = string.Empty; sg.wxticket = string.Empty; return Json(sg, JsonRequestBehavior.AllowGet); } }
获取AccessToken的方法
public static bool GetAccessToken(string appid, string secret, out string res) { //正确的返回值格式{"access_token":"rcSFy_BaOHfW92AdXmer1ec4yLbMYeW3Sl3N29uKM96cRJnfZkpxUTr9VTw7ih4S9OY9tTqd5c697iNWVeXesqVPWFRi5pLRAnyPJNw7aMhIaK_dJDo3cxoXfyahUtyAOGXiAAATLC","expires_in":7200} //错误返回值格式{"errcode":40013,"errmsg":"invalid appid"} string strJson = GetJsonData(string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appid, secret), "get"); string access_token = GetJsonValue(strJson, "access_token"); if (string.IsNullOrEmpty(access_token)) { res = GetJsonValue(strJson, "errcode"); return false; } res = access_token; return true; }
根据accesstoken获取对应的JsAPITicket的方法
public static string GetJsAPITicket(string accesstoken) { string strJson = GetJsonData(string.Format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi", accesstoken), "get"); string jsapiticket = GetJsonValue(strJson, "ticket"); if (string.IsNullOrEmpty(jsapiticket)) { return GetJsonValue(strJson, "errcode"); } return jsapiticket; }
获取SHA1Value值
public static string GetSHA1Value(string str_sha1_in) { SHA1 sha1 = new SHA1CryptoServiceProvider(); byte[] bytes_sha1_in = System.Text.UTF8Encoding.Default.GetBytes(str_sha1_in); byte[] bytes_sha1_out = sha1.ComputeHash(bytes_sha1_in); string str_sha1_out = BitConverter.ToString(bytes_sha1_out); str_sha1_out = str_sha1_out.Replace("-", "").ToLower(); return str_sha1_out; }
//
缓存的CatchHelper.cs
/// <summary> /// 获取数据缓存 /// </summary> /// <param name="CacheKey">键</param> public static object GetCache(string CacheKey) { Cache objCache = HttpRuntime.Cache; if (objCache[CacheKey] == null) return null; else return objCache[CacheKey]; }
public static void SetCacheDateTime(string CacheKey, object objObject, long Seconds) { Cache objCache = HttpRuntime.Cache; objCache.Insert(CacheKey, objObject, null, System.DateTime.Now.AddSeconds(Seconds), TimeSpan.Zero); }