feat:文件上传的功能开发

master
jiazheng.zhao 2 weeks ago
parent f19428560a
commit 44df252f9b

@ -52,7 +52,7 @@ public class CurrencyGenerationRequestService {
request = CurrencyGenerationRequest.restore(requestId, input.getIdentifierApplicationId(), request = CurrencyGenerationRequest.restore(requestId, input.getIdentifierApplicationId(),
input.getInstitutionIdentifier(), input.getFullInstitutionIdentifier(), input.getAmount(), input.getInstitutionIdentifier(), input.getFullInstitutionIdentifier(), input.getAmount(),
input.getDeliveryNodeCode(), input.getRequestTimestamp(), input.getRequestOriginalText(), input.getDeliveryNodeCode(), input.getRequestTimestamp(), input.getRequestOriginalText(),
null, null, null, null, input.getStatus()); null, null, null, null, null, input.getStatus());
} }
String digest = cryptography.sm3(input.getRequestOriginalText()); String digest = cryptography.sm3(input.getRequestOriginalText());
CurrencyGenerationRequest.Status expected = request.getStatus(); CurrencyGenerationRequest.Status expected = request.getStatus();
@ -77,7 +77,7 @@ public class CurrencyGenerationRequestService {
"签名必须使用当前实训主体的商业银行第二私钥,本次实训第" "签名必须使用当前实训主体的商业银行第二私钥,本次实训第"
+ errorSequence + "次错误"); + errorSequence + "次错误");
} }
invokeDomain(() -> request.recordSignature(InstitutionKeyService.BANK_SECOND_KEY, signature)); invokeDomain(() -> request.recordSignature(InstitutionKeyService.BANK_SECOND_KEY, signature, privateKey));
repository.update(request, expected, "SIGN", "使用商业银行第二私钥完成SM2签名", operator); repository.update(request, expected, "SIGN", "使用商业银行第二私钥完成SM2签名", operator);
return new CurrencyRequestResult(request); return new CurrencyRequestResult(request);
} }

@ -51,6 +51,12 @@ public class CurrencyGenerationVerificationResult {
private final String confirmationTime; private final String confirmationTime;
@Schema(description = "央行打包完成的确认报文;尚未点击打包报文时为空") @Schema(description = "央行打包完成的确认报文;尚未点击打包报文时为空")
private final String confirmationMessage; private final String confirmationMessage;
@Schema(description = "用户提交的商业银行第二公钥;尚未验签时为空")
private final String submittedPublicKey;
@Schema(description = "用户提交的央行第一私钥;尚未确权时为空")
private final String submittedPrivateKey;
@Schema(description = "用户在步骤三运算摘要时输入的请求原文;尚未运算时为空")
private final String userInputOriginalText;
public CurrencyGenerationVerificationResult() { public CurrencyGenerationVerificationResult() {
verificationId = null; requestId = null; status = null; verificationId = null; requestId = null; status = null;
@ -61,6 +67,8 @@ public class CurrencyGenerationVerificationResult {
remainingQuota = null; quotaSufficient = null; remainingQuota = null; quotaSufficient = null;
centralBankKeyId = null; centralBankSignature = null; centralBankKeyId = null; centralBankSignature = null;
confirmationTime = null; confirmationMessage = null; confirmationTime = null; confirmationMessage = null;
submittedPublicKey = null; submittedPrivateKey = null;
userInputOriginalText = null;
} }
public CurrencyGenerationVerificationResult(CurrencyGenerationVerification v) { public CurrencyGenerationVerificationResult(CurrencyGenerationVerification v) {
@ -72,6 +80,8 @@ public class CurrencyGenerationVerificationResult {
remainingQuota = v.getRemainingQuota(); quotaSufficient = v.getQuotaSufficient(); remainingQuota = v.getRemainingQuota(); quotaSufficient = v.getQuotaSufficient();
centralBankKeyId = v.getCentralBankKeyId(); centralBankSignature = v.getCentralBankSignature(); centralBankKeyId = v.getCentralBankKeyId(); centralBankSignature = v.getCentralBankSignature();
confirmationTime = v.getConfirmationTime(); confirmationMessage = v.getConfirmationMessage(); confirmationTime = v.getConfirmationTime(); confirmationMessage = v.getConfirmationMessage();
submittedPublicKey = v.getSubmittedPublicKey(); submittedPrivateKey = v.getSubmittedPrivateKey();
userInputOriginalText = v.getUserInputOriginalText();
} }
public Long getVerificationId() { return verificationId; } public Long getVerificationId() { return verificationId; }
@ -94,4 +104,7 @@ public class CurrencyGenerationVerificationResult {
public String getCentralBankSignature() { return centralBankSignature; } public String getCentralBankSignature() { return centralBankSignature; }
public String getConfirmationTime() { return confirmationTime; } public String getConfirmationTime() { return confirmationTime; }
public String getConfirmationMessage() { return confirmationMessage; } public String getConfirmationMessage() { return confirmationMessage; }
public String getSubmittedPublicKey() { return submittedPublicKey; }
public String getSubmittedPrivateKey() { return submittedPrivateKey; }
public String getUserInputOriginalText() { return userInputOriginalText; }
} }

@ -51,7 +51,7 @@ public class CurrencyGenerationVerificationService {
return new CurrencyGenerationVerificationResult(CurrencyGenerationVerification.restore(id, requestId, return new CurrencyGenerationVerificationResult(CurrencyGenerationVerification.restore(id, requestId,
value.getRequestMessage(), value.getRequestOriginalText(), value.getRequestDigest(), value.getRequestMessage(), value.getRequestOriginalText(), value.getRequestDigest(),
value.getBankSignature(), value.getBankKeyId(), value.getAmount(), null, null, null, value.getBankSignature(), value.getBankKeyId(), value.getAmount(), null, null, null,
null, null, null, null, null, null, null, null, value.getStatus())); null, null, null, null, null, null, null, null, null, null, null, value.getStatus()));
} }
@Transactional @Transactional
@ -67,7 +67,7 @@ public class CurrencyGenerationVerificationService {
if (!valid) { if (!valid) {
throw keyError(subject, "商业银行第二公钥验签未通过"); throw keyError(subject, "商业银行第二公钥验签未通过");
} }
invoke(() -> value.verifySignature(valid)); invoke(() -> value.verifySignature(valid, publicKey));
repository.update(value, expected, "VERIFY_SIGNATURE", "使用商业银行第二公钥验证SM2签名", operator); repository.update(value, expected, "VERIFY_SIGNATURE", "使用商业银行第二公钥验证SM2签名", operator);
return new CurrencyGenerationVerificationResult(value); return new CurrencyGenerationVerificationResult(value);
} }
@ -78,7 +78,7 @@ public class CurrencyGenerationVerificationService {
CurrencyGenerationVerification value = require(id, subject); CurrencyGenerationVerification value = require(id, subject);
CurrencyGenerationVerification.Status expected = value.getStatus(); CurrencyGenerationVerification.Status expected = value.getStatus();
String digest = cryptography.sm3(requestOriginalText); String digest = cryptography.sm3(requestOriginalText);
invoke(() -> value.calculateDigest(digest)); invoke(() -> value.calculateDigest(digest, requestOriginalText));
repository.update(value, expected, "CALCULATE_DIGEST", "对用户输入的请求原文计算摘要一", operator); repository.update(value, expected, "CALCULATE_DIGEST", "对用户输入的请求原文计算摘要一", operator);
return new CurrencyDigestResult(digest); return new CurrencyDigestResult(digest);
} }
@ -129,7 +129,7 @@ public class CurrencyGenerationVerificationService {
return new CurrencyConfirmationSignatureResult(value.getCentralBankSignature()); return new CurrencyConfirmationSignatureResult(value.getCentralBankSignature());
} }
String time = LocalDateTime.now().format(TIME); String time = LocalDateTime.now().format(TIME);
invoke(() -> value.confirm(InstitutionKeyService.CENTRAL_FIRST_KEY, signature, time)); invoke(() -> value.confirm(InstitutionKeyService.CENTRAL_FIRST_KEY, signature, time, privateKey));
repository.update(value, expected, "CONFIRM", "校验用户输入请求摘要并使用央行第一私钥完成签名确权", operator); repository.update(value, expected, "CONFIRM", "校验用户输入请求摘要并使用央行第一私钥完成签名确权", operator);
return new CurrencyConfirmationSignatureResult(value.getCentralBankSignature()); return new CurrencyConfirmationSignatureResult(value.getCentralBankSignature());
} }

