| | |
| | | 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; |
| | |
| | | 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; |
| | | } |
| | |
| | | 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; |
| | |
| | | } |
| | | } |
| | | |
| | | 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); |
| | | } |