macrozheng/mall-swarm · warning
支付回调签名校验失败!
Error message
支付回调签名校验失败!
What it means
AlipayServiceImpl.notify calls AlipaySignature.rsaCheckV1 to verify the signature of Alipay's async payment callback using the configured Alipay public key, charset, and sign type. If verification returns false (or throws), the callback is rejected with this warning and 'failure' is returned, causing the order to never be marked paid and Alipay to retry the notification.
Solutions
- Verify alipayConfig.getAlipayPublicKey() is Alipay's platform public key (from the open platform app details), not your own application private/public key.
- Confirm charset and signType in alipayConfig exactly match those used in the Alipay app settings (e.g., UTF-8, RSA2).
- Ensure the notify handler receives ALL raw callback parameters unmodified (don't re-encode, reorder, or drop fields before verification).
- Check that the callback URL belongs to the same Alipay app/gateway environment whose key is configured.
- If the same endpoint serves sandbox traffic, use the sandbox Alipay public key accordingly.
Example fix
// before (config) alipay.public-key=MIIBIjANBgkq...your-app-public-key... // after (config) - use the Alipay PLATFORM public key from open.alipay.com app settings alipay.public-key=MIIBIjANBgkq...alipay-platform-public-key... alipay.sign-type=RSA2 alipay.charset=UTF-8
Defensive patterns
Strategy: validation
Validate before calling
// Before deploying, self-test key configuration
boolean ok;
try {
ok = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(),
alipayConfig.getCharset(), alipayConfig.getSignType());
} catch (AlipayApiException e) {
log.error("签名校验异常", e);
ok = false;
}
if (!ok) { log.warn("拒绝回调: 签名不匹配"); return "failure"; } Type guard
boolean isConfigValid(AlipayConfig c) {
return c != null
&& StringUtils.isNotBlank(c.getAlipayPublicKey())
&& StringUtils.isNotBlank(c.getCharset())
&& StringUtils.isNotBlank(c.getSignType());
} Try / catch
try {
signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(),
alipayConfig.getCharset(), alipayConfig.getSignType());
} catch (AlipayApiException e) {
log.error("支付回调签名校验异常!", e);
return "failure";
} Prevention
- Configure Alipay's PLATFORM public key (not your app's own key pair) in alipayConfig.
- Keep charset and signType identical between your config and the Alipay app settings.
- Never transform, re-encode, or partially parse callback params before signature verification.
- Point notify_url at the environment matching the configured keys (sandbox vs production).
- Log failing callbacks' out_trade_no and sign_type to diagnose key mismatches quickly.
When it happens
Trigger: A callback arrives whose params fail rsaCheckV1: wrong/placeholder alipayPublicKey (e.g., merchant app public key instead of Alipay's public key), mismatched charset or signType, params altered/missing fields (e.g., sign or sign_type stripped), or a forged/unauthorized callback request.
Common situations: Swapping the app's own public key with Alipay's platform public key in config; switching Alipay apps/keys between environments; sign_type mismatch after upgrading to RSA2; a proxy or gateway re-encoding the callback and corrupting parameters; attackers probing the notify URL.
Related errors
AI-assisted analysis of macrozheng/mall-swarm@04c442fe31 (2026-09-08).
Data as JSON: /api/errors/62714a4d30822a47.
Report an issue: GitHub.
Appendix: source
Thrown at mall-portal/src/main/java/com/macro/mall/portal/service/impl/AlipayServiceImpl.java:93
try {
//调用SDK验证签名
signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType());
} catch (AlipayApiException e) {
log.error("支付回调签名校验异常!",e);
e.printStackTrace();
}
if (signVerified) {
String tradeStatus = params.get("trade_status");
if("TRADE_SUCCESS".equals(tradeStatus)){
result = "success";
log.info("notify方法被调用了,tradeStatus:{}",tradeStatus);
String outTradeNo = params.get("out_trade_no");
portalOrderService.paySuccessByOrderSn(outTradeNo,1);
}else{
log.warn("订单未支付成功,trade_status:{}",tradeStatus);
}
} else {
log.warn("支付回调签名校验失败!");
}
return result;
}
@Override
public String query(String outTradeNo, String tradeNo) {
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
//******必传参数******
JSONObject bizContent = new JSONObject();
//设置查询参数,out_trade_no和trade_no至少传一个
if(StrUtil.isNotEmpty(outTradeNo)){
bizContent.put("out_trade_no",outTradeNo);
}
if(StrUtil.isNotEmpty(tradeNo)){
bizContent.put("trade_no",tradeNo);
}
//交易结算信息: trade_settle_info
String[] queryOptions = {"trade_settle_info"};View on GitHub (pinned to 04c442fe31)