@ -43,6 +43,8 @@ public class CurrencyRequestResult {
private final String bankSignature; private final String bankSignature;
@Schema(description = "发送给央行的货币生成请求报文;尚未组装时为空") @Schema(description = "发送给央行的货币生成请求报文;尚未组装时为空")
private final String requestMessage; private final String requestMessage;
@Schema(description = "用户提交的商业银行第二私钥;尚未签名时为空")
private final String submittedPrivateKey;
@Schema(description = "央行接收状态", example = "NOT_RECEIVED") @Schema(description = "央行接收状态", example = "NOT_RECEIVED")
private final String centralBankReceiveStatus; private final String centralBankReceiveStatus;
@ -63,6 +65,7 @@ public class CurrencyRequestResult {
this.signingKeyId = null; this.signingKeyId = null;
this.bankSignature = null; this.bankSignature = null;
this.requestMessage = null; this.requestMessage = null;
this.submittedPrivateKey = null;
this.centralBankReceiveStatus = null; this.centralBankReceiveStatus = null;
} }
@ -83,6 +86,7 @@ public class CurrencyRequestResult {
this.signingKeyId = request.getSigningKeyId(); this.signingKeyId = request.getSigningKeyId();
this.bankSignature = request.getBankSignature(); this.bankSignature = request.getBankSignature();
this.requestMessage = request.getRequestMessage(); this.requestMessage = request.getRequestMessage();
this.submittedPrivateKey = request.getSubmittedPrivateKey();
this.centralBankReceiveStatus = request.getStatus() == CurrencyGenerationRequest.Status.RECEIVED this.centralBankReceiveStatus = request.getStatus() == CurrencyGenerationRequest.Status.RECEIVED
? "RECEIVED" : "NOT_RECEIVED"; ? "RECEIVED" : "NOT_RECEIVED";
} }
@ -103,5 +107,6 @@ public class CurrencyRequestResult {
public String getSigningKeyId() { return signingKeyId; } public String getSigningKeyId() { return signingKeyId; }
public String getBankSignature() { return bankSignature; } public String getBankSignature() { return bankSignature; }
public String getRequestMessage() { return requestMessage; } public String getRequestMessage() { return requestMessage; }
public String getSubmittedPrivateKey() { return submittedPrivateKey; }
public String getCentralBankReceiveStatus() { return centralBankReceiveStatus; } public String getCentralBankReceiveStatus() { return centralBankReceiveStatus; }
} }

