根据企业微信的文档来看,有4个必传参数:
noncestr(随机字符串), jsapi_ticket(如何获取参考“获取企业jsapi_ticket”以及“获取应用的jsapi_ticket接口”), timestamp(时间戳), url(当前网页的URL, 不包含#及其后面部分)
首先是配置:
public class WeiXinQiYeConstants {
/**
* 获取code
*/
public static final String GET_CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={CORPID}&redirect_uri={REDIRECT_URI}&response_type=code&scope={SCOPE}&state={STATE}#wechat_redirect";
/**
* 获取user_ticket
*/
public static final String GET_USER_TICKET_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token={ACCESS_TOKEN}&code={CODE}";
/**
* 获取用户信息
*/
public static final String GET_USER_INFO_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail?access_token={ACCESS_TOKEN}";
/**
* 获取token的url
*/
public static final String WECHAT_ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={ID}&corpsecret={SECRET}";
/**
* 获取ticket的url
*/
public static final String WECHAT_JSAPI_TICKET_URL = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token={ACCESS_TOKEN}";
/**
* 签名规则
*/
public static final String SIGN_RULE = "jsapi_ticket=%s&noncestr=%s×tamp=%d&url=%s";
}
首先生成一个随机字符串:
public static String genNonce() {
return bytesToHex(Long.toString(System.nanoTime())
.getBytes(StandardCharsets.UTF_8));
}
public static String bytesToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
获取当前时间戳
long timestamp = System.currentTimeMillis() / 1000;
然后根据应用id和企业id去获取access_token
public static AccessToken getAccessToken(String orgId, String applyId) throws BusinessException {
AccessToken token = null;
String url = WeiXinQiYeConstants.WECHAT_ACCESS_TOKEN_URL
.replace("{ID}",orgId)
.replace("{SECRET}",applyId);
logger.info("get weixin access_token url:"+url);
JSONObject jsonObject = JSON.parseObject(HttpUtil.get(url));
logger.info("get weixin access_token callback data:"+jsonObject);
if(StringUtils.isEmpty(jsonObject)){
logger.info("access_token返回为空,result:"+jsonObject);
throw new BusinessException("access_token返回为空,result:"+jsonObject);
}else{
try {
token = new AccessToken();
token.setAccessToken(jsonObject.getString("access_token"));
token.setExpiresIn(jsonObject.getInteger("expires_in"));
token.setErrcode(jsonObject.getInteger("errcode"));
token.setErrmsg(jsonObject.getString("errmsg"));
/*缓存进tokenMap*/
//tokenMap.put("TOKENKEY",token);
}catch (Exception e){
logger.info("access_token 获取失败, errcode:"+jsonObject.getInteger("errcode")+",errmsg:"+jsonObject.getString("errmsg"));
throw new BusinessException("access_token 获取失败, errcode:"+jsonObject.getInteger("errcode")+",errmsg:"+jsonObject.getString("errmsg"));
}
}
return token;
}
通过token获取用户的jsapi_ticket:
private static String getJsapiTicket(String accessToken) {
String url = WeiXinQiYeConstants.WECHAT_JSAPI_TICKET_URL
.replace("{ACCESS_TOKEN}", accessToken);
String res = HttpUtil.get(url);
JSONObject jsonObject = JSON.parseObject(res);
String ticket = (String)jsonObject.get("ticket");
return ticket;
}
这里需要注意下文档中的提示
最后把随机字符串,时间戳,url和用户的的ticket,用SHA-1做下签名:
private static String sign(String url, String nonce, Long timestamp, String ticket) throws Exception {
String plain = String.format(WeiXinQiYeConstants.SIGN_RULE, ticket, nonce, timestamp, url);
logger.info("plain:" + plain);
try {
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
sha1.reset();
sha1.update(plain.getBytes(StandardCharsets.UTF_8));
return bytesToHex(sha1.digest());
} catch (NoSuchAlgorithmException e) {
// throw new LeysenException("jsapi_ticket计算签名错误");
throw new Exception("jsapi_ticket计算签名错误");
}
}
ok,这个签名就是我们最终要的