You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
digital-rmb-backend/src/main/java/com/yau/digitalrmb/institutionidentity/domain/CurrencyGenerationVerificat...

241 lines
12 KiB
Java

package com.yau.digitalrmb.institutionidentity.domain;
import java.math.BigDecimal;
public class CurrencyGenerationVerification {
public enum Status {
RECEIVED, SIGNATURE_VERIFIED, DIGEST_CALCULATED, DIGEST_MATCHED,
DIGEST_VERIFIED, QUOTA_VERIFIED, CONFIRMED, PACKAGED, RESPONSE_RETURNED
}
private final Long id;
private final long requestId;
private final String requestMessage;
private final String requestOriginalText;
private final String requestDigest;
private final String bankSignature;
private final String bankKeyId;
private final BigDecimal amount;
private Boolean signatureValid;
private String recomputedDigest;
private Boolean digestMatches;
private BigDecimal totalQuota;
private BigDecimal usedQuota;
private BigDecimal remainingQuota;
private Boolean quotaSufficient;
private String centralBankKeyId;
private String centralBankSignature;
private String confirmationTime;
private String confirmationMessage;
private String submittedPublicKey;
private String submittedPrivateKey;
private String userInputOriginalText;
private Status status;
private CurrencyGenerationVerification(Long id, long requestId, String requestMessage,
String requestOriginalText, String requestDigest,
String bankSignature, String bankKeyId, BigDecimal amount,
Boolean signatureValid, String recomputedDigest,
Boolean digestMatches, BigDecimal totalQuota,
BigDecimal usedQuota, BigDecimal remainingQuota,
Boolean quotaSufficient, String centralBankKeyId,
String centralBankSignature, String confirmationTime,
String confirmationMessage, String submittedPublicKey,
String submittedPrivateKey, String userInputOriginalText, Status status) {
this.id = id;
this.requestId = requestId;
this.requestMessage = requestMessage;
this.requestOriginalText = requestOriginalText;
this.requestDigest = requestDigest;
this.bankSignature = bankSignature;
this.bankKeyId = bankKeyId;
this.amount = amount;
this.signatureValid = signatureValid;
this.recomputedDigest = recomputedDigest;
this.digestMatches = digestMatches;
this.totalQuota = totalQuota;
this.usedQuota = usedQuota;
this.remainingQuota = remainingQuota;
this.quotaSufficient = quotaSufficient;
this.centralBankKeyId = centralBankKeyId;
this.centralBankSignature = centralBankSignature;
this.confirmationTime = confirmationTime;
this.confirmationMessage = confirmationMessage;
this.submittedPublicKey = submittedPublicKey;
this.submittedPrivateKey = submittedPrivateKey;
this.userInputOriginalText = userInputOriginalText;
this.status = status;
}
public static CurrencyGenerationVerification receive(long requestId, String requestMessage,
String requestOriginalText, String requestDigest,
String bankSignature, String bankKeyId,
BigDecimal amount) {
if (requestId <= 0 || requestMessage == null || requestOriginalText == null
|| requestDigest == null || bankSignature == null || bankKeyId == null || amount == null) {
throw new IllegalArgumentException("步骤二请求数据不完整,不能进入步骤三");
}
return new CurrencyGenerationVerification(null, requestId, requestMessage, requestOriginalText,
requestDigest, bankSignature, bankKeyId, amount, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, Status.RECEIVED);
}
public static CurrencyGenerationVerification restore(Long id, long requestId, String requestMessage,
String requestOriginalText, String requestDigest,
String bankSignature, String bankKeyId, BigDecimal amount,
Boolean signatureValid, String recomputedDigest,
Boolean digestMatches, BigDecimal totalQuota,
BigDecimal usedQuota, BigDecimal remainingQuota,
Boolean quotaSufficient, String centralBankKeyId,
String centralBankSignature, String confirmationTime,
String confirmationMessage, String submittedPublicKey,
String submittedPrivateKey, String userInputOriginalText,
Status status) {
return new CurrencyGenerationVerification(id, requestId, requestMessage, requestOriginalText, requestDigest,
bankSignature, bankKeyId, amount, signatureValid, recomputedDigest, digestMatches, totalQuota,
usedQuota, remainingQuota, quotaSufficient, centralBankKeyId, centralBankSignature,
confirmationTime, confirmationMessage, submittedPublicKey, submittedPrivateKey,
userInputOriginalText, status);
}
public void receiveAgain() {
if (status != null && status.ordinal() >= Status.RECEIVED.ordinal()) {
return;
}
signatureValid = null;
recomputedDigest = null;
digestMatches = null;
totalQuota = null;
usedQuota = null;
remainingQuota = null;
quotaSufficient = null;
centralBankKeyId = null;
centralBankSignature = null;
confirmationTime = null;
confirmationMessage = null;
submittedPublicKey = null;
submittedPrivateKey = null;
userInputOriginalText = null;
status = Status.RECEIVED;
}
public void verifySignature(boolean valid, String publicKey) {
requireBeforeDigestMatch("第二公钥SM2验证");
if (!valid) throw new IllegalArgumentException("商业银行SM2签名验证未通过");
signatureValid = true;
submittedPublicKey = publicKey;
status = recomputedDigest == null ? Status.SIGNATURE_VERIFIED : Status.DIGEST_CALCULATED;
}
public void calculateDigest(String digest, String userInputOriginalText) {
if (digest == null || !digest.matches("[0-9A-F]{64}")) {
throw new IllegalArgumentException("重新计算的摘要一格式不正确");
}
if (this.recomputedDigest != null && this.recomputedDigest.equalsIgnoreCase(digest)) {
return;
}
recomputedDigest = digest;
this.userInputOriginalText = userInputOriginalText;
digestMatches = null;
if (isBefore(Status.DIGEST_CALCULATED)) {
status = Status.DIGEST_CALCULATED;
}
}
public void matchDigest() {
if (recomputedDigest == null) {
throw new IllegalStateException("还未进行摘要运算,请先运算摘要一");
}
digestMatches = recomputedDigest.equalsIgnoreCase(requestDigest);
if (!digestMatches) throw new IllegalArgumentException("摘要一和摘要二不一致,请求完整性验证未通过");
if (isBefore(Status.DIGEST_MATCHED)) {
status = Status.DIGEST_MATCHED;
}
}
public void verifyQuota(BigDecimal total, BigDecimal used, BigDecimal remaining) {
// 额度验证是系统级操作,不依赖摘要匹配状态
// 移除 digestMatches 检查,允许独立进行额度验证
totalQuota = total;
usedQuota = used;
remainingQuota = remaining;
// 判断本次申请金额是否超过剩余额度
quotaSufficient = amount.compareTo(remaining) <= 0;
if (quotaSufficient) {
status = Status.QUOTA_VERIFIED;
}
}
public void confirm(String keyId, String signature, String time, String privateKey) {
if (!Boolean.TRUE.equals(quotaSufficient)) {
throw new IllegalStateException("请先完成额度检查");
}
if (keyId == null || signature == null || time == null) {
throw new IllegalArgumentException("央行签名确权数据不完整");
}
centralBankKeyId = keyId;
centralBankSignature = signature;
confirmationTime = time;
submittedPrivateKey = privateKey;
status = Status.CONFIRMED;
}
public void packageResponse(String message) {
if (centralBankSignature == null || confirmationTime == null) {
throw new IllegalStateException("请先完成央行签名确权");
}
if (message == null || message.trim().isEmpty()) {
throw new IllegalArgumentException("确认报文不能为空");
}
confirmationMessage = message;
status = Status.PACKAGED;
}
public void returnResponse() {
if (confirmationMessage == null) {
throw new IllegalStateException("请先打包确认报文");
}
status = Status.RESPONSE_RETURNED;
}
private void requireBeforeDigestMatch(String operation) {
if (status == Status.DIGEST_MATCHED || status == Status.DIGEST_VERIFIED
|| status == Status.QUOTA_VERIFIED || status == Status.CONFIRMED
|| status == Status.PACKAGED || status == Status.RESPONSE_RETURNED) {
throw new IllegalStateException(operation + "只能在摘要匹配前执行,当前状态:" + status.name());
}
}
private boolean isBefore(Status target) {
return status.ordinal() < target.ordinal();
}
private void requireStatus(Status expected, String message) {
if (status != expected) throw new IllegalStateException(message + ",当前状态:" + status.name());
}
public Long getId() { return id; }
public long getRequestId() { return requestId; }
public String getRequestMessage() { return requestMessage; }
public String getRequestOriginalText() { return requestOriginalText; }
public String getRequestDigest() { return requestDigest; }
public String getBankSignature() { return bankSignature; }
public String getBankKeyId() { return bankKeyId; }
public BigDecimal getAmount() { return amount; }
public Boolean getSignatureValid() { return signatureValid; }
public String getRecomputedDigest() { return recomputedDigest; }
public Boolean getDigestMatches() { return digestMatches; }
public BigDecimal getTotalQuota() { return totalQuota; }
public BigDecimal getUsedQuota() { return usedQuota; }
public BigDecimal getRemainingQuota() { return remainingQuota; }
public Boolean getQuotaSufficient() { return quotaSufficient; }
public String getCentralBankKeyId() { return centralBankKeyId; }
public String getCentralBankSignature() { return centralBankSignature; }
public String getConfirmationTime() { return confirmationTime; }
public String getConfirmationMessage() { return confirmationMessage; }
public String getSubmittedPublicKey() { return submittedPublicKey; }
public String getSubmittedPrivateKey() { return submittedPrivateKey; }
public String getUserInputOriginalText() { return userInputOriginalText; }
public Status getStatus() { return status; }
}