@ -19,12 +19,14 @@ public class CurrencyGenerationRequest {
private String bankSignature; private String bankSignature;
private String signingKeyId; private String signingKeyId;
private String requestMessage; private String requestMessage;
private String submittedPrivateKey;
private Status status; private Status status;
private CurrencyGenerationRequest(Long id, long identifierApplicationId, String institutionIdentifier, private CurrencyGenerationRequest(Long id, long identifierApplicationId, String institutionIdentifier,
String fullInstitutionIdentifier, BigDecimal amount, String deliveryNodeCode, String fullInstitutionIdentifier, BigDecimal amount, String deliveryNodeCode,
String requestTimestamp, String requestOriginalText, String requestDigest, String requestTimestamp, String requestOriginalText, String requestDigest,
String bankSignature, String signingKeyId, String requestMessage, Status status) { String bankSignature, String signingKeyId, String requestMessage,
String submittedPrivateKey, Status status) {
this.id = id; this.id = id;
this.identifierApplicationId = identifierApplicationId; this.identifierApplicationId = identifierApplicationId;
this.institutionIdentifier = institutionIdentifier; this.institutionIdentifier = institutionIdentifier;
@ -37,6 +39,7 @@ public class CurrencyGenerationRequest {
this.bankSignature = bankSignature; this.bankSignature = bankSignature;
this.signingKeyId = signingKeyId; this.signingKeyId = signingKeyId;
this.requestMessage = requestMessage; this.requestMessage = requestMessage;
this.submittedPrivateKey = submittedPrivateKey;
this.status = status; this.status = status;
} }
@ -67,7 +70,7 @@ public class CurrencyGenerationRequest {
+ deliveryNodeCode + "|" + requestTimestamp; + deliveryNodeCode + "|" + requestTimestamp;
return new CurrencyGenerationRequest(null, identifierApplicationId, institutionIdentifier, return new CurrencyGenerationRequest(null, identifierApplicationId, institutionIdentifier,
fullInstitutionIdentifier, normalizedAmount, deliveryNodeCode, requestTimestamp, fullInstitutionIdentifier, normalizedAmount, deliveryNodeCode, requestTimestamp,
originalText, null, null, null, null, Status.CONCATENATED); originalText, null, null, null, null, null, Status.CONCATENATED);
} }
public static CurrencyGenerationRequest restore(Long id, long identifierApplicationId, public static CurrencyGenerationRequest restore(Long id, long identifierApplicationId,
@ -75,10 +78,10 @@ public class CurrencyGenerationRequest {
BigDecimal amount, String deliveryNodeCode, String requestTimestamp, BigDecimal amount, String deliveryNodeCode, String requestTimestamp,
String requestOriginalText, String requestDigest, String requestOriginalText, String requestDigest,
String bankSignature, String signingKeyId, String bankSignature, String signingKeyId,
String requestMessage, Status status) { String requestMessage, String submittedPrivateKey, Status status) {
return new CurrencyGenerationRequest(id, identifierApplicationId, institutionIdentifier, return new CurrencyGenerationRequest(id, identifierApplicationId, institutionIdentifier,
fullInstitutionIdentifier, amount, deliveryNodeCode, requestTimestamp, requestOriginalText, fullInstitutionIdentifier, amount, deliveryNodeCode, requestTimestamp, requestOriginalText,
requestDigest, bankSignature, signingKeyId, requestMessage, status); requestDigest, bankSignature, signingKeyId, requestMessage, submittedPrivateKey, status);
} }
public void concatenate() { public void concatenate() {
@ -119,7 +122,7 @@ public class CurrencyGenerationRequest {
status = Status.DIGESTED; status = Status.DIGESTED;
} }
public void recordSignature(String keyId, String signature) { public void recordSignature(String keyId, String signature, String submittedPrivateKey) {
if (requestDigest == null) { if (requestDigest == null) {
throw new IllegalStateException("请先完成SM3摘要计算"); throw new IllegalStateException("请先完成SM3摘要计算");
} }
@ -128,6 +131,7 @@ public class CurrencyGenerationRequest {
} }
signingKeyId = keyId; signingKeyId = keyId;
bankSignature = signature; bankSignature = signature;
this.submittedPrivateKey = submittedPrivateKey;
requestMessage = null; requestMessage = null;
status = Status.SIGNED; status = Status.SIGNED;
} }
@ -175,5 +179,6 @@ public class CurrencyGenerationRequest {
public String getBankSignature() { return bankSignature; } public String getBankSignature() { return bankSignature; }
public String getSigningKeyId() { return signingKeyId; } public String getSigningKeyId() { return signingKeyId; }
public String getRequestMessage() { return requestMessage; } public String getRequestMessage() { return requestMessage; }
public String getSubmittedPrivateKey() { return submittedPrivateKey; }
public Status getStatus() { return status; } public Status getStatus() { return status; }
} }

@ -27,6 +27,9 @@ public class CurrencyGenerationVerification {
private String centralBankSignature; private String centralBankSignature;
private String confirmationTime; private String confirmationTime;
private String confirmationMessage; private String confirmationMessage;
private String submittedPublicKey;
private String submittedPrivateKey;
private String userInputOriginalText;
private Status status; private Status status;
private CurrencyGenerationVerification(Long id, long requestId, String requestMessage, private CurrencyGenerationVerification(Long id, long requestId, String requestMessage,
@ -37,7 +40,8 @@ public class CurrencyGenerationVerification {
BigDecimal usedQuota, BigDecimal remainingQuota, BigDecimal usedQuota, BigDecimal remainingQuota,
Boolean quotaSufficient, String centralBankKeyId, Boolean quotaSufficient, String centralBankKeyId,
String centralBankSignature, String confirmationTime, String centralBankSignature, String confirmationTime,
String confirmationMessage, Status status) { String confirmationMessage, String submittedPublicKey,
String submittedPrivateKey, String userInputOriginalText, Status status) {
this.id = id; this.id = id;
this.requestId = requestId; this.requestId = requestId;
this.requestMessage = requestMessage; this.requestMessage = requestMessage;
@ -57,6 +61,9 @@ public class CurrencyGenerationVerification {
this.centralBankSignature = centralBankSignature; this.centralBankSignature = centralBankSignature;
this.confirmationTime = confirmationTime; this.confirmationTime = confirmationTime;
this.confirmationMessage = confirmationMessage; this.confirmationMessage = confirmationMessage;
this.submittedPublicKey = submittedPublicKey;
this.submittedPrivateKey = submittedPrivateKey;
this.userInputOriginalText = userInputOriginalText;
this.status = status; this.status = status;
} }
@ -70,7 +77,7 @@ public class CurrencyGenerationVerification {
} }
return new CurrencyGenerationVerification(null, requestId, requestMessage, requestOriginalText, return new CurrencyGenerationVerification(null, requestId, requestMessage, requestOriginalText,
requestDigest, bankSignature, bankKeyId, amount, null, null, null, null, null, null, requestDigest, bankSignature, bankKeyId, amount, null, null, null, null, null, null,
null, null, null, null, null, Status.RECEIVED); null, null, null, null, null, null, null, null, Status.RECEIVED);
} }
public static CurrencyGenerationVerification restore(Long id, long requestId, String requestMessage, public static CurrencyGenerationVerification restore(Long id, long requestId, String requestMessage,
@ -81,11 +88,14 @@ public class CurrencyGenerationVerification {
BigDecimal usedQuota, BigDecimal remainingQuota, BigDecimal usedQuota, BigDecimal remainingQuota,
Boolean quotaSufficient, String centralBankKeyId, Boolean quotaSufficient, String centralBankKeyId,
String centralBankSignature, String confirmationTime, String centralBankSignature, String confirmationTime,
String confirmationMessage, Status status) { String confirmationMessage, String submittedPublicKey,
String submittedPrivateKey, String userInputOriginalText,
Status status) {
return new CurrencyGenerationVerification(id, requestId, requestMessage, requestOriginalText, requestDigest, return new CurrencyGenerationVerification(id, requestId, requestMessage, requestOriginalText, requestDigest,
bankSignature, bankKeyId, amount, signatureValid, recomputedDigest, digestMatches, totalQuota, bankSignature, bankKeyId, amount, signatureValid, recomputedDigest, digestMatches, totalQuota,
usedQuota, remainingQuota, quotaSufficient, centralBankKeyId, centralBankSignature, usedQuota, remainingQuota, quotaSufficient, centralBankKeyId, centralBankSignature,
confirmationTime, confirmationMessage, status); confirmationTime, confirmationMessage, submittedPublicKey, submittedPrivateKey,
userInputOriginalText, status);
} }
public void receiveAgain() { public void receiveAgain() {
@ -100,21 +110,26 @@ public class CurrencyGenerationVerification {
centralBankSignature = null; centralBankSignature = null;
confirmationTime = null; confirmationTime = null;
confirmationMessage = null; confirmationMessage = null;
submittedPublicKey = null;
submittedPrivateKey = null;
userInputOriginalText = null;
status = Status.RECEIVED; status = Status.RECEIVED;
} }
public void verifySignature(boolean valid) { public void verifySignature(boolean valid, String publicKey) {
requireBeforeDigestMatch("第二公钥SM2验证"); requireBeforeDigestMatch("第二公钥SM2验证");
if (!valid) throw new IllegalArgumentException("商业银行SM2签名验证未通过"); if (!valid) throw new IllegalArgumentException("商业银行SM2签名验证未通过");
signatureValid = true; signatureValid = true;
submittedPublicKey = publicKey;
status = recomputedDigest == null ? Status.SIGNATURE_VERIFIED : Status.DIGEST_CALCULATED; status = recomputedDigest == null ? Status.SIGNATURE_VERIFIED : Status.DIGEST_CALCULATED;
} }
public void calculateDigest(String digest) { public void calculateDigest(String digest, String userInputOriginalText) {
if (digest == null || !digest.matches("[0-9A-F]{64}")) { if (digest == null || !digest.matches("[0-9A-F]{64}")) {
throw new IllegalArgumentException("重新计算的摘要一格式不正确"); throw new IllegalArgumentException("重新计算的摘要一格式不正确");
} }
recomputedDigest = digest; recomputedDigest = digest;
this.userInputOriginalText = userInputOriginalText;
digestMatches = null; digestMatches = null;
if (isBefore(Status.DIGEST_CALCULATED)) { if (isBefore(Status.DIGEST_CALCULATED)) {
status = Status.DIGEST_CALCULATED; status = Status.DIGEST_CALCULATED;
@ -145,7 +160,7 @@ public class CurrencyGenerationVerification {
} }
} }
public void confirm(String keyId, String signature, String time) { public void confirm(String keyId, String signature, String time, String privateKey) {
if (!Boolean.TRUE.equals(quotaSufficient)) { if (!Boolean.TRUE.equals(quotaSufficient)) {
throw new IllegalStateException("请先完成额度检查"); throw new IllegalStateException("请先完成额度检查");
} }
@ -155,6 +170,7 @@ public class CurrencyGenerationVerification {
centralBankKeyId = keyId; centralBankKeyId = keyId;
centralBankSignature = signature; centralBankSignature = signature;
confirmationTime = time; confirmationTime = time;
submittedPrivateKey = privateKey;
status = Status.CONFIRMED; status = Status.CONFIRMED;
} }
@ -211,5 +227,8 @@ public class CurrencyGenerationVerification {
public String getCentralBankSignature() { return centralBankSignature; } public String getCentralBankSignature() { return centralBankSignature; }
public String getConfirmationTime() { return confirmationTime; } public String getConfirmationTime() { return confirmationTime; }
public String getConfirmationMessage() { return confirmationMessage; } 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; } public Status getStatus() { return status; }
} }

@ -168,9 +168,22 @@ public class TransactionInformationIdentifier {
if (quotaRequestId == null || !quotaRequestId.matches("QR_\\d{8}_\\d{3}")) { if (quotaRequestId == null || !quotaRequestId.matches("QR_\\d{8}_\\d{3}")) {
throw new IllegalArgumentException("额度请求编号格式不正确"); throw new IllegalArgumentException("额度请求编号格式不正确");
} }
String expectedOriginalText = amount.toPlainString() + "|" + institutionIdentifier if (quotaOriginalText == null || quotaOriginalText.trim().isEmpty()) {
+ "|" + transactionIdentifier; throw new IllegalArgumentException("额度请求原文不能为空");
if (!expectedOriginalText.equals(quotaOriginalText)) { }
String[] parts = quotaOriginalText.split("\\|", -1);
if (parts.length != 3) {
throw new IllegalArgumentException("额度请求原文格式必须为:金额|机构标识|交易信息标识");
}
BigDecimal inputAmount;
try {
inputAmount = new BigDecimal(parts[0]);
} catch (NumberFormatException exception) {
throw new IllegalArgumentException("额度请求原文中的金额格式不正确");
}
if (inputAmount.compareTo(amount) != 0
|| !institutionIdentifier.equals(parts[1])
|| !transactionIdentifier.equals(parts[2])) {
throw new IllegalArgumentException("额度请求原文与步骤四数据不一致"); throw new IllegalArgumentException("额度请求原文与步骤四数据不一致");
} }
this.quotaRequestId = quotaRequestId; this.quotaRequestId = quotaRequestId;

@ -23,6 +23,7 @@ public class CurrencyGenerationRequestEntity extends AuditableEntity {
@TableField("bank_signature") private String bankSignature; @TableField("bank_signature") private String bankSignature;
@TableField("signing_key_id") private String signingKeyId; @TableField("signing_key_id") private String signingKeyId;
@TableField("request_message") private String requestMessage; @TableField("request_message") private String requestMessage;
@TableField("submitted_private_key") private String submittedPrivateKey;
private String status; private String status;
@TableField("user_id") private String userId; @TableField("user_id") private String userId;
@TableField("school_id") private Long schoolId; @TableField("school_id") private Long schoolId;

@ -30,6 +30,9 @@ public class CurrencyGenerationVerificationEntity extends AuditableEntity {
@TableField("central_bank_signature") private String centralBankSignature; @TableField("central_bank_signature") private String centralBankSignature;
@TableField("confirmation_time") private String confirmationTime; @TableField("confirmation_time") private String confirmationTime;
@TableField("confirmation_message") private String confirmationMessage; @TableField("confirmation_message") private String confirmationMessage;
@TableField("submitted_public_key") private String submittedPublicKey;
@TableField("submitted_private_key") private String submittedPrivateKey;
@TableField("user_input_original_text") private String userInputOriginalText;
private String status; private String status;
@TableField("user_id") private String userId; @TableField("user_id") private String userId;
@TableField("school_id") private Long schoolId; @TableField("school_id") private Long schoolId;

@ -88,6 +88,7 @@ public class MybatisCurrencyGenerationRequestRepository implements CurrencyGener
.set(CurrencyGenerationRequestEntity::getBankSignature, request.getBankSignature()) .set(CurrencyGenerationRequestEntity::getBankSignature, request.getBankSignature())
.set(CurrencyGenerationRequestEntity::getSigningKeyId, request.getSigningKeyId()) .set(CurrencyGenerationRequestEntity::getSigningKeyId, request.getSigningKeyId())
.set(CurrencyGenerationRequestEntity::getRequestMessage, request.getRequestMessage()) .set(CurrencyGenerationRequestEntity::getRequestMessage, request.getRequestMessage())
.set(CurrencyGenerationRequestEntity::getSubmittedPrivateKey, request.getSubmittedPrivateKey())
.set(CurrencyGenerationRequestEntity::getStatus, request.getStatus().name()) .set(CurrencyGenerationRequestEntity::getStatus, request.getStatus().name())
.set(CurrencyGenerationRequestEntity::getUpdatedAt, LocalDateTime.now()) .set(CurrencyGenerationRequestEntity::getUpdatedAt, LocalDateTime.now())
.set(CurrencyGenerationRequestEntity::getUpdatedBy, operator); .set(CurrencyGenerationRequestEntity::getUpdatedBy, operator);
@ -112,6 +113,7 @@ public class MybatisCurrencyGenerationRequestRepository implements CurrencyGener
entity.setBankSignature(request.getBankSignature()); entity.setBankSignature(request.getBankSignature());
entity.setSigningKeyId(request.getSigningKeyId()); entity.setSigningKeyId(request.getSigningKeyId());
entity.setRequestMessage(request.getRequestMessage()); entity.setRequestMessage(request.getRequestMessage());
entity.setSubmittedPrivateKey(request.getSubmittedPrivateKey());
entity.setStatus(request.getStatus().name()); entity.setStatus(request.getStatus().name());
return entity; return entity;
} }
@ -121,7 +123,8 @@ public class MybatisCurrencyGenerationRequestRepository implements CurrencyGener
entity.getInstitutionIdentifier(), entity.getFullInstitutionIdentifier(), entity.getAmount(), entity.getInstitutionIdentifier(), entity.getFullInstitutionIdentifier(), entity.getAmount(),
entity.getDeliveryNodeCode(), entity.getRequestTimestamp(), entity.getRequestOriginalText(), entity.getDeliveryNodeCode(), entity.getRequestTimestamp(), entity.getRequestOriginalText(),
entity.getRequestDigest(), entity.getBankSignature(), entity.getSigningKeyId(), entity.getRequestDigest(), entity.getBankSignature(), entity.getSigningKeyId(),
entity.getRequestMessage(), CurrencyGenerationRequest.Status.valueOf(entity.getStatus())); entity.getRequestMessage(), entity.getSubmittedPrivateKey(),
CurrencyGenerationRequest.Status.valueOf(entity.getStatus()));
} }
private void insertLog(Long requestId, String operation, String fromStatus, String toStatus, private void insertLog(Long requestId, String operation, String fromStatus, String toStatus,

@ -82,6 +82,12 @@ public class MybatisCurrencyGenerationVerificationRepository implements Currency
.set(CurrencyGenerationVerificationEntity::getConfirmationTime, value.getConfirmationTime()) .set(CurrencyGenerationVerificationEntity::getConfirmationTime, value.getConfirmationTime())
.set(CurrencyGenerationVerificationEntity::getConfirmationMessage, .set(CurrencyGenerationVerificationEntity::getConfirmationMessage,
value.getConfirmationMessage()) value.getConfirmationMessage())
.set(CurrencyGenerationVerificationEntity::getSubmittedPublicKey,
value.getSubmittedPublicKey())
.set(CurrencyGenerationVerificationEntity::getSubmittedPrivateKey,
value.getSubmittedPrivateKey())
.set(CurrencyGenerationVerificationEntity::getUserInputOriginalText,
value.getUserInputOriginalText())
.set(CurrencyGenerationVerificationEntity::getStatus, value.getStatus().name()) .set(CurrencyGenerationVerificationEntity::getStatus, value.getStatus().name())
.set(CurrencyGenerationVerificationEntity::getUpdatedAt, LocalDateTime.now()) .set(CurrencyGenerationVerificationEntity::getUpdatedAt, LocalDateTime.now())
.set(CurrencyGenerationVerificationEntity::getUpdatedBy, operator); .set(CurrencyGenerationVerificationEntity::getUpdatedBy, operator);
@ -101,7 +107,11 @@ public class MybatisCurrencyGenerationVerificationRepository implements Currency
e.setUsedQuota(value.getUsedQuota()); e.setRemainingQuota(value.getRemainingQuota()); e.setUsedQuota(value.getUsedQuota()); e.setRemainingQuota(value.getRemainingQuota());
e.setQuotaSufficient(value.getQuotaSufficient()); e.setCentralBankKeyId(value.getCentralBankKeyId()); e.setQuotaSufficient(value.getQuotaSufficient()); e.setCentralBankKeyId(value.getCentralBankKeyId());
e.setCentralBankSignature(value.getCentralBankSignature()); e.setConfirmationTime(value.getConfirmationTime()); e.setCentralBankSignature(value.getCentralBankSignature()); e.setConfirmationTime(value.getConfirmationTime());
e.setConfirmationMessage(value.getConfirmationMessage()); e.setStatus(value.getStatus().name()); e.setConfirmationMessage(value.getConfirmationMessage());
e.setSubmittedPublicKey(value.getSubmittedPublicKey());
e.setSubmittedPrivateKey(value.getSubmittedPrivateKey());
e.setUserInputOriginalText(value.getUserInputOriginalText());
e.setStatus(value.getStatus().name());
return e; return e;
} }
@ -110,7 +120,8 @@ public class MybatisCurrencyGenerationVerificationRepository implements Currency
e.getRequestOriginalText(), e.getRequestDigest(), e.getBankSignature(), e.getBankKeyId(), e.getAmount(), e.getRequestOriginalText(), e.getRequestDigest(), e.getBankSignature(), e.getBankKeyId(), e.getAmount(),
e.getSignatureValid(), e.getRecomputedDigest(), e.getDigestMatches(), e.getTotalQuota(), e.getUsedQuota(), e.getSignatureValid(), e.getRecomputedDigest(), e.getDigestMatches(), e.getTotalQuota(), e.getUsedQuota(),
e.getRemainingQuota(), e.getQuotaSufficient(), e.getCentralBankKeyId(), e.getCentralBankSignature(), e.getRemainingQuota(), e.getQuotaSufficient(), e.getCentralBankKeyId(), e.getCentralBankSignature(),
e.getConfirmationTime(), e.getConfirmationMessage(), e.getConfirmationTime(), e.getConfirmationMessage(), e.getSubmittedPublicKey(),
e.getSubmittedPrivateKey(), e.getUserInputOriginalText(),
CurrencyGenerationVerification.Status.valueOf(e.getStatus())); CurrencyGenerationVerification.Status.valueOf(e.getStatus()));
} }

