微信自定义分享(java)config:fail,Error: invalid signature,updateTimelineShareData:fail the permission value

之前做过一次自定义分享,可能碰巧前端没问题,各个参数碰巧都是对的,整个过程很顺利;

可最近做另个微信应用的自定义分享遇到的坑,找了老半天,最终解决,特记录一下;

异常1:config:fail,Error: invalid signature

异常2:updateTimelineShareData:fail the permission value is offline verifying

关于前面错误的,百度了好久,有用信息很少,无力吐槽,很多说加密的url必须和分享的link一致,这个纯属放屁,你分享的link只需要在授权域名下面就ok了,可以是另外的地址,比如我写的就是我微信应用授权地址,别人点击授权完直接访问主页;

首先你的后台加密部分要没有问题,下面的方法才可能帮助到你;

被这两个异常折磨了好久,对于异常一,当时写的过程中,怎么都查都查不出来,去验签平台验签也没问题,分享就是会提示签名错误,现在看来只能是自己对官方文档没细心看,对于这个问题如果你也和我一样,验签没问题,那么明确告诉你,是你的加密时用的url错了(******注意这个加密时用的url必须是你请求页面的url一样,连参数都要带上********)

比如我当前调用后台获取签名的页面是:http://wx.abdfc.com/wxGame/test/result.html?&number=125;那么你后台生成签名加密时用的url也要是这个;页面可以通过

window.location.href.split('#')[0] 方式获取url,传到后台,最后会贴一下我的关键代码

ps:其实遇到这种问题都是,当时开发时进了死胡同,没有真正看清微信开发文档的描述,建议开发时详细查看微信开发文档;

贴一下微信分享接口关于加密部分的说明:

附录1-JS-SDK使用权限签名算法

jsapi_ticket

生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。

1.参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):../15/54ce45d8d30b6bf6758f68d2e95bc627.html

2.用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

成功返回如下JSON:

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

获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。

签名算法

签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。

即signature=sha1(string1)。 示例:

noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
url=http://mp.weixin.qq.com?params=value

步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:

jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value

步骤2. 对string1进行sha1签名,得到signature:

0f9de62fce790f9a083d5c99e95740ceb90c27ed

注意事项

1.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。

2.签名用的url必须是调用JS接口页面的完整URL。

3.出于安全考虑,开发者必须在服务器端实现签名的逻辑。

如出现invalid signature 等错误详见附录5常见错误及解决办法

 

对于异常2(updateTimelineShareData:fail the permission value is offline verifying),我个人认为是引入的js版本不对,没有找到相应的函数;

最后贴一下我的代码:

前端页面:(***注:我用的js版本是<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>)

initWeixinAPI(){
                var _this = this;
                var urld = window.location.href.split('#')[0];
                $.ajax({
                    type: "get",
                    url: host + "/wxGame/getSignInfo",
                    data: {
                        url: urld
                    },
                    success: function(data) {
                        _this.signature = data.signature; // 签名
                        _this.appId =data.appId; // 应用id
                        _this.jsapi_ticket =data.jsapi_ticket; // 票据
                        _this.nonceStr =data.nonceStr; // 随机串
                        _this.url =data.signature; // 路径
                        _this.timestamp =data.timestamp; // 时间戳
                        _this.yaoqing();
                    },
                    error: function(e) {
                        console.log('获取用户信息失败');
                    }
                });
            },
            yaoqing(){
                var _this = this;
                _this.isTrue = true;debugger;
                wx.config({
                    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId: _this.appId, // 必填,企业号的唯一标识,此处填写企业号corpid
                    timestamp: _this.timestamp, // 必填,生成签名的时间戳
                    nonceStr: _this.nonceStr, // 必填,生成签名的随机串
                    signature: _this.signature,// 必填,签名,见附录1
                    jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                });
                wx.ready(function() {
                    wx.onMenuShareAppMessage({
                        title: '我的情商已经满分,你要不要来测一下', // 分享标题
                        desc: '权威情商测试,帮你清除认识自己', // 分享描述
                        link:host +'/wxGame/toOauth', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                        imgUrl: host+'/wxGame/test/img/logo.png', // 分享图标
                        success: function () {
                            vant.Toast('分享成功');
                        },
                        cancel: function () {
                            vant.Toast('取消分享');
                        }
                    });
                    wx.onMenuShareTimeline({
                        title: '我的情商已经满分,你要不要来测一下', // 分享标题
                        link: host +'/wxGame/toOauth', // 分享链接,该链接域名必须与当前企业的可信域名一致
                        imgUrl: host+'/wxGame/test/img/logo.png', // 分享图标
                        success: function () {
                            vant.Toast('已分享至朋友圈');
                        },
                        cancel: function () {
                            vant.Toast('取消分享');
                        }
                    });
                });

后台对应接口实现:(由于我用的后端框架是jfinal,里面集成了微信获取相关票据的接口,我就补贴代码,能看到这里后台逻辑一般没什么问题了,注意一下坑点就行)

public void getSignInfo() {

		JsTicket jsApiTicket = JsTicketApi.getTicket(JsTicketApi.JsApiType.jsapi);
		String jsapi_ticket = jsApiTicket.getTicket();
		String nonce_str = create_nonce_str();
		// 注意 URL 一定要动态获取,不能 hardcode.
		System.out.println("url>>>>" + url);
		String url = getPara("url");
		String timestamp = create_timestamp();
		// 这里参数的顺序要按照 key 值 ASCII 码升序排序
		//注意这里参数名必须全部小写,且必须有序
		String  str = "jsapi_ticket=" + jsapi_ticket +
				"&noncestr=" + nonce_str +
				"&timestamp=" + timestamp +
				"&url=" + url;

		String signature = HashKit.sha1(str);

		System.out.println("appId " + ApiConfigKit.getApiConfig().getAppId()
				+ "  nonceStr " + nonce_str + " timestamp " + timestamp);
		System.out.println("url " + url + " signature " + signature);
		System.out.println("nonceStr " + nonce_str + " timestamp " + timestamp);
		System.out.println(" jsapi_ticket " + jsapi_ticket);
		System.out.println("nonce_str  " + nonce_str);
		setAttr("appId", ApiConfigKit.getApiConfig().getAppId());
		setAttr("nonceStr", nonce_str);
		setAttr("timestamp", timestamp);
		setAttr("url", url);
		setAttr("signature", signature);
		setAttr("jsapi_ticket", jsapi_ticket);
		Map map =new HashMap();
		map.put("appId", ApiConfigKit.getApiConfig().getAppId());
		map.put("nonceStr", nonce_str);
		map.put("timestamp", timestamp);
		map.put("url", url);
		map.put("signature", signature);
		map.put("jsapi_ticket", jsapi_ticket);
		renderJson(JsonUtils.toJson(map));

	}

以上就是我遇到的问题及解决,希望能帮助到同样遇到问题的你;

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值