JAVA代码示例

verifySignature 方法

public Application verifySignature(OpenApiRequest openApiRequest) {
    long nowExpires = Instant.now().getEpochSecond();
    if (Math.abs(nowExpires - Integer.parseInt(openApiRequest.getExpires())) > 60 * 30) {
        throw new OpenApiServiceException(openApiRequest, ErrorTypeEnum.EXCEED_TIME_LIMIT);
    }
    Application application = applicationService.getByAppId(openApiRequest.getAppId());
    if (ObjectUtil.isEmpty(application) || !Objects.equals(application.getStatus(), DefaultStatusEnum.YES.getValue())) {
        throw new OpenApiServiceException(openApiRequest, ErrorTypeEnum.DEVICE_APPID_INVALID);
    }
    if (OpenApiSignUtils.isErrorSign(openApiRequest.getData(), openApiRequest.getSign(), AESUtil.decrypt(application.getAppSecret()))) {
        throw new OpenApiServiceException(openApiRequest, ErrorTypeEnum.DEVICE_SIGN_ERROR);
    }
    return application;
}

OpenApiSignUtils 工具类

package com.deviceIot.common.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.apache.commons.codec.digest.DigestUtils;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;

/**
 * 开放接口签名工具类
 *
 */
public class OpenApiSignUtils {

    /**
     * 私有化构造器(单例模式)
     */
    private OpenApiSignUtils() {
    }
    // region 私有方法

    /**
     * 生成签名串
     *
     * @param data 请求参数
     * @param appSecret appSecret
     * @return 签名串
     */
    private static String generateSignReduce(String data, String appSecret) {
        return generateSignReduce(data) + "&key=" + appSecret;
    }

    /**
     * 生成签名字符串
     *
     * @param data 生成签名的参数
     * @return 签名字符串
     */
    private static String generateSignReduce(String data) {
        if (ObjectUtil.isEmpty(data)) {
            return "";
        }
        JSONObject parse = JSONUtil.parseObj(data);
        if (ObjectUtil.isEmpty(parse)) {
            return "";
        }
        handleValue(parse);
        return sortedCollectSign(parse);
    }
    // endregion

    // region 工具方法
    /**
     * 生成签名 (MD5)
     *
     * @param data 请求参数
     * @param appSecret appSecret
     * @return 签名
     */
    public static String generateSign(String data, String appSecret) {
        return DigestUtils.md5Hex(generateSignReduce(data, appSecret)).toLowerCase();
    }

    /**
     * 验证签名
     *
     * @param data 请求参数
     * @param sign 签名
     * @param appSecret appSecret
     * @return 签名是否错误
     */
    public static boolean isErrorSign(String data, String sign, String appSecret) {
        return !generateSign(data, appSecret).equalsIgnoreCase(sign);
    }

    /**
     * 对Json对象的value进行排序,如果value为对象时,先将对象转换成json字符串
     * @param jsonObject Json对象
     */
    public static void handleValue(JSONObject jsonObject) {
        for (String key : jsonObject.keySet()) {
            Object value = jsonObject.get(key);
            if (ObjectUtil.isNotEmpty(value)) {
                if (value instanceof JSONObject || value instanceof JSONArray) {
                    jsonObject.set(key, JSONUtil.toJsonStr(value));
                }
            }
        }
    }

    /**
     * 排序并生成签名字符串
     * @param parse json对象
     * @return 签名字符串
     */
    public static String sortedCollectSign(JSONObject parse){
        return parse.keySet().stream()
                .filter(key -> !"sign".equalsIgnoreCase(key))
                .filter(key -> ObjectUtil.isNotEmpty(parse.getStr(key)))
                .sorted()
                .map(key -> {
                    try {
                        return key + "=" + URLEncoder.encode(parse.getStr(key), StandardCharsets.UTF_8.name());
                    } catch (Exception e) {
                        return "";
                    }
                })
                .filter(ObjectUtil::isNotEmpty)
                .collect(Collectors.joining("&"));
    }
    // endregion
}
作者:yrh  创建时间:2026-06-05 14:29
最后编辑:yrh  更新时间:2026-06-05 14:43