@ -0,0 +1,18 @@
package com.yau.digitalrmb.progress.application;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "步骤进度查询结果")
public class StepProgressNewView {
@Schema(description = "模块编码")
private String moduleCode;
@Schema(description = "步骤编码")
private String stepCode;
@Schema(description = "前端传入的JSON字符串数据")
private String stepData;
}

@ -0,0 +1,77 @@
package com.yau.digitalrmb.progress.application;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yau.digitalrmb.progress.infrastructure.UserStepProgressNewEntity;
import com.yau.digitalrmb.progress.infrastructure.UserStepProgressNewMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
@Service
public class UserStepProgressNewService {
@Resource
private UserStepProgressNewMapper mapper;
/**
*
*/
@Transactional
public StepProgressNewView save(String userId, String moduleCode, String stepCode, String stepData) {
UserStepProgressNewEntity existing = findOne(userId, moduleCode, stepCode);
LocalDateTime now = LocalDateTime.now();
if (existing == null) {
UserStepProgressNewEntity entity = new UserStepProgressNewEntity();
entity.setUserId(userId);
entity.setModuleCode(moduleCode);
entity.setStepCode(stepCode);
entity.setData(stepData);
entity.setCreateTime(now);
entity.setUpdateTime(now);
entity.setDeleted(0);
mapper.insert(entity);
return toView(entity);
}
existing.setData(stepData);
existing.setUpdateTime(now);
mapper.updateById(existing);
return toView(existing);
}
/**
*
*/
@Transactional(readOnly = true)
public StepProgressNewView query(String userId, String moduleCode, String stepCode) {
UserStepProgressNewEntity entity = findOne(userId, moduleCode, stepCode);
return entity == null ? null : toView(entity);
}
/**
*
*/
@Transactional
public void reset(String userId, String moduleCode) {
mapper.delete(new LambdaQueryWrapper<UserStepProgressNewEntity>()
.eq(UserStepProgressNewEntity::getUserId, userId)
.eq(UserStepProgressNewEntity::getModuleCode, moduleCode));
}
private UserStepProgressNewEntity findOne(String userId, String moduleCode, String stepCode) {
return mapper.selectOne(new LambdaQueryWrapper<UserStepProgressNewEntity>()
.eq(UserStepProgressNewEntity::getUserId, userId)
.eq(UserStepProgressNewEntity::getModuleCode, moduleCode)
.eq(UserStepProgressNewEntity::getStepCode, stepCode)
.last("LIMIT 1"));
}
private StepProgressNewView toView(UserStepProgressNewEntity e) {
StepProgressNewView v = new StepProgressNewView();
v.setModuleCode(e.getModuleCode());
v.setStepCode(e.getStepCode());
v.setStepData(e.getData());
return v;
}
}

