longz
2026-07-15 c207fd1454b64f47e2e66cd2f578a2b21b06f019
ruoyi-service/ruoyi-payment/src/main/java/com/ruoyi/payment/icbc/service/impl/IcbcPayServiceImpl.java
@@ -37,9 +37,11 @@
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.net.URI;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
@@ -294,8 +296,10 @@
                    params, result, "SUCCESS", null);
            return result;
        } catch (RuntimeException e) {
            flowRecorder.record("PAY_NOTIFY", firstNotBlank(params.get("out_trade_no"), params.get("outTradeNo")),
                    parseInteger(firstNotBlank(params.get("attach"), params.get("paymentType"))), null,
            Map<String, String> auditParams = new HashMap<>(params);
            mergeBizContent(auditParams);
            flowRecorder.record("PAY_NOTIFY", firstNotBlank(auditParams.get("out_trade_no"), auditParams.get("outTradeNo")),
                    parseInteger(firstNotBlank(auditParams.get("attach"), auditParams.get("paymentType"))), null,
                    params, null, "FAIL", e.getMessage());
            throw e;
        }
@@ -581,8 +585,16 @@
            String content = buildSignContent(params);
            String signType = firstNotBlank(params.get("sign_type"), properties.getSignType());
            String publicKey = normalizePublicKey(properties.getIcbcPublicKey());
            log.info("工行回调验签参数,signType:{},publicKeyLength:{},content:{}", signType, publicKey == null ? 0 : publicKey.length(), content);
            return IcbcSignature.verify(content, signType, publicKey, properties.getCharset(), sign);
            String notifyPath = resolveNotifyPath();
            log.info("工行回调验签参数,notifyPath:{},signType:{},charset:{},publicKeyLength:{},publicKeySha256:{},contentSha256:{},signLength:{}",
                    notifyPath, signType, properties.getCharset(), publicKey == null ? 0 : publicKey.length(),
                    sha256Hex(publicKey), sha256Hex(content), sign.length());
            boolean verified = IcbcSignature.verify(content, signType, publicKey, properties.getCharset(), sign);
            log.info("工行回调验签结果,verified:{}", verified);
            if (!verified) {
                log.warn("工行回调验签未通过,content:{}", content);
            }
            return verified;
        } catch (Exception e) {
            log.error("工行回调验签异常", e);
            return false;
@@ -659,6 +671,23 @@
        }
    }
    private String sha256Hex(String value) {
        if (value == null) {
            return "";
        }
        try {
            byte[] digest = MessageDigest.getInstance("SHA-256").digest(value.getBytes(StandardCharsets.UTF_8));
            StringBuilder hex = new StringBuilder(digest.length * 2);
            for (byte item : digest) {
                hex.append(String.format("%02x", item & 0xff));
            }
            return hex.toString();
        } catch (Exception e) {
            log.warn("计算工行验签摘要失败", e);
            return "";
        }
    }
    private boolean isPaidStatus(String status) {
        return Arrays.asList("1", "2", "SUCCESS", "PAID", "PAY_SUCCESS", "TRADE_SUCCESS").contains(status);
    }