微信公众号自定义分享功能
一.测试微信公众号接入自己的系统
写个后台接入的方法
[HttpGet] public string Validate(string signature,string timestamp,string nonce,string echostr) { //1. 将token、timestamp、nonce三个参数进行字典序排序 string[] arr = {timestamp, nonce, WeChatUtil.Token}; Array.Sort(arr); //2. 将三个参数字符串拼接成一个字符串进行sha1加密 StringBuilder sb = new StringBuilder(); foreach (var temp in arr) { sb.Append(temp); } string sha1 = EncryptionSha1.EncryptString(sb.ToString()).ToLower(); if (sha1.Equals(signature)) { //接入成功 Trace.WriteLine("接入成功"); return echostr; } //接入失败 return null; }
注意:
1.这个方法必须是get请求
2.微信调用这个方法会自动传入四个参数
3.通过token(公众号配置中的token),和传入的timestamp,nonce三个参数,字典排序,然后sha1加密
4.加密结果就应该等于微信传入的第一个signature参数
5.判断加密结果和signature,如果相同,表示接入成功,将微信传入的第四个参数源样返回.如果不同,返回null,就表示接入失败
然后将这个方法地址填写到微信接入配置的URL中,和用到token也配置进去
二.使用微信JS-SDK
JSSDK中的wx.config需要几个参数,需要后台返回给它,
[HttpGet] public void GetSignature(string url,string callback) { var appid = WeChatUtil.AppId; var timeStamp = WeChatUtil.GetTimeStamp(); var nonceStr = WeChatUtil.GetNonceStr(); var signature = WeChatUtil.GetSignature(timeStamp, nonceStr, url); var obj = JsonConvert.SerializeObject(new {appid = appid, timeStamp = timeStamp , nonceStr = nonceStr, signature= signature }); var jsonp = $"{callback}({obj})"; HttpContext.Response.ContentType= "application/json"; HttpContext.Response.Write(jsonp); }
1,返回appid.
2.返回timestamp,这个就是后台生成个时间戳就行
3.返回nonceStr,随便生成一个随机字符串就可以
4.返回签名signature 比较复杂,看下面代码
public static string GetSignature(string timestamp,string nonceStr,string url) { string str = $"jsapi_ticket={GetJsApiTicket()}" + $"&noncestr={nonceStr}" + $"×tamp={timestamp}" + $"&url={url}"; return EncryptionSha1.EncryptStringSha1(str).ToLower(); }
public static string GetJsApiTicket() { string ticket; ICacheManager cache = new MemoryCacheManager(); var contains = cache.Contains("js_api_ticket"); if (contains) { ticket =cache.GetCache<string>("js_api_ticket"); } else { var httpGet = HttpHelper.HttpGet(GetTicketUrl(), ""); var jsApiTicketModel = JsonConvert.DeserializeObject<JsApiTicketModel>(httpGet); if (jsApiTicketModel.errcode == 0) { ticket = jsApiTicketModel.ticket; long expiresIn = jsApiTicketModel.expires_in; cache.SetCache("js_api_ticket", ticket,TimeSpan.FromSeconds(expiresIn-60)); } else { ticket = null; } } // var httpGet = HttpHelper.HttpGet(GetTicketUrl(), ""); // var jsApiTicketModel = JsonConvert.DeserializeObject<JsApiTicketModel>(httpGet); // ticket = jsApiTicketModel.errcode == 0 ? jsApiTicketModel.ticket : null; return ticket; }
private static string GetTicketUrl() { string url = $"https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={GetAccessToken()}&type=jsapi"; return url; }
public static string GetAccessToken() { string accessToken; ICacheManager cache = new MemoryCacheManager(); var contains = cache.Contains("access_token"); if (contains) { accessToken = cache.GetCache<string>("access_token"); } else { var result = HttpHelper.HttpGet(GetAccessTokenUrl(), ""); var accessTokenModel = JsonConvert.DeserializeObject<AccessTokenModel>(result); accessToken = accessTokenModel.access_token; long expiresIn = accessTokenModel.expires_in; cache.SetCache("access_token", accessToken,TimeSpan.FromSeconds(expiresIn-60)); } return accessToken; }
说明,顺序就是生成签名 --> 依赖JsApiTicket--->依赖TickertUrl --> GetAccessToken
然后将这四个值传给wx.config
三,前端JS
var secure_domain='http://www.taekwondoshow.com';//微信js SDK安全域名 var url_str = window.location.href; var wx_baseUrl='http://q6m89n.natappfree.cc/'; /** * 全局分享调用 */ $(function(){ get_signature(); }) function get_signature() { $.ajax({ type: "GET", url: wx_baseUrl + "/Wechat/Login_Service/_wxSign?jsoncallback=?", data: { url: url_str }, cache: false, dataType: "jsonp", success: function (data) { var result = eval('(' + data + ')'); if(result.code ==200){ try{ wx_config(result.data.appid, result.data.timestamp, result.data.noncestr, result.data.sign); }catch(e){ console.log(e); } } }, error: function () { console.log("配置参数错误!"); } }); } function wx_config(appid, timestamp, nonceStr, signature) { //通过config接口注入权限验证配置 wx.config({ debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: appid, // 必填,公众号的唯一标识 timestamp: timestamp, // 必填,生成签名的时间戳 nonceStr: nonceStr, // 必填,生成签名的随机串 signature: signature, // 必填,签名 jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline','hideMenuItems'] // 必填,需要使用的JS接口列表 }); } wx.ready(function () { // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 wx.onMenuShareAppMessage({ title: '自定义标题', // 分享标题 desc: '自定义描述', // 分享描述 link: secure_domain+'/error401.html', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 imgUrl: secure_domain+'/asset/images/erweima.png', // 分享图标 success: function () { // 设置成功 } }); wx.onMenuShareTimeline({ title: '朋友圈标题', // 分享标题 link: secure_domain+'/error401.html', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致 imgUrl: secure_domain+'/asset/images/erweima.png', // 分享图标 success: function () { // 设置成功 } }); wx.hideMenuItems({ menuList:[ "menuItem:share:qq", "menuItem:share:weiboApp", "menuItem:favorite", "menuItem:share:facebook", "menuItem:share:QZone", "menuItem:editTag", "menuItem:delete", "menuItem:copyUrl", "menuItem:originPage", "menuItem:openWithQQBrowser", "menuItem:openWithSafari", "menuItem:share:email", "menuItem:share:brand" ] }) });
注意:坑1--分享接口中的link和imgurl必须是微信配置中的JS安全域名下的网址
坑2 ---文档说'onMenuShareAppMessage', 'onMenuShareTimeline'这两个接口即将作废,让用两个新的
但新的有很多问题,IOS可以分享,安卓不行
记录下我参考的教程
https://www.jianshu.com/p/443c905e58a3
https://www.jianshu.com/p/b3c4450f845e