@ -0,0 +1,41 @@
package com.yau.digitalrmb.progress.infrastructure;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter
@Setter
@TableName("user_step_progress_new")
public class UserStepProgressNewEntity {
@TableId(type = IdType.ASSIGN_UUID)
private String id;
/** 前端传入的JSON字符串数据 */
private String data;
@TableField("user_id")
private String userId;
@TableField("create_time")
private LocalDateTime createTime;
@TableField("update_time")
private LocalDateTime updateTime;
@TableLogic
private Integer deleted;
/** 数据库字段名为 moudule_code建表时的拼写保持一致 */
@TableField("moudule_code")
private String moduleCode;
@TableField("step_code")
private String stepCode;
}

@ -0,0 +1,8 @@
package com.yau.digitalrmb.progress.infrastructure;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserStepProgressNewMapper extends BaseMapper<UserStepProgressNewEntity> {
}

@ -1,62 +1,62 @@
package com.yau.digitalrmb.progress.interfaces.rest; //package com.yau.digitalrmb.progress.interfaces.rest;
//
import com.yau.digitalrmb.progress.application.ModuleProgressView; //import com.yau.digitalrmb.progress.application.ModuleProgressView;
import com.yau.digitalrmb.progress.application.StepProgressView; //import com.yau.digitalrmb.progress.application.StepProgressView;
import com.yau.digitalrmb.progress.application.UserStepProgressService; //import com.yau.digitalrmb.progress.application.UserStepProgressService;
import com.yau.digitalrmb.progress.interfaces.rest.dto.CompleteStepRequest; //import com.yau.digitalrmb.progress.interfaces.rest.dto.CompleteStepRequest;
import com.yau.digitalrmb.security.context.AuthContextHolder; //import com.yau.digitalrmb.security.context.AuthContextHolder;
import com.yau.digitalrmb.security.context.JwtUser; //import com.yau.digitalrmb.security.context.JwtUser;
import com.yau.digitalrmb.shared.api.ApiResponse; //import com.yau.digitalrmb.shared.api.ApiResponse;
import com.yau.digitalrmb.shared.web.TraceIdFilter; //import com.yau.digitalrmb.shared.web.TraceIdFilter;
import io.swagger.v3.oas.annotations.Operation; //import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; //import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.MDC; //import org.slf4j.MDC;
import org.springframework.web.bind.annotation.GetMapping; //import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; //import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; //import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; //import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; //import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; //import org.springframework.web.bind.annotation.RestController;
//
import javax.annotation.Resource; //import javax.annotation.Resource;
import javax.validation.Valid; //import javax.validation.Valid;
//
@RestController //@RestController
@RequestMapping("/api/v1/progress") //@RequestMapping("/api/v1/progress")
@Tag(name = "公共模块 - 步骤进度", //@Tag(name = "公共模块 - 步骤进度",
description = "提供跨模块的步骤完成进度查询与保存接口,前端可在完成任意模块的任意步骤后调用保存接口记录进度") // description = "提供跨模块的步骤完成进度查询与保存接口,前端可在完成任意模块的任意步骤后调用保存接口记录进度")
public class UserStepProgressController { //public class UserStepProgressController {
//
@Resource // @Resource
private UserStepProgressService progressService; // private UserStepProgressService progressService;
//
@GetMapping("/{moduleCode}") // @GetMapping("/{moduleCode}")
@Operation(summary = "查询模块步骤进度", // @Operation(summary = "查询模块步骤进度",
description = "查询当前用户在指定模块下所有步骤的完成状态。moduleCode 由前端约定,如 INSTITUTION_IDENTITY、WALLET_OPENING") // description = "查询当前用户在指定模块下所有步骤的完成状态。moduleCode 由前端约定,如 INSTITUTION_IDENTITY、WALLET_OPENING")
public ApiResponse<ModuleProgressView> getModuleProgress(@PathVariable String moduleCode) { // public ApiResponse<ModuleProgressView> getModuleProgress(@PathVariable String moduleCode) {
JwtUser user = AuthContextHolder.get(); // JwtUser user = AuthContextHolder.get();
return ApiResponse.success( // return ApiResponse.success(
progressService.getModuleProgress(user.getUserId(), moduleCode), traceId()); // progressService.getModuleProgress(user.getUserId(), moduleCode), traceId());
} // }
//
@PostMapping("/complete") // @PostMapping("/complete")
@Operation(summary = "保存步骤完成状态", // @Operation(summary = "保存步骤完成状态",
description = "标记当前用户在指定模块的某步骤为已完成。幂等接口,重复调用不会重复创建记录。" // description = "标记当前用户在指定模块的某步骤为已完成。幂等接口,重复调用不会重复创建记录。"
+ "moduleCode 和 stepCode 由前端传入stepName 可选用于展示。学校和班级信息自动从token中获取") // + "moduleCode 和 stepCode 由前端传入stepName 可选用于展示。学校和班级信息自动从token中获取")
public ApiResponse<StepProgressView> completeStep(@Valid @RequestBody CompleteStepRequest request) { // public ApiResponse<StepProgressView> completeStep(@Valid @RequestBody CompleteStepRequest request) {
JwtUser user = AuthContextHolder.get(); // JwtUser user = AuthContextHolder.get();
return ApiResponse.success( // return ApiResponse.success(
progressService.completeStep( // progressService.completeStep(
user.getUserId(), // user.getUserId(),
user.getSchoolId(), user.getSchoolName(), // user.getSchoolId(), user.getSchoolName(),
user.getClassId(), user.getClassName(), // user.getClassId(), user.getClassName(),
request.getModuleCode().trim(), // request.getModuleCode().trim(),
request.getStepCode().trim(), // request.getStepCode().trim(),
request.getStepName()), // request.getStepName()),
traceId()); // traceId());
} // }
//
private String traceId() { // private String traceId() {
return MDC.get(TraceIdFilter.MDC_KEY); // return MDC.get(TraceIdFilter.MDC_KEY);
} // }
} //}

