概要
最近在开发一个模块,模块里面有个接口,需要调用微信的相关接口,去获取微信公众号的Js-config签名配置,把这些签名配置返回给前端,前端用于拉起语音,进而进行语音识别的功能。具体技术文档可以看一下微信官网文档:JS-SDK说明文档
实现思路:
获取微信JS签名是微信小程序开发中常见的一个步骤,主要用于确保小程序与微信服务器之间通信的安全性。微信JS签名通常用于调用微信提供的JS-SDK接口,以便在小程序中实现一些高级功能,如分享、支付、语音等。
要获取微信JS签名,你需要按照以下步骤操作:
-
获取AppID和AppSecret
首先,你需要在微信公众平台注册一个小程序,并获取到对应的AppID和AppSecret。这两个参数是调用微信接口的凭证。 -
获取Access Token
使用AppID和AppSecret调用微信提供的接口获取Access Token。Access Token是调用微信接口的临时凭证,有效期为7200秒。 -
获取JSAPI Ticket
使用获取到的Access Token调用微信提供的接口获取JSAPI Ticket。JSAPI Ticket是用于生成签名的临时凭证,有效期同样为7200秒。 -
生成签名
使用JSAPI Ticket、当前时间戳、随机字符串以及小程序的URL生成签名。签名的生成算法是SHA1加密。
以下是生成签名的基本步骤:
将URL、时间戳、随机字符串和JSAPI Ticket按照字典序排序。
将排序后的字符串拼接成一个字符串。
对拼接后的字符串进行SHA1加密,得到签名。
废话不多说,直接开弄
/**
*获取微信配置方法
**/
public WxJsConfig getWxJsConfig(String url) {
WxJsConfig result = new WxJsConfig();
try {
//需要加密的url不能为空,
Assert.notBlank(url, "传入的url不能为空!");
//这里为对应需要获取配置的公众号的appId和appSecret 具体参数可以在公众号后台获取到
String appId = "wx1*******1ds";
String appSecret = "appSecret";
//获取微信ticket
String jsApiTicket = getJsApiTicket(appId,setSecret);
//自行生成随机字符串
String nonceStr = RandomStringGenerator.getRandomStringByLength(32);
long timestamp = System.currentTimeMillis();
//签名
String signature = generateSignature(jsApiTicket, nonceStr, String.valueOf(timestamp), req.getUrl());
result.setAppId(appId);
result.setNonceStr(nonceStr);
result.setTimestamp(timestamp);
result.setSignature(signature);
} catch (Exception e) {
throw new XKSHException("获取JS签名失败:" + e.getMessage());
}
return result;
}
/**
* 获取微信JsApiTicket
* @param appId
* @param appSecret
* @return
*/
public static String getJsApiTicket(String appId, String appSecret) {
//优先从redis获取ticket,获取不到再调用接口获取
//获取accessToken
String accessToken = getWxAccessToken(appId,appSecret);
String requestUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token="+accessToken;
//发起请求
String result = sendGetRequest(requestUrl );
if(result.contains("请求失败")){
throw new Exception("请求失败");
}
JSONObject jsonObject = JSON.parseObject(response);
String ticket= jsonObject.getString("ticket");
//这里成功获取到ticket后,最好根据接口返回的有效时间放入redis,避免频繁调用
//放入redis
return ticket;
}
/**
* 获取微信accessToken
* @param appId
* @param appSecret
* @return
*/
public static String getWxAccessToken(String appId, String appSecret) {
//优先从redis获取,获取不到再调用接口获取
//构建请求地址
String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+appSecret;
//发起请求
String result = sendGetRequest(requestUrl );
if(result.contains("请求失败")){
throw new Exception("请求失败");
}
JSONObject jsonObject = JSON.parseObject(response);
String accessToken = jsonObject.getString("token");
//这里成功获取到token后,最好根据接口返回的有效时间放入redis,避免频繁调用
//放入redis
return accessToken;
}
/**
* 签名加密
* @param jsApiTicket
* @param nonceStr
* @param timestamp
* @param url
* @return
*/
public static String generateSignature(String jsApiTicket, String nonceStr, String timestamp, String url) {
String[] params = {
"jsapi_ticket=" + jsApiTicket,
"noncestr=" + nonceStr,
"timestamp=" + timestamp,
"url=" + url
};
Arrays.sort(params);
StringBuilder sb = new StringBuilder();
for (String param : params) {
sb.append(param).append("&");
}
sb.setLength(sb.length() - 1);
return DigestUtils.sha1Hex(sb.toString());
}
public static String sendGetRequest(String requestUrl) throws IOException {
URL url = new URL(requestUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
} else {
return "请求失败,响应码: " + responseCode;
}
}