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.
241 lines
12 KiB
Java
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; }
|
|
}
|