51 lines
1.8 KiB
Java
51 lines
1.8 KiB
Java
package com.yunhai.userbase.service.push;
|
||
|
||
import javax.crypto.Mac;
|
||
import javax.crypto.spec.SecretKeySpec;
|
||
import java.nio.charset.StandardCharsets;
|
||
|
||
/**
|
||
* 推送签名器:复刻文档 2.x 规范。<br><br>
|
||
* 签名串 DATA2 = 业务JSON(原始字符串) + 时间戳t;<br>
|
||
* sign = HMAC-SHA256(DATA2, secret),UTF-8,hex 小写。<br><br>
|
||
* <b>关键</b>:签名与发送均基于「发送方实际写出的 body 原始字符串字节」,
|
||
* 订阅方须用接收到的原始 body 验签(不得反序列化后重新序列化,否则字节不一致导致验签失败)。
|
||
*
|
||
* @author chenx
|
||
* @date 2026/8/14
|
||
*/
|
||
public final class PushSigner {
|
||
|
||
private PushSigner() {
|
||
}
|
||
|
||
/**
|
||
* 计算签名。
|
||
*
|
||
* @param body 业务数据原始 JSON 字符串(与发送 body 完全一致)
|
||
* @param secret 签名密钥(push_secret 优先,否则 app_secret)
|
||
* @param t 时间戳(毫秒或秒,与订阅方约定一致即可;本实现直接拼接字符串)
|
||
* @return hex 小写签名
|
||
*/
|
||
public static String sign(String body, String secret, String t) {
|
||
try {
|
||
Mac mac = Mac.getInstance("HmacSHA256");
|
||
SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
|
||
mac.init(keySpec);
|
||
String data2 = body + t;
|
||
byte[] raw = mac.doFinal(data2.getBytes(StandardCharsets.UTF_8));
|
||
return toHex(raw);
|
||
} catch (Exception e) {
|
||
throw new RuntimeException("推送签名失败", e);
|
||
}
|
||
}
|
||
|
||
private static String toHex(byte[] bytes) {
|
||
StringBuilder sb = new StringBuilder(bytes.length * 2);
|
||
for (byte b : bytes) {
|
||
sb.append(String.format("%02x", b));
|
||
}
|
||
return sb.toString();
|
||
}
|
||
}
|