微信JS-SDK 签名方式-java代码小记

浮夸小生。
2024-04-26 / 0 评论 / 4 阅读 / 正在检测是否收录...

签名加密方式

阅读官方文档: JS-SDK使用权限签名算法

  首先获取 access_token -> AppID(开发者ID) + AppSecret(开发者密码) 获取方式:公众号后台地址-基本配置

  其次获取 jsapi_ticket —>携带 access_token 请求链接 (见官方文档)

生成加密方式

最终需要返回如下信息:

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

  加密算法不在赘述,详情查看 官方文档
  

附java实现代码:

@Slf4j
public class WeChatUtil {

    private static final String APP_ID = "开发者ID";
    private static final String APP_SECRET = "开发者密钥";
    private static final long EXPIRATION_TIME_MILLIS = 7200 * 1000; // 7200秒转换为毫秒

    private static String accessToken;
    private static String jsapiTicket;
    private static Date accessTokenLastUpdateTime;
    private static Date jsapiTicketLastUpdateTime;

    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    // 使用线程安全的ConcurrentHashMap来存储accessToken和jsapiTicket,避免多线程并发问题
    private static final ConcurrentHashMap<String, String> cache = new ConcurrentHashMap<>();

    // 获取微信配置信息
    public static WxConfig getWxConfig(String url) {
        String accessToken = getAccessToken();
        String jsapiTicket = getJsapiTicket(accessToken);

        if (StringUtils.isNotBlank(accessToken) && StringUtils.isNotBlank(jsapiTicket)) {
            //进行加密
            String nonceStr = UUID.randomUUID().toString();
            Long timestamp = System.currentTimeMillis() / 1000;
            Map<String, Object> paramMap = new TreeMap<>();
            paramMap.put("noncestr", nonceStr);
            paramMap.put("jsapi_ticket", jsapiTicket);
            paramMap.put("timestamp", timestamp);
            paramMap.put("url", url);
            // 拼接参数为字符串
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            String string1 = sb.substring(0, sb.length() - 1); // 去掉最后一个&符号
            // 使用SHA1加密
            String signature = SHA1(string1);

            List<String> jsApiList = new ArrayList<>();
            jsApiList.add("jsApiList");
            return new WxConfig(true, APP_ID, timestamp, nonceStr, signature, jsApiList);
        }

        return null;
    }

    // 获取 access_token
    private static String getAccessToken() {
        log.info("获取acctoken");
        // 检查是否过期
        if (accessToken == null || accessTokenLastUpdateTime == null || new Date().getTime() - accessTokenLastUpdateTime.getTime() > EXPIRATION_TIME_MILLIS) {
            // 过期或者第一次获取,需要更新 accessToken
            updateAccessToken();
        }
        return accessToken;
    }

    // 更新 access_token
    private static void updateAccessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + APP_ID + "&secret=" + APP_SECRET;
        String result = HttpClientManager.httpGetMethod(url, null);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (!jsonObject.containsKey("errcode")) {
            accessToken = jsonObject.getString("access_token");
            accessTokenLastUpdateTime = new Date();
            log.info(accessToken);
            // 使用 scheduler 定时在7200秒后再次更新 accessToken
            scheduler.schedule(WeChatUtil::updateAccessToken, EXPIRATION_TIME_MILLIS, TimeUnit.MILLISECONDS);
        }
    }

    // 获取 jsapi_ticket
    private static String getJsapiTicket(String accessToken) {
        // 检查是否过期
        if (jsapiTicket == null || jsapiTicketLastUpdateTime == null || new Date().getTime() - jsapiTicketLastUpdateTime.getTime() > EXPIRATION_TIME_MILLIS) {
            // 过期或者第一次获取,需要更新 jsapiTicket
            updateJsapiTicket(accessToken);
        }
        return jsapiTicket;
    }

    // 更新 jsapi_ticket
    private static void updateJsapiTicket(String accessToken) {
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";
        String result = HttpClientManager.httpGetMethod(url, null);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (jsonObject.getInteger("errcode") == 0) {
            jsapiTicket = jsonObject.getString("ticket");
            jsapiTicketLastUpdateTime = new Date();

            // 使用 scheduler 定时在7200秒后再次更新 jsapiTicket
            scheduler.schedule(() -> updateJsapiTicket(accessToken), EXPIRATION_TIME_MILLIS, TimeUnit.MILLISECONDS);
        }
    }

    // SHA1 加密
    private static String SHA1(String str) {
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(str.getBytes("UTF-8"));
            byte[] digest = crypt.digest();
            // 转换为十六进制字符串
            Formatter formatter = new Formatter();
            for (byte b : digest) {
                formatter.format("%02x", b);
            }
            String result = formatter.toString();
            formatter.close();
            return result;
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}
0

评论 (0)

取消