最近写的微信分享功能,调试一个签名就用了一天时间,主要还是微信的API有点难看得懂吧!主要是调用JS-SDK时,生成签名花费了很长时间调试,到最后才发现原来是原来是自己配置做错了。

    先看看官方的JS-SDK使用步骤:

    步骤一:绑定域名

    步骤二:引入JS文件


步骤三:通过config接口注入权限验证配置


    值得一提的是第一步,绑定域名一定是去掉“http://”或者"https://"(我就是在这里花费了很长时间调试),在公众号测试系统填写

JS接口安全域名

如下图所示:

java 微信公众号群发 java微信公众号消息推送_java 微信公众号群发




在需要调用JS接口的页面引入如下JS文件,(支持https): http://res.wx.qq.com/open/js/jweixin-1.2.0.js


    最重要的一步还是在java中获取jsapi_ticket,并且通过一系列操作得到一个签名;其主要步骤是:


  1、获取access_token(普通的access_token),通过access_token获取jsapi_ticket,主要注意的是,jsapi_ticket和access_token每一天都是有使用次数限制的,超时时间是7200s,所以在使用的时候需要保存到全局变量或者数据库或者是redis等,并且需要写一个定时器,在7200s后重新获取这两个值,刷新到保存的区域中;以下是我获取access_token的方法:

public AccessToken getAccessToken(@Context HttpServletRequest req, @Context HttpServletResponse resp) throws ClientProtocolException, IOException{
				HttpSession httpSession = req.getSession();
				AccessToken token = new AccessToken();
		        String url = ACCESS_TOKEN_URL;
		        JSONObject jsonObject = WeiXinUtil.doGetStr(url);//使用刚刚写的doGet方法接收结果
		        if(jsonObject!=null){ //如果返回不为空,将返回结果封装进AccessToken实体类
		            token.setToken(jsonObject.getString("access_token"));//取出access_token
		            token.setExpiresIn(jsonObject.getInt("expires_in"));//取出access_token的有效期
		            httpSession.setAttribute("access_token", token.getToken());
		            System.out.println("授权获取的token==="+jsonObject.getString("access_token"));
		            Contants.ACCESS_TOKEN=jsonObject.getString("access_token");
		            Contants.token_expires_in=jsonObject.getInt("expires_in");
		        }
		        return token;
		}

 2、获取jsapi_ticket的主要实现方法如下:

public void getJsapi_ticket(@Context HttpServletRequest req, @Context HttpServletResponse resp) throws ClientProtocolException, IOException{
			String  access_token=Contants.ACCESS_TOKEN;
			System.out.println("access_token==="+access_token);
			String url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_token+"&type=jsapi";
			JSONObject jsonObject=WeiXinUtil.doGetStr(url);
			System.out.println(jsonObject);
			String ticket=jsonObject.getString("ticket");
			Contants.JSAPI_TICKET=jsonObject.getString("ticket");
			Contants.ticket_expires_in=jsonObject.getInt("expires_in");
		}

通过config接口注入权限验证配置,在这个步骤,需要几个参数是要和服务器保持一致的:


wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳(由开发者生成)
    nonceStr: '', // 必填,生成签名的随机串 (由开发者生成)
    signature: '',// 必填,签名  *(接下来计算这一个值是关键步骤)
    jsApiList: [] // 必填,需要使用的JS接口列表
});

以下是生成JS-SDK配置文件所需要的参数的步骤和代码:

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

public WxParam getEncryptJsapiTicket(@Context HttpServletRequest req , @Context HttpServletResponse resp, @RequestParam("url") String url) throws UnsupportedEncodingException {
			String ticket=Contants.JSAPI_TICKET;
			String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//随机生成的时间戳
			String noncestr = CommonUtil.getRandomString(16);//生成的16位随机码
			String url1=java.net.URLDecoder.decode(url.split("=")[1],"UTF-8");//在调用js的页面完整URL
			String signature=getSignature(url1, timestamp, noncestr);//开始进行sha1签名
			WxParam wxparam=new WxParam();
			wxparam.setNonce(noncestr);
			wxparam.setSignature(signature);
			wxparam.setTimestamp(timestamp);
			return wxparam;
		}

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

public static String getSignature(String url,String timeStamp,String nonceStr){  
			//所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:
			String signValue = "jsapi_ticket="+Contants.JSAPI_TICKET+"&noncestr="+nonceStr+"×tamp="+timeStamp+"&url="+url;  
			String signature =DigestUtils.sha1Hex(signValue);
			return signature;    
		}

    到这里,生成页面需要的参数步骤已经完成了,这个时候需要在页面初始化的时候调用这个方法,获取相关参数,填充到we.config中即可调用成功。如果在开发过程中遇到报错,可以看微信的api附录,每一个报错信息都有对应的说明:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

    接下来是时候贴一下页面的代码啦!

<script type="text/javascript">
  var basePath= "<%=basePath%>";
  var nonce="";//生成签名的随机串
  var signature="";//签名
  var timestamp="";//时间戳
  var title="恭喜你!中奖啦!快戳我查看吧!";
  var desc="原来中奖的感觉是那么美好!";
  var sharLink="http://7ef60179.ngrok.io/wxh5/interestbills/index.jsp";
  var imgUrl="http://7ef60179.ngrok.io/wxh5/interestbills/images/test.jpg";
  $(document).ready(function(){  
	  var url = encodeURI(location.href.split('#')[0]);
	  console.log("url=="+url);
	  $.ajax({
	         url: "./rest/wx/sdk/getEncryptJsapiTicket",
	         type: "POST",
	         data:{"url":url},
	         dataType: "json",
	         success: function(data){
	             console.log(data);
	             nonce=data.nonce;
	             signature=data.signature;
	             timestamp=data.timestamp;
	             loadWx();
	          },
	          error:function(err){
	            console.log('异常');
	          }
	        });
  }); 
  function loadWx(){
	  wx.config({
		    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
		    appId: 'wx733b07f00930f0df', // 必填,公众号的唯一标识
		    timestamp: timestamp, // 必填,生成签名的时间戳
		    nonceStr: nonce, // 必填,生成签名的随机串
		    signature: signature,// 必填,签名
		    jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表
		});
	  wx.ready(function(){
		  //分享到朋友圈
		  wx.onMenuShareTimeline({
			    title: title, // 分享标题
			    link: sharLink, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
			    imgUrl: imgUrl, // 分享图标
			    success: function () {
			    	alert("分享成功");
			    // 用户确认分享后执行的回调函数
				},
			cancel: function () {
				alert("分享失败");
			    // 用户取消分享后执行的回调函数
		    }
		});
		  //分享到朋友
		  wx.onMenuShareAppMessage({
			  title: title, // 分享标题
			  desc: desc, // 分享描述
			  link: sharLink, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
			  imgUrl: imgUrl, // 分享图标
			  type: 'link', // 分享类型,music、video或link,不填默认为link
			  dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
			  success: function () {
				  alert("分享成功");
			  // 用户确认分享后执行的回调函数
			  },
			  cancel: function () {
				  alert("分享失败");
			  // 用户取消分享后执行的回调函数
			  }
			  });
		  //分享到QQ
		  wx.onMenuShareQQ({
			  title: title, // 分享标题
			  desc: desc, // 分享描述
			  link: sharLink, // 分享链接
			  imgUrl: imgUrl, // 分享图标
			  success: function () {
				  alert("分享成功");
			  // 用户确认分享后执行的回调函数
			  },
			  cancel: function () {
				  alert("分享失败");
			  // 用户取消分享后执行的回调函数
			  }
			  });
		  //分享到腾讯微博
		  wx.onMenuShareWeibo({
			  title: title, // 分享标题
			  desc: desc, // 分享描述
			  link: sharLink, // 分享链接
			  imgUrl: imgUrl, // 分享图标
			  success: function () {
			  // 用户确认分享后执行的回调函数
			  },
			  cancel: function () {
			  // 用户取消分享后执行的回调函数
			  }
			  });
		  //分享到QQ空间
		  wx.onMenuShareQZone({
			  title: titlec, // 分享标题
			  desc: desc, // 分享描述
			  link: sharLink, // 分享链接
			  imgUrl: imgUrl, // 分享图标
			  success: function () {
			  // 用户确认分享后执行的回调函数
			  },
			  cancel: function () {
			  // 用户取消分享后执行的回调函数
			  }
			  });
	  });
	  wx.error(function(res){
		alert("验证失败了");
	  });
	  
  }
  
  
  </script>



    看看我的分享效果:

java 微信公众号群发 java微信公众号消息推送_java 微信公众号群发_02

java 微信公众号群发 java微信公众号消息推送_回调函数_03

java 微信公众号群发 java微信公众号消息推送_json_04