引言
在开发微信企业号相关的应用时,我们常常需要与微信服务器交互来获取必要的权限验证票据(ticket),用于生成用于网页授权的签名(signature)。本文将介绍一个简单的工具类 WeChatApiUtil
,封装了与微信企业号平台进行通信的方法,用于获取访问令牌(access_token)以及JS-SDK票据。
代码功能介绍
WeChatApiUtil
类提供了以下功能:
- 获取微信企业号的访问令牌
access_token
; - 获取JS-SDK票据
jsapi_ticket
; - 生成用于网页授权的签名
signature
。
该工具类利用Spring框架提供的 RestTemplate
和 StringRedisTemplate
进行HTTP请求及缓存管理。
代码细节解释
依赖引入
确保项目中引入了必要的依赖库,如Fastjson、Apache Commons Codec、Lombok等
<!-- Fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<!-- Apache Commons Codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
工具类实现
1. 获取访问令牌 getAccessToken
访问令牌 access_token
是进行后续API调用的基础,每次请求都会被缓存在Redis中,以减少不必要的请求次数。
public String getAccessToken() {
if (stringRedisTemplate == null || restTemplate == null) {
throw new MallException("stringRedisTemplate or restTemplate is not initialized.");
}
String accessToken = stringRedisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
if (StringUtils.isEmpty(accessToken)) {
try {
ResponseEntity<String> responseEntity = restTemplate.getForEntity(API_URL_GET_ACCESS_TOKEN, String.class, corpId, secret);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
String responseBody = responseEntity.getBody();
if (StringUtils.isNotBlank(responseBody)) {
accessToken = extractAccessToken(responseBody);
if (StringUtils.isNotEmpty(accessToken)) {
stringRedisTemplate.opsForValue().set(ACCESS_TOKEN_KEY, accessToken, EXPIRATION, java.util.concurrent.TimeUnit.SECONDS);
}
}
} else {
log.error("获取access_token失败. Status code: {}", responseEntity.getStatusCode());
}
} catch (Exception e) {
log.error("Error while fetching access token.", e);
}
}
return accessToken;
}
2. 获取JS-SDK票据 getJsApiTicket
此方法会检查本地缓存,如果缓存中的票据还未过期,则直接返回;否则会请求微信服务器获取新的票据并更新缓存。
public String getJsApiTicket(String type) {
String accessToken = getAccessToken();
String key = accessToken;
if ("agent_config".equals(type)) {
key = type + "_" + accessToken;
}
Ticket ticket = ticketMap.get(key);
long now = System.currentTimeMillis();
if (ticket != null && ticket.getValid() - now > 0) {
return ticket.getTicket();
}
ticket = getJsApiTicketFromWeChatPlatform(accessToken, type);
if (ticket != null) {
ticketMap.put(key, ticket);
return ticket.getTicket();
}
return null;
}
3. 生成签名 getSignature
使用SHA-1算法生成签名,签名字符串由票据、随机字符串、时间戳和页面URL组成。
public String getSignature(String ticket, String nonceStr, long timestamp, String url) {
try {
String unEncryptStr = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + url;
MessageDigest sha = MessageDigest.getInstance("SHA-1"); // 使用 SHA-1 算法
byte[] cipherBytes = sha.digest(unEncryptStr.getBytes());
return Hex.encodeHexString(cipherBytes);
} catch (NoSuchAlgorithmException e) {
log.error("生成signature错误: ", e);
return null;
}
}
使用示例
假设已经初始化了 WeChatApiUtil
并且设置了正确的 corpId
和 secret
,可以这样使用它
String ticket = weChatApiUtil.getJsApiTicket("jsapi");
String signature = weChatApiUtil.getSignature(ticket, weChatApiUtil.generateNonceStr(), System.currentTimeMillis() / 1000, "http://example.com/page");
结论
通过 WeChatApiUtil
工具类,可以方便地集成微信企业号的功能,特别是网页授权的部分。