微信网页JS分享,微信二次分享无缩略图问题
很多时候我们要在微信中分享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 + "×tamp=" + 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
微信网页JS分享,微信二次分享无缩略图问题的更多相关文章
- VueJs单页应用实现微信网页授权及微信分享功能
		
在实际开发中,无论是做PC端.WebApp端还是微信公众号等类型的项目的时候,或多或少都会涉及到微信相关的开发,最近公司项目要求实现微信网页授权,并获取微信用户基本信息的功能及微信分享的功能,现在总算 ...
 - 手把手实现微信网页授权和微信支付,附源代码(VUE and thinkPHP)
		
wechat github 手把手实现微信网页授权和微信支付,附源代码(VUE and thinkPHP) 概述 公众号开发是痛苦的,痛苦在好多问题开发者文档是没有提到的,是需要你猜的. 在开发过程中 ...
 - 微信公众号jssdk自定义分享,二次分享自定义失败解决技巧
		
百度上自定义微信分享标题以及描述的解决方法有很多,基本上都能实现一次分享:流程基本上是这样的 1.首先引入微信jssdk =><script src="http://res.wx ...
 - 微信网页开发调用微信jssdk接口遇到的坑以及最终解决方法 (持续更新)
		
1.微信网页开发调用jssdk时报permission denied 大致是两个原因 (1)首先注册时未将你所调用的接口名字添加至jsApiList (2)第二个就是你的这个公众号没有权限使用这个ap ...
 - h5聊天室web端(仿微博、微信)|h5仿微信网页端|仿微信界面弹窗
		
这段时间一直在着手h5开发手机端聊天系统——html5仿微信聊天室,最近又在原先基础上开发了一个仿微信.微博网页web版聊天系统,使用到了HTML5+css3+jQuery+wcpop等技术开发,弹窗 ...
 - 微信、qq二次分享
		
前言 我们平时做微信分享的时候,一般分享出来的页面都是一个简单的html页面,不会加入框架之类的东西.所以当我们在分享出来的页面里面再次进行分享的时候,由于我们没有配置分享的标题.描述这些东西,分享出 ...
 - 服务号使用微信网页授权(H5应用等)
		
获取授权准备 AppId 服务号已经认证且获取到响应接口权限 设置网页授权域名 公众号设置 - 功能设置 - 网页授权域名.注意事项: 回调页面域名或路径需使用字母.数字及"-"的 ...
 - [微信小程序] 认识微信小程序及开发环境搭建
		
微信公众平台首页 https://mp.weixin.qq.com 微信公众平台测试帐号系统 https://open.weixin.qq.com/connect/qrconnect?appid=wx ...
 - 微信、qq网页二次分享
		
二次分享是指,在APP或者浏览器分享到微信或者qq,然后从微信或者qq再分享到别的平台.如果不处理,再次分享出去的图片或者标题就不会显示,对用户非常不友好. 一.微信二次分享 官方接入文档:https ...
 
随机推荐
- openwrt中防暴力破解shell的脚本
			
原文:http://www.right.com.cn/forum/thread-124429-1-1.html 原理:1. snort做入侵检测是很好,但是太大太复杂,我们需要轻量化的操作.当对方进行 ...
 - WebRequest + Https + 憑証錯誤 = 作業逾時
			
前言 一般的系統一登入時,都會顯示公告訊息,我們的系統也是! 因為系統效能問題,所以就幫忙看了程式.發現,每次登入時,都會到DB取公告資料,但公告並不會因為個人而有所不同,是針對整個系統的呀! 所以就 ...
 - 通过给事件处理程序传递this参数,获取事件源对象的引用。单机提交按钮时在信息框中显示用户输入的字符。
			
<script> function mymethod(str) { alert("您输入的是:"+str); } </script><form act ...
 - 多线程  死锁 wait(int i) notifyAll()
			
public class ThreadDemo5 { public static void main(String[] args){ Pool pool = new Pool(); Productor ...
 - iOS修改状态栏颜色
			
application.statusBarStyle = .LightContent // 在APPlication中设置全局状态栏颜色,为白色 application.statusBarHidden ...
 - property 、classmethod 、 staticmethod 的用法
			
@property # property是一个装饰器函数 ,作用:将一个方法伪装成属性 # 所有的装饰器函数都怎么用? 在函数.方法.类的上面一行直接@装饰器的名字 # 装饰器的分类: # 装饰函数 ...
 - 05_ssm基础(三)之Spring基础
			
11.spring入门引导 12.spring_HelloWord程序 实现步骤: 0.找到spring压缩包,并解压 1.拷贝jar包 2.添加主配置文件(官方文档约28页) 3.在测试中使用 13 ...
 - Python 第一个程序_1
			
第一个Python程序(P108) 目标 第一个HelloPython 程序 Python2.x与3.x版本简介 执行Python程序的三种方式 解释器--python/python3 (终端中.使 ...
 - lvm磁盘分区
			
初始分区情况见下: 创建lvm类型磁盘 创建卷pv 添加pv到vg中,vg名vgroup0 创建lv lvcreate -L 2g -n zookeeper vgroup0 在vg vgroup0中创 ...
 - java中几个happens-before规则
			
1. 程序顺序规则:一个线程中的每个操作,happens-before 该线程中的任意后续操作. 2.监视器锁规则:对一个锁的解锁, happens-before 于随后对这个锁的加锁操作 3.vol ...