300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 微信分享功能(分享到朋友和朋友圈显示图片和简介)

微信分享功能(分享到朋友和朋友圈显示图片和简介)

时间:2023-10-16 09:50:14

相关推荐

微信分享功能(分享到朋友和朋友圈显示图片和简介)

想在微站里面实现分享帖子给朋友和朋友圈,显示图片和简介,就这么简单的功能折腾了1星期。。。主要是微信官方文档没看清楚,怪自己了。

官方文档在这里,https://mp./wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html

参考/stoneniqiu/p/6286599.html这篇文章。

遇到invalid signature签名错误。找了半天,各种调试,终于找到问题了,每个新闻的id是变动的,

url需要传入完整的地址,在微信官方手册里面查到的。

比如页面是/wx.aspx?id=111,需要完整传入,不能仅仅在url里面传入/wx.aspx

下面是stoneniqiu 的具体做法,大家可以参考一下。

内嵌在微信中的网页,右上角都会有一个默认的分享功能。如下图所示,第一个为自定义的效果,第二个为默认的效果。实现了自定义的分享链接是不是更让人有点击的欲望?下面讲解下开发的过程。

一、准备,设置js接口安全域名

这需要使用微信的jssdk,先需要在微信公众号后台进行设置:公众号设置-->功能设置-->JS接口安全域名。打开这个页面之后你会看到下面的提示。需要先下载这个文件并上传到指定域名的根目录。

这个文件里面是一个字符串,从名称看是用来校验用的。先上传了这个文件,你才能保存成功。这样你就可以使用jssdk了。

二、前端配置

首先要说明的是分享功能是一个配置功能,绑定在按钮的click事件中是没有效果的。也就是说只有点击右上角的分享才有效果(有的文字内容分享不知道是怎么实现的)。官方的js有四个步骤,首先是引入jssdk:

<script src="http://res./open/js/jweixin-1.1.0.js"></script>

根据官方的配置参数,我们可以定义一个WXShareModel对象:

public class WXShareModel{public string appId { get; set; }public string nonceStr { get; set; }public long timestamp { get; set; }public string signature { get; set; }public string ticket { get; set; }public string url { get; set; }public void MakeSign(){var string1Builder = new StringBuilder();string1Builder.Append("jsapi_ticket=").Append(ticket).Append("&").Append("noncestr=").Append(nonceStr).Append("&").Append("timestamp=").Append(timestamp).Append("&").Append("url=").Append(url.IndexOf("#") >= 0 ? url.Substring(0, url.IndexOf("#")) : url);var string1 = string1Builder.ToString();signature = Util.Sha1(string1, Encoding.Default);}}

然后是进行配置:

wx.config({debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId: '@Model.appId', // 必填,公众号的唯一标识timestamp: '@Model.timestamp', // 必填,生成签名的时间戳nonceStr: '@Model.nonceStr', // 必填,生成签名的随机串signature: '@Model.signature',// 必填,签名,见附录1jsApiList: ["checkJsApi", "onMenuShareTimeline", "onMenuShareAppMessage", "onMenuShareQQ", "onMenuShareQZone"] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2});wx.ready(function () {document.querySelector('#checkJsApi').onclick = function () {wx.checkJsApi({jsApiList: ['getNetworkType','previewImage'],success: function (res) {alert(JSON.stringify(res));}});};//朋友圈wx.onMenuShareTimeline({title: '暖木科技', // 分享标题link: '/home/lampindex', // 分享链接imgUrl: '/images/s1.jpg',success: function (res) {alert('已分享');},cancel: function (res) {alert('已取消');},fail: function (res) {alert(JSON.stringify(res));}});//朋友wx.onMenuShareAppMessage({title: '暖木科技', // 分享标题desc: '宝宝的睡眠很重要,你的睡眠也很重要', // 分享描述link: '/home/lampindex', // 分享链接imgUrl: '/images/s1.jpg', // 分享图标type: '', // 分享类型,music、video或link,不填默认为linkdataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空success: function () {// 用户确认分享后执行的回调函数alert("分享");},cancel: function () {// 用户取消分享后执行的回调函数alert("取消分享");}});});

然后剩下就是后端的事情了。后端的关键是获取access_token和jsapi_ticket以及生成正确的签名。另外如果要统计分享的数量,最好就是在success方法中进行统计了。

三、生成签名

1.access_token

获取access_token方法全平台都是一致的。

public const string AccessTokenUrl = "https://api./cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";

public TokenResult GetAccessToken(){var url = string.Format(WxDeviceConfig.AccessTokenUrl, WxDeviceConfig.AppId, WxDeviceConfig.APPSECRET);var res = SendHelp.Send<TokenResult>(null, url, null, CommonJsonSendType.GET);return res;}

access_token的超时时间是7200秒,所以先可以缓存起来。SendHelp文章末尾可下载

2.获取jsapi_ticket

access_token的作用就是为了获取jsapi_ticket。用get方式获取,url:https://api./cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi,返回的JSON对象如下。

{"errcode":0,"errmsg":"ok","ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA","expires_in":7200}

所以可以定义一个模型:

public class jsapiTicketModel{public string errcode { get; set; }public string errmsg { get; set; }public string ticket { get; set; }public string expires_in { get; set; }}

再完成获取ticket的方法:

public jsapiTicketModel GetJsApiTicket(string accessToken){var url = string.Format(WxPayConfig.Jsapi_ticketUrl, accessToken);return SendHelp.Send<jsapiTicketModel>(accessToken, url, "", CommonJsonSendType.GET);}

ticket过期时间也是7200秒,并且不能频繁的请求,所以也需要再服务端缓存起来。

private void setCacheTicket(string cache){_cacheManager.Set(tokenKey, cache, 7200);}

MemoryCacheManager:

View Code

3.签名

终于到这一步了,然后你在文档中看到让你失望的一幕:

么有C#的demo,支付那边都提供了,为啥jssdk没有提供,好吧先不吐槽了。官方也说明白签名的规则。一开始我使用的是/night-king/weixinSDK中的签名:

public static string Sha1(string orgStr, string encode = "UTF-8"){var sha1 = new SHA1Managed();var sha1bytes = System.Text.Encoding.GetEncoding(encode).GetBytes(orgStr);byte[] resultHash = puteHash(sha1bytes);string sha1String = BitConverter.ToString(resultHash).ToLower();sha1String = sha1String.Replace("-", "");return sha1String;}//错误示例

得出的结果和官方校验的不一致,一直提示签名错误。

正确的写法是:

public static string Sha1(string orgStr, Encoding encode){SHA1 sha1 = new SHA1CryptoServiceProvider();byte[] bytes_in = encode.GetBytes(orgStr);byte[] bytes_out = puteHash(bytes_in);sha1.Dispose();string result = BitConverter.ToString(bytes_out);result = result.Replace("-", "");return result; }

和官方校验的结果一直后,就ok了(忽略大小写)。另外一个需要注意的地方是签名中的url。如果页面有参数,model中的url也需要带参数,#号后面的不要。不然也是会报签名错误。

public ActionResult H5Share(){var model = new WXShareModel();model.appId = WxPayConfig.APPID;model.nonceStr = WxPayApi.GenerateNonceStr();model.timestamp = Util.CreateTimestamp();model.ticket = GetTicket();model.url = "/AuthWeiXin/share";// domain + Request.Url.PathAndQuery;model.MakeSign();Logger.Debug("获取到ticket:" + model.ticket);Logger.Debug("获取到签名:" + model.signature);return View(model);}

四、小结

wx.config中的debug为true会alert各种操作结果。参数正确之后界面会提示:

至此,分享的功能就ok了。也就打开了调用其他jssdk的大门。另外文中的SendHelp对象是用的Senparc(基于.net4.5)的dll。

参考资料:

签名校验:https://mp./debug/cgi-bin/sandbox?t=jsapisign

官方文档:https://mp./wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html

我的核心代码

[System.Web.Services.WebMethod]public static WXShareModel GetKey(string str){WXShareModel aModel = new WXShareModel();WXToolsHelper tb = new WXToolsHelper();string AppId = "你的APPID";string secret = "你的secret";string access_token = tb.GetAccess_Token(AppId, secret);aModel.appId = AppId;aModel.nonceStr = tb.CreatenNonce_str();aModel.timestamp = tb.CreatenTimestamp();aModel.ticket = tb.GetTicket(access_token);aModel.url = str;aModel.MakeSign();return aModel;}public class WXShareModel{public string appId { get; set; }public string nonceStr { get; set; }public long timestamp { get; set; }public string ticket { get; set; }public string url { get; set; }public string signature { get; set; }public void MakeSign(){var string1Builder = new StringBuilder();string1Builder.Append("jsapi_ticket=").Append(ticket).Append("&").Append("noncestr=").Append(nonceStr).Append("&").Append("timestamp=").Append(timestamp).Append("&").Append("url=").Append(url.IndexOf("#") >= 0 ? url.Substring(0, url.IndexOf("#")) : url);var string1 = string1Builder.ToString();signature = Sha1(string1, Encoding.Default);}public static string Sha1(string orgStr, Encoding encode){SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();byte[] bytes_in = encode.GetBytes(orgStr);byte[] bytes_out = puteHash(bytes_in);sha1.Dispose();string result = BitConverter.ToString(bytes_out);result = result.Replace("-", "");return result;}public class WXToolsHelper{/// <summary>/// 获取全局的access_token,程序缓存/// </summary>/// <param name="AppId">第三方用户唯一凭证</param>/// <param name="AppSecret">第三方用户唯一凭证密钥,即appsecret</param>/// <returns>得到的全局access_token</returns>public string GetAccess_Token(string AppId, string AppSecret){try{//先查缓存数据if (HttpContext.Current.Cache["access_token"] != null){return HttpContext.Current.Cache["access_token"].ToString();}else{return GetToken(AppId, AppSecret);}}catch{return GetToken(AppId, AppSecret);}}/// <summary>/// 获取全局的access_token/// </summary>/// <param name="AppId">第三方用户唯一凭证</param>/// <param name="AppSecret">第三方用户唯一凭证密钥,即appsecret</param>/// <returns>得到的全局access_token</returns>public string GetToken(string AppId, string AppSecret){var client = new .WebClient();client.Encoding = System.Text.Encoding.UTF8;var url = string.Format("https://api./cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", AppId, AppSecret);var data = client.DownloadString(url);var jss = new JavaScriptSerializer();var access_tokenMsg = jss.Deserialize<Dictionary<string, object>>(data);//放入缓存中HttpContext.Current.Cache.Insert("access_token", access_tokenMsg["access_token"], null, DateTime.Now.AddSeconds(7100), TimeSpan.Zero, CacheItemPriority.Normal, null);//清除jsapi_ticket缓存HttpContext.Current.Cache.Remove("ticket");//获取jsapi_ticket,为了同步GetTicket(access_tokenMsg["access_token"].ToString());return access_tokenMsg["access_token"].ToString();}/// <summary>/// 获取jsapi_ticket,程序缓存/// </summary>/// <param name="access_token">全局的access_token</param>/// <returns>得到的jsapi_ticket</returns>public string GetJsapi_Ticket(string access_token){try{//先查缓存数据if (HttpContext.Current.Cache["ticket"] != null){return HttpContext.Current.Cache["ticket"].ToString();}else{return GetTicket(access_token);}}catch{return GetTicket(access_token);}}/// <summary>/// 获取jsapi_ticket/// </summary>/// <param name="access_token">全局的access_token</param>/// <returns>得到的jsapi_ticket</returns>public string GetTicket(string access_token){var client = new .WebClient();client.Encoding = System.Text.Encoding.UTF8;var url = string.Format("https://api./cgi-bin/ticket/getticket?access_token={0}&type=jsapi", access_token);var data = client.DownloadString(url);var jss = new JavaScriptSerializer();var ticketMsg = jss.Deserialize<Dictionary<string, object>>(data);try{//放入缓存中HttpContext.Current.Cache.Insert("ticket", ticketMsg["ticket"], null, DateTime.Now.AddSeconds(7100), TimeSpan.Zero, CacheItemPriority.Normal, null);return ticketMsg["ticket"].ToString();}catch (Exception ex){return ex.Message;}}/// <summary>/// 微信权限签名的 sha1 算法/// 签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同/// </summary>/// <param name="jsapi_ticket">获取到的jsapi_ticket</param>/// <param name="noncestr">生成签名的随机串</param>/// <param name="timestamp">生成签名的时间戳</param>/// <param name="url">签名用的url必须是调用JS接口页面的完整URL</param>/// <returns></returns>public string GetShal(string jsapi_ticket, string noncestr, long timestamp, string url){string strSha1 = string.Format("jsapi_ticket={0}&noncestr={1}&timestamp={2}&url={3}", jsapi_ticket, noncestr, timestamp, url);return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(strSha1, "sha1").ToLower();}/// <summary>/// 微信权限签名( sha1 算法 )/// 签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同/// </summary>/// <param name="AppId">第三方用户唯一凭证</param>/// /// <param name="AppSecret">第三方用户唯一凭证密钥,即appsecret</param>/// <param name="noncestr">生成签名的随机串</param>/// <param name="timestamp">生成签名的时间戳</param>/// <param name="url">签名用的url必须是调用JS接口页面的完整URL</param>/// <returns></returns>public string Get_Signature(string AppId, string AppSecret, string noncestr, long timestamp, string url){string access_token = GetAccess_Token(AppId, AppSecret); //获取全局的access_tokenstring jsapi_ticket = GetJsapi_Ticket(access_token); //获取jsapi_ticketstring strSha1 = string.Format("jsapi_ticket={0}&noncestr={1}&timestamp={2}&url={3}", jsapi_ticket, noncestr, timestamp, url);return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(strSha1, "sha1").ToLower();}/// <summary>/// 微信权限签名( sha1 算法 )/// 签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同/// </summary>/// <param name="AppId">第三方用户唯一凭证</param>/// /// <param name="AppSecret">第三方用户唯一凭证密钥,即appsecret</param>/// <param name="noncestr">生成签名的随机串</param>/// <param name="timestamp">生成签名的时间戳</param>/// <param name="url">签名用的url必须是调用JS接口页面的完整URL</param>/// <returns></returns>public void signatureOut(string AppId, string AppSecret, string noncestr, long timestamp, string url, out string access_token, out string jsapi_ticket, out string signature){access_token = GetAccess_Token(AppId, AppSecret); //获取全局的access_tokenjsapi_ticket = GetJsapi_Ticket(access_token); //获取jsapi_ticketstring strSha1 = string.Format("jsapi_ticket={0}&noncestr={1}&timestamp={2}&url={3}", jsapi_ticket, noncestr, timestamp, url);signature = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(strSha1, "sha1").ToLower();}private string[] strs = new string[]{"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};/// <summary>/// 创建随机字符串 /// </summary>/// <returns></returns>public string CreatenNonce_str(){Random r = new Random();var sb = new StringBuilder();var length = strs.Length;for (int i = 0; i < 15; i++){sb.Append(strs[r.Next(length - 1)]);}return sb.ToString();}/// <summary>/// 创建时间戳 /// </summary>/// <returns></returns>public long CreatenTimestamp(){return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000;}}

前段调用

var strUrl = location.href.split('#')[0];$.ajax({type: "Post",url: "config.aspx/GetKey",//方法传参的写法一定要对,strUrl为形参的名字 data: "{'str':'" + strUrl + "'}",contentType: "application/json; charset=utf-8",dataType: "json",success: function (data) {//返回的数据用data.d获取内容 $("#wx-share-sign").val(data.d.signature);wxconifg(data.d);},error: function (err) {alert('55');}});function wxconifg(WXDate) {wx.config({debug: false,appId: '你的APPID',timestamp: WXDate.timestamp,nonceStr: WXDate.nonceStr,signature: WXDate.signature,jsApiList: ["checkJsApi", "onMenuShareTimeline", "onMenuShareAppMessage", "onMenuShareQQ", "onMenuShareQZone"]});wx.ready(function () {wx.onMenuShareAppMessage({title: $("#wx-share-title").val(),desc: $("#wx-share-desc").val(),link: strUrl,imgUrl: $("#wx-share-img").val(),trigger: function (res) {},success: function (res) {},cancel: function (res) {},fail: function (res) {alert(JSON.stringify(res));}});//分享到朋友圈 wx.onMenuShareTimeline({title: 'XX新闻|'+$("#wx-share-desc").val(),desc: $("#wx-share-desc").val(),link: $("#wx-share-link").val(),imgUrl: $("#wx-share-img").val(),type: 'link',dataUrl: strUrl,trigger: function (res) {},success: function (res) {},cancel: function (res) {},fail: function (res) {alert(JSON.stringify(res));}});});}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。