CashFree Webhook验证示例代码无法正常运行
CashFree Webhook签名验证失败排查与修复方案
核心问题排查点
- 请求体读取方式错误:原代码通过
readLine()按行拼接并添加换行符,会破坏原始请求体的字节结构,导致签名计算不一致。CashFree要求使用原始请求体的完整字节流进行计算。 - 字符编码未指定:默认
getBytes()方法使用系统编码,可能与CashFree使用的UTF-8不匹配,必须明确指定UTF-8编码。 - Timestamp头部校验:需确认
x-webhook-timestamp头部是否正确获取,避免因大小写或空值导致拼接错误。
修正后的代码实现
import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Base64; import javax.servlet.http.HttpServletRequest; public String generateSignature(HttpServletRequest request) throws IOException { // 读取原始请求体字节流,保留完整结构 byte[] payloadBytes = request.getInputStream().readAllBytes(); String payload = new String(payloadBytes, StandardCharsets.UTF_8); String timestamp = request.getHeader("x-webhook-timestamp"); if (timestamp == null) { throw new IllegalArgumentException("x-webhook-timestamp header is missing"); } // 严格按照timestamp + payload的顺序拼接 String data = timestamp + payload; byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8); String secretKey = "YOUR_SECRET_KEY"; // 替换为商户后台获取的Secret Key try { Mac sha256Hmac = Mac.getInstance("HmacSHA256"); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); sha256Hmac.init(secretKeySpec); byte[] hmacBytes = sha256Hmac.doFinal(dataBytes); return Base64.getEncoder().encodeToString(hmacBytes); } catch (Exception e) { throw new RuntimeException("Signature generation failed", e); } }
额外验证步骤
- 对比
x-webhook-timestamp头部值与Webhook请求中的原始值,确保无空格、大小写错误或截断。 - 将计算出的签名与请求头
x-webhook-signature直接做字符串相等校验,不要添加任何额外处理。 - 使用CashFree测试工具生成的示例payload和timestamp手动计算签名,验证代码逻辑正确性。
内容的提问来源于stack exchange,提问作者ksernow
相关产品推荐
相关产品推荐