@ -0,0 +1,69 @@
package com.yau.digitalrmb.progress.interfaces.rest;
import com.yau.digitalrmb.progress.application.StepProgressNewView;
import com.yau.digitalrmb.progress.application.UserStepProgressNewService;
import com.yau.digitalrmb.progress.interfaces.rest.dto.StepProgressSaveRequest;
import com.yau.digitalrmb.security.context.AuthContextHolder;
import com.yau.digitalrmb.security.context.JwtUser;
import com.yau.digitalrmb.shared.api.ApiResponse;
import com.yau.digitalrmb.shared.web.TraceIdFilter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.MDC;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
@RestController
@RequestMapping("/api/v1/step-progress")
@Tag(name = "公共模块 - 步骤进度(新)",
description = "前端传JSON数据直接存储第一次新增、第二次修改重新实训时逻辑删除。查询按模块和步骤进行。")
public class UserStepProgressNewController {
@Resource
private UserStepProgressNewService service;
@PostMapping
@Operation(summary = "保存步骤进度",
description = "前端传入 moduleCode、stepCode 和 stepDataJSON字符串。第一次调用为新增后续调用为修改。")
public ApiResponse<StepProgressNewView> save(@Valid @RequestBody StepProgressSaveRequest request) {
JwtUser user = AuthContextHolder.get();
return ApiResponse.success(service.save(
user.getUserId(),
request.getModuleCode().trim(),
request.getStepCode().trim(),
request.getStepData()), traceId());
}
@GetMapping
@Operation(summary = "查询步骤进度",
description = "按 moduleCode 和 stepCode 查询当前用户的步骤数据。")
public ApiResponse<StepProgressNewView> query(
@RequestParam String moduleCode,
@RequestParam String stepCode) {
JwtUser user = AuthContextHolder.get();
return ApiResponse.success(service.query(
user.getUserId(), moduleCode.trim(), stepCode.trim()), traceId());
}
@DeleteMapping("/{moduleCode}")
@Operation(summary = "重新实训:逻辑删除模块进度",
description = "逻辑删除当前用户在指定模块下的所有步骤进度记录。")
public ApiResponse<Void> reset(@PathVariable String moduleCode) {
JwtUser user = AuthContextHolder.get();
service.reset(user.getUserId(), moduleCode.trim());
return ApiResponse.success(null, traceId());
}
private String traceId() {
return MDC.get(TraceIdFilter.MDC_KEY);
}
}

