微信网页JS分享,微信二次分享无缩略图问题

时间:2022-01-13 23:57:47

很多时候我们要在微信中分享h5网页,这个时候就得用微信的分享接口来自定义分享的地址、标题、描述、缩略图了。

分享到微信的时候遇到一个问题,就是第一次分享到微信里,是正确的,但是在微信打开分享的链接,再次分享的时候,发现小图片没了。

原因就是微信在你分享的时候,会自动给你分享的地址后面加入参数,导致你分享的地址改变了,这时候再去用原来的地址获取签名,就不能用了。

解决方法,动态获取地址:

var link = encodeURIComponent(location.href.split('#')[0]);//编码动态获取地址

var link = location.href.split('#')[0];//动态获取地址

代码:

 <script src="js/jquery.min.js"></script>
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script src="js/sha1.js"></script>
<script src="js/WeiXinShare.js"></script>
<script type="text/javascript">
//var link = "http://adv.xxx.com/Index.html";//原网页地址
//var link = encodeURIComponent(location.href.split('#')[0]);//编码动态获取地址
//var link = "http://adv.xxx.com/Index.html?from=groupmessage";//微信加入参数后的地址
var link = location.href.split('#')[];//动态获取当前地址,防止微信在原地址后加入参数 var imgUrl = "http://adv.xxx.com/img/fm.png";//缩略图地址
var apiUrl = "https://api.xxx.com/Common/GetSignature";//服务器端签名
var title = "这里是分享标题";
var desc = "这里是分享描述";
Share(link, imgUrl, title, desc, apiUrl);
</script>

Share函数代码:

function Share(link, imgUrl, title, desc, apiUrl) {
var randNum = Math.floor(Math.random(, ) * );
$.ajax({
url: apiUrl,
type: 'GET',
dataType: 'jsonp',
async: false,
data:
{
linkUrl: link,
randNum: randNum
}
}).done(function (d) {
//debugger;
ShareCallBack(d, link, imgUrl, title, desc);
}).fail(function () {
console.log("error");
}).always(function () {
});
} function ShareCallBack(d, link, imgUrl, title, desc) {
//debugger;
var appid = "";
var timestamp = "";
var noncestr = "";
var signature = "";
if (d.Data != undefined && d.Data != null) { var result = $.parseJSON(d.Data);
timestamp = result.timestamp;
noncestr = result.noncestr;
signature = result.signature;
appid = result.appid; //weixin begin
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: appid, // 必填,公众号的唯一标识
timestamp: timestamp, // 必填,生成签名的时间戳
nonceStr: noncestr, // 必填,生成签名的随机串
signature: signature, // 必填,签名,见附录1
jsApiList: ["onMenuShareTimeline", "onMenuShareAppMessage", "onMenuShareQQ", "onMenuShareWeibo", "onMenuShareQZone"]
//jsApiList 必填,需要使用的JS接口列表,所有JS接口列表见附录2
}); wx.ready(function () {
//获取“分享到朋友圈”按钮点击状态及自定义分享内容接口
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
wx.onMenuShareTimeline({
title: title, // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接
imgUrl: imgUrl, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
}); //获取“分享给朋友”按钮点击状态及自定义分享内容接口
wx.onMenuShareAppMessage({
title: title, // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接
imgUrl: imgUrl, // 分享图标
type: 'link', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
}); //获取“分享到QQ”按钮点击状态及自定义分享内容接口
wx.onMenuShareQQ({
title: title, // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接
imgUrl: imgUrl, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
//获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口
wx.onMenuShareWeibo({
title: title, // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接
imgUrl: imgUrl, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
//获取“分享到QQ空间”按钮点击状态及自定义分享内容接口
wx.onMenuShareQZone({
title: title, // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接
imgUrl: imgUrl, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
}); wx.error(function (res) { // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
}); });
//weixin end
}
}

服务器端签名:

/// <summary>
/// 获取微信 signature
/// </summary>
/// <param name="callback"></param>
[AcceptVerbs("GET")]
public void GetSignature(string callback, string linkUrl)
{
MessagesDataCodeModel json = new MessagesDataCodeModel(false, "无效参数", );
try
{
string AppId = "xxxxxxxx";//微信公众号官网签发的 appid和appsecret
string AppSecret = "xxxxxxx";
DateTime endDate = DateTime.Now.AddSeconds();
string token = "", ticket = "";
List<Models.WeiXinTokens> list = WeiXinTokensBLL.GetList();
if (list != null && list.Count > )
{
if (list[].EndDate > DateTime.Now)
{
token = list[].Token.Trim();
ticket = list[].Ticket.Trim();
}
} if (string.IsNullOrEmpty(token))
{
string result = Common.WeiXinHelper.GetJsApiTicket(AppId, AppSecret);
JavaScriptSerializer jss = new JavaScriptSerializer();
WeiXinTokenModel model = jss.Deserialize<WeiXinTokenModel>(result);
if (model != null)
{
Models.WeiXinTokens wxt = new Models.WeiXinTokens();
wxt.Token = model.token;
wxt.Ticket = model.ticket;
wxt.EndDate = endDate;
if (list.Count > )
{
wxt.ID = list[].ID;
WeiXinTokensBLL.ModifyEntity(wxt);
}
else
{
WeiXinTokensBLL.Append(wxt);
} token = model.token;
ticket = model.ticket;
}
}
else
{
Models.WeiXinTokens wxt = list[];
wxt.Token = token;
wxt.Ticket = ticket;
WeiXinTokensBLL.ModifyEntity(wxt);
} string noncestr = Guid.NewGuid().ToString().Replace("-", "");
int timestamp = Utils.ConvertDateTimeInt(DateTime.Now);
string key_str = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + linkUrl;
string signature = Utils.EncryptToSHA1(key_str);
string jsonStr = "{\"ticket\":\"" + ticket + "\",\"token\":\"" + token + "\",\"noncestr\":\"" + noncestr + "\",\"timestamp\":\"" + timestamp + "\",\"appid\":\"" + AppId + "\",\"signature\":\"" + signature + "\",\"url\":\"" + linkUrl + "\"}";
json.Success = true;
json.Msg = "操作成功";
json.Code = ;
json.Data = jsonStr;
}
catch (Exception ex)
{
json.Success = false;
json.Msg = "服务器无响应";
json.Code = ;
json.Data = -;
} string str = ToJsonTran.ToJson2(json);
if (!string.IsNullOrEmpty(callback))
{
str = callback + "(" + str + ")";
}
System.Web.HttpContext.Current.Response.Clear();
System.Web.HttpContext.Current.Response.Write(str);
System.Web.HttpContext.Current.Response.End();
}

辅助方法:

/// <summary>
/// C# SHA1散列算法
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string EncryptToSHA1(string str)
{
byte[] cleanBytes = Encoding.Default.GetBytes(str);
byte[] hashedBytes = System.Security.Cryptography.SHA1.Create().ComputeHash(cleanBytes);
return BitConverter.ToString(hashedBytes).Replace("-", "");
}
/// <summary>
/// DateTime时间格式转换为Unix时间戳格式
/// </summary>
/// <param name="time"> DateTime时间格式</param>
/// <returns>Unix时间戳格式</returns>
public static int ConvertDateTimeInt(System.DateTime time)
{
System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(, , ));
return (int)(time - startTime).TotalSeconds;
}

签名程序:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization; namespace Common
{
public class WeiXinHelper
{
public static string GetJsApiTicket(string AppId, string AppSecret)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
string result_token = GetAccessToken(AppId, AppSecret);
string result_jsapi_ticket = "";
if (!string.IsNullOrEmpty(result_token))
{
result_jsapi_ticket = GetJsApiTicketByToken(result_token);
}
return "{\"token\":\"" + result_token + "\",\"ticket\":\"" + result_jsapi_ticket + "\"}";
} /// <summary>
/// 获得微信AccessToken
/// 正常返回:{"access_token":"ACCESS_TOKEN","expires_in":7200}
/// 错误返回:{"errcode":40013,"errmsg":"invalid appid"}
/// </summary>
/// <param name="AppId"></param>
/// <param name="AppSecret"></param>
/// <returns></returns>
public static string GetAccessToken(string AppId, string AppSecret)
{
string url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + AppId + "&secret=" + AppSecret;
string result_token = "";
WebRequest webRequest = System.Net.HttpWebRequest.Create(url);
WebResponse webResponse = webRequest.GetResponse();
Stream stream = webResponse.GetResponseStream();
using (StreamReader sr = new StreamReader(stream))
{
result_token = sr.ReadToEnd();
} JavaScriptSerializer jss = new JavaScriptSerializer();
WeiXinAccessTokenResult atr = jss.Deserialize<WeiXinAccessTokenResult>(result_token);
if (!string.IsNullOrEmpty(atr.access_token))
{
return atr.access_token;
}
return "";
} public static string GetJsApiTicketByToken(string AccessToken)
{
string url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + AccessToken + "&type=jsapi";
string result = Utils.ClientRequest(url, "", "GET");
JavaScriptSerializer jss = new JavaScriptSerializer();
WeiXinJsApiTicketResult ticket_model = jss.Deserialize<WeiXinJsApiTicketResult>(result);
if (ticket_model.errcode == "")
{
return ticket_model.ticket;
}
return "";
}
}
public class WeiXinJsApiTicketResult
{
public string errcode { get; set; }
public string errmsg { get; set; }
public string ticket { get; set; }
public string expires_in { get; set; }
}
public class WeiXinAccessTokenResult
{
//正常返回:{"access_token":"ACCESS_TOKEN","expires_in":7200}
//错误返回:{"errcode":40013,"errmsg":"invalid appid"}
public string access_token { get; set; }
public string expires_in { get; set; }
public string errcode { get; set; }
public string errmsg { get; set; }
public string error { get; set; }
}
}

微信分享SDK:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115