微信企业号开发之获取jsapi_ticket并生成JS-SDK权限验证签名

在做企业号开发的时候,很有可能会调用微信提供的js接口(JS-SDK),   

那么使用JS-SDK必须生成权限验证签名,而生成权限验证签名又必须依赖jsapi_ticket,

而获取jsapi_ticket又必须依赖AccessToken,在上一篇文章介绍了获取AccessToken的方法,

本章就介绍一下如何获取jsapi_ticket并且怎样生成JS-SDK权限验证签名。

注:以下内容摘自微信官方

附录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):主动调用 - 企业号开发者接口文档
  2. 用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKE

成功返回如下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


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

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

注:以上内容摘自微信官方

上一篇文章里面已经写了一个springMvc的Controller,这里我们在里面再添加两个方法,代码如下:

package com.weixin.qiye;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.weixin.utils.SignUtil;

@Controller
@RequestMapping("/qiye")
public class QiyeController {

	private static final String CORPID="wxf75e84161068f7b7";
	private static final String CORPSECRET="BkN0-Orh2d1GI9quC9GnG3KsmApLumgStJfmH29TzsekCWv4eO_8aR8KTZOVdOBh";
	
	@RequestMapping("/getAccessToken")
	public void getAccessToken(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String urlStr = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid="+CORPID+"&corpsecret="+CORPSECRET;  
        <span style="white-space:pre">	</span>processUrl(response, urlStr);  
	}
	
	@RequestMapping("/getTsapiTicket")
	public void getTsapiTicket(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String access_token = request.getParameter("access_token");
		String urlStr = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token="+access_token;  
		processUrl(response, urlStr);  
	}
	@RequestMapping("/getJsSdkSign")
	public void getJsSdkSign(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String noncestr = request.getParameter("noncestr");
		String tsapiTicket = request.getParameter("jsapi_ticket");
		String timestamp = request.getParameter("timestamp");
		String url = request.getParameter("url");
		String jsSdkSign = SignUtil.getJsSdkSign(noncestr, tsapiTicket, timestamp, url);
		PrintWriter out = response.getWriter();
		out.print(jsSdkSign);
	}
	
	private void processUrl(HttpServletResponse response, String urlStr) {
		URL url;
		try {
			url = new URL(urlStr);
			URLConnection URLconnection = url.openConnection();  
			HttpURLConnection httpConnection = (HttpURLConnection)URLconnection;  
			int responseCode = httpConnection.getResponseCode();  
			if (responseCode == HttpURLConnection.HTTP_OK) {  
				InputStream urlStream = httpConnection.getInputStream();  
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlStream));  
				String sCurrentLine = "";  
				String sTotalString = "";  
				while ((sCurrentLine = bufferedReader.readLine()) != null) {  
					sTotalString += sCurrentLine;  
				}  
				PrintWriter out = response.getWriter();
				out.print(sTotalString);
			}else{
				System.err.println("失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

以上代码的getTsapiTicket方法用来获取jsapi_ticket,getJsSdkSign方法用来获取JS-SDK权限验证签名,在getJsSdkSign方法中有一个SignUtil类,用来生成签名,代码如下:

package com.weixin.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class SignUtil {

	public static boolean checkSignature(String signature,String timestamp,String nonce){
		String token="leonjo";
		String[] array=new String[]{token,timestamp,nonce};
		Arrays.sort(array);
		String content=array[0].concat(array[1]).concat(array[2]);
		String ciphertext=null;
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			byte[] digest = md.digest(content.toString().getBytes());
			ciphertext=byteToStr(digest);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return ciphertext!=null?ciphertext.equals(signature.toUpperCase()):false;
	}
	public static String getJsSdkSign(String noncestr,String tsapiTicket,String timestamp,String url){
		String content="jsapi_ticket="+tsapiTicket+"&noncestr="+noncestr+"×tamp="+timestamp+"&url="+url;
		String ciphertext=null;
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			byte[] digest = md.digest(content.toString().getBytes());
			ciphertext=byteToStr(digest);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return ciphertext;
	}
	public static String byteToStr(byte[] byteArray){
		String strDigest="";
		for (int i = 0; i < byteArray.length; i++) {
			strDigest+=byteToHexStr(byteArray[i]);
		}
		return strDigest;
	}
	public static String byteToHexStr(byte mByte){
		char[] Digit={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
		char[] tempArr = new char[2];
		tempArr[0]=Digit[(mByte>>>4)&0X0F];
		tempArr[1]=Digit[mByte&0X0F];
		String s=new String(tempArr);
		return s;
	}
}


前台代码需要先获取jsapi_ticket,后生成JS-SDK权限验证签名,完整代码如下(包括之前生成AccessToken的代码):

$.ajax({
		dataType:"json",
		url: "http://leonjoweixin.duapp.com/weixingongzhong/qiye/getAccessToken",
		success: function(data){
			 $.getJSON("http://leonjoweixin.duapp.com/weixingongzhong/qiye/getTsapiTicket",
				  {
				 	access_token:data.access_token	//获取的access_token
				  },
				  function(result){
					  var time=new Date().getTime();
					  $.get("http://leonjoweixin.duapp.com/weixingongzhong/qiye/getJsSdkSign",
				  		{
		  			  		noncestr:"Wm3WZYTPz0wzccnW",
		  			  		jsapi_ticket:result.ticket,//获取的jsapi_ticket
		  			  		timestamp:time,
		  			  		url:location.href.split('#')[0]
			  			},
				  		function(sign){
			  			   	console.log(sign)	//生成的JS-SDK权限签名
			  			}
					  );
			   	  }
			   );
			},
		error:function(XMLHttpRequest, textStatus, errorThrown){
		}
	});

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西山水壶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值