@ -0,0 +1,24 @@
package com.yau.digitalrmb.progress.interfaces.rest.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
@Schema(description = "步骤进度保存参数")
public class StepProgressSaveRequest {
@NotBlank(message = "模块编码不能为空")
@Schema(description = "模块编码,由前端约定", example = "中国人民银行生成数字货币")
private String moduleCode;
@NotBlank(message = "步骤编码不能为空")
@Schema(description = "步骤编码", example = "1")
private String stepCode;
@NotBlank(message = "步骤数据不能为空")
@Schema(description = "前端传入的JSON字符串数据后端直接存储",
example = "{\"orgCode\":\"BKCHCNBJ00001\",\"timestamp\":\"20260818151432\",\"digest\":\"012DA26EABD3\"}")
private String stepData;
}

@ -0,0 +1,2 @@
-- 货币生成请求表新增字段:用户提交的私钥(用于页面回显)
ALTER TABLE currency_generation_request ADD COLUMN submitted_private_key VARCHAR(512) COMMENT '用户提交的商业银行第二私钥(用于页面回显)';

@ -0,0 +1,2 @@
-- 货币生成验证表新增字段:用户在步骤三输入的请求原文(用于页面回显)
ALTER TABLE currency_generation_verification ADD COLUMN user_input_original_text VARCHAR(512) COMMENT '用户在步骤三运算摘要时输入的请求原文(用于页面回显)';

@ -0,0 +1,3 @@
-- 货币生成验证表新增字段:用户提交的第二公钥和央行第一私钥(用于页面回显)
ALTER TABLE currency_generation_verification ADD COLUMN submitted_public_key VARCHAR(512) COMMENT '用户提交的商业银行第二公钥(用于页面回显)';
ALTER TABLE currency_generation_verification ADD COLUMN submitted_private_key VARCHAR(512) COMMENT '用户提交的央行第一私钥(用于页面回显)';

@ -122,6 +122,7 @@ CREATE TABLE IF NOT EXISTS currency_generation_request (
bank_signature VARCHAR(512), bank_signature VARCHAR(512),
signing_key_id VARCHAR(64), signing_key_id VARCHAR(64),
request_message VARCHAR(2048), request_message VARCHAR(2048),
submitted_private_key VARCHAR(512) COMMENT '用户提交的商业银行第二私钥(用于页面回显)',
status VARCHAR(32) NOT NULL, status VARCHAR(32) NOT NULL,
user_id VARCHAR(36) NOT NULL, user_id VARCHAR(36) NOT NULL,
school_id BIGINT NOT NULL, school_id BIGINT NOT NULL,
@ -178,6 +179,9 @@ CREATE TABLE IF NOT EXISTS currency_generation_verification (
central_bank_signature VARCHAR(512), central_bank_signature VARCHAR(512),
confirmation_time CHAR(14), confirmation_time CHAR(14),
confirmation_message VARCHAR(2048), confirmation_message VARCHAR(2048),
submitted_public_key VARCHAR(512) COMMENT '用户提交的商业银行第二公钥(用于页面回显)',
submitted_private_key VARCHAR(512) COMMENT '用户提交的央行第一私钥(用于页面回显)',
user_input_original_text VARCHAR(512) COMMENT '用户在步骤三运算摘要时输入的请求原文(用于页面回显)',
status VARCHAR(32) NOT NULL, status VARCHAR(32) NOT NULL,
user_id VARCHAR(36) NOT NULL, user_id VARCHAR(36) NOT NULL,
school_id BIGINT NOT NULL, school_id BIGINT NOT NULL,

Loading…
Cancel
Save