feat:文件上传的功能开发

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

@ -52,7 +52,7 @@ public class CurrencyGenerationRequestService {
request = CurrencyGenerationRequest.restore(requestId, input.getIdentifierApplicationId(),
input.getInstitutionIdentifier(), input.getFullInstitutionIdentifier(), input.getAmount(),
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());
CurrencyGenerationRequest.Status expected = request.getStatus();
@ -77,7 +77,7 @@ public class CurrencyGenerationRequestService {
"签名必须使用当前实训主体的商业银行第二私钥,本次实训第"
+ 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);
return new CurrencyRequestResult(request);
}

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

@ -51,7 +51,7 @@ public class CurrencyGenerationVerificationService {
return new CurrencyGenerationVerificationResult(CurrencyGenerationVerification.restore(id, requestId,
value.getRequestMessage(), value.getRequestOriginalText(), value.getRequestDigest(),
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
@ -67,7 +67,7 @@ public class CurrencyGenerationVerificationService {
if (!valid) {
throw keyError(subject, "商业银行第二公钥验签未通过");
}
invoke(() -> value.verifySignature(valid));
invoke(() -> value.verifySignature(valid, publicKey));
repository.update(value, expected, "VERIFY_SIGNATURE", "使用商业银行第二公钥验证SM2签名", operator);
return new CurrencyGenerationVerificationResult(value);
}
@ -78,7 +78,7 @@ public class CurrencyGenerationVerificationService {
CurrencyGenerationVerification value = require(id, subject);
CurrencyGenerationVerification.Status expected = value.getStatus();
String digest = cryptography.sm3(requestOriginalText);
invoke(() -> value.calculateDigest(digest));
invoke(() -> value.calculateDigest(digest, requestOriginalText));
repository.update(value, expected, "CALCULATE_DIGEST", "对用户输入的请求原文计算摘要一", operator);
return new CurrencyDigestResult(digest);
}
@ -129,7 +129,7 @@ public class CurrencyGenerationVerificationService {
return new CurrencyConfirmationSignatureResult(value.getCentralBankSignature());
}
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);
return new CurrencyConfirmationSignatureResult(value.getCentralBankSignature());
}

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

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

@ -27,6 +27,9 @@ public class CurrencyGenerationVerification {
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,
@ -37,7 +40,8 @@ public class CurrencyGenerationVerification {
BigDecimal usedQuota, BigDecimal remainingQuota,
Boolean quotaSufficient, String centralBankKeyId,
String centralBankSignature, String confirmationTime,
String confirmationMessage, Status status) {
String confirmationMessage, String submittedPublicKey,
String submittedPrivateKey, String userInputOriginalText, Status status) {
this.id = id;
this.requestId = requestId;
this.requestMessage = requestMessage;
@ -57,6 +61,9 @@ public class CurrencyGenerationVerification {
this.centralBankSignature = centralBankSignature;
this.confirmationTime = confirmationTime;
this.confirmationMessage = confirmationMessage;
this.submittedPublicKey = submittedPublicKey;
this.submittedPrivateKey = submittedPrivateKey;
this.userInputOriginalText = userInputOriginalText;
this.status = status;
}
@ -70,7 +77,7 @@ public class CurrencyGenerationVerification {
}
return new CurrencyGenerationVerification(null, requestId, requestMessage, requestOriginalText,
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,
@ -81,11 +88,14 @@ public class CurrencyGenerationVerification {
BigDecimal usedQuota, BigDecimal remainingQuota,
Boolean quotaSufficient, String centralBankKeyId,
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,
bankSignature, bankKeyId, amount, signatureValid, recomputedDigest, digestMatches, totalQuota,
usedQuota, remainingQuota, quotaSufficient, centralBankKeyId, centralBankSignature,
confirmationTime, confirmationMessage, status);
confirmationTime, confirmationMessage, submittedPublicKey, submittedPrivateKey,
userInputOriginalText, status);
}
public void receiveAgain() {
@ -100,21 +110,26 @@ public class CurrencyGenerationVerification {
centralBankSignature = null;
confirmationTime = null;
confirmationMessage = null;
submittedPublicKey = null;
submittedPrivateKey = null;
userInputOriginalText = null;
status = Status.RECEIVED;
}
public void verifySignature(boolean valid) {
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) {
public void calculateDigest(String digest, String userInputOriginalText) {
if (digest == null || !digest.matches("[0-9A-F]{64}")) {
throw new IllegalArgumentException("重新计算的摘要一格式不正确");
}
recomputedDigest = digest;
this.userInputOriginalText = userInputOriginalText;
digestMatches = null;
if (isBefore(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)) {
throw new IllegalStateException("请先完成额度检查");
}
@ -155,6 +170,7 @@ public class CurrencyGenerationVerification {
centralBankKeyId = keyId;
centralBankSignature = signature;
confirmationTime = time;
submittedPrivateKey = privateKey;
status = Status.CONFIRMED;
}
@ -211,5 +227,8 @@ public class CurrencyGenerationVerification {
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; }
}

@ -168,9 +168,22 @@ public class TransactionInformationIdentifier {
if (quotaRequestId == null || !quotaRequestId.matches("QR_\\d{8}_\\d{3}")) {
throw new IllegalArgumentException("额度请求编号格式不正确");
}
String expectedOriginalText = amount.toPlainString() + "|" + institutionIdentifier
+ "|" + transactionIdentifier;
if (!expectedOriginalText.equals(quotaOriginalText)) {
if (quotaOriginalText == null || quotaOriginalText.trim().isEmpty()) {
throw new IllegalArgumentException("额度请求原文不能为空");
}
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("额度请求原文与步骤四数据不一致");
}
this.quotaRequestId = quotaRequestId;

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

@ -30,6 +30,9 @@ public class CurrencyGenerationVerificationEntity extends AuditableEntity {
@TableField("central_bank_signature") private String centralBankSignature;
@TableField("confirmation_time") private String confirmationTime;
@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;
@TableField("user_id") private String userId;
@TableField("school_id") private Long schoolId;

@ -88,6 +88,7 @@ public class MybatisCurrencyGenerationRequestRepository implements CurrencyGener
.set(CurrencyGenerationRequestEntity::getBankSignature, request.getBankSignature())
.set(CurrencyGenerationRequestEntity::getSigningKeyId, request.getSigningKeyId())
.set(CurrencyGenerationRequestEntity::getRequestMessage, request.getRequestMessage())
.set(CurrencyGenerationRequestEntity::getSubmittedPrivateKey, request.getSubmittedPrivateKey())
.set(CurrencyGenerationRequestEntity::getStatus, request.getStatus().name())
.set(CurrencyGenerationRequestEntity::getUpdatedAt, LocalDateTime.now())
.set(CurrencyGenerationRequestEntity::getUpdatedBy, operator);
@ -112,6 +113,7 @@ public class MybatisCurrencyGenerationRequestRepository implements CurrencyGener
entity.setBankSignature(request.getBankSignature());
entity.setSigningKeyId(request.getSigningKeyId());
entity.setRequestMessage(request.getRequestMessage());
entity.setSubmittedPrivateKey(request.getSubmittedPrivateKey());
entity.setStatus(request.getStatus().name());
return entity;
}
@ -121,7 +123,8 @@ public class MybatisCurrencyGenerationRequestRepository implements CurrencyGener
entity.getInstitutionIdentifier(), entity.getFullInstitutionIdentifier(), entity.getAmount(),
entity.getDeliveryNodeCode(), entity.getRequestTimestamp(), entity.getRequestOriginalText(),
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,

@ -82,6 +82,12 @@ public class MybatisCurrencyGenerationVerificationRepository implements Currency
.set(CurrencyGenerationVerificationEntity::getConfirmationTime, value.getConfirmationTime())
.set(CurrencyGenerationVerificationEntity::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::getUpdatedAt, LocalDateTime.now())
.set(CurrencyGenerationVerificationEntity::getUpdatedBy, operator);
@ -101,7 +107,11 @@ public class MybatisCurrencyGenerationVerificationRepository implements Currency
e.setUsedQuota(value.getUsedQuota()); e.setRemainingQuota(value.getRemainingQuota());
e.setQuotaSufficient(value.getQuotaSufficient()); e.setCentralBankKeyId(value.getCentralBankKeyId());
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;
}
@ -110,7 +120,8 @@ public class MybatisCurrencyGenerationVerificationRepository implements Currency
e.getRequestOriginalText(), e.getRequestDigest(), e.getBankSignature(), e.getBankKeyId(), e.getAmount(),
e.getSignatureValid(), e.getRecomputedDigest(), e.getDigestMatches(), e.getTotalQuota(), e.getUsedQuota(),
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()));
}

@ -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;
import com.yau.digitalrmb.progress.application.ModuleProgressView;
import com.yau.digitalrmb.progress.application.StepProgressView;
import com.yau.digitalrmb.progress.application.UserStepProgressService;
import com.yau.digitalrmb.progress.interfaces.rest.dto.CompleteStepRequest;
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.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.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
@RestController
@RequestMapping("/api/v1/progress")
@Tag(name = "公共模块 - 步骤进度",
description = "提供跨模块的步骤完成进度查询与保存接口,前端可在完成任意模块的任意步骤后调用保存接口记录进度")
public class UserStepProgressController {
@Resource
private UserStepProgressService progressService;
@GetMapping("/{moduleCode}")
@Operation(summary = "查询模块步骤进度",
description = "查询当前用户在指定模块下所有步骤的完成状态。moduleCode 由前端约定,如 INSTITUTION_IDENTITY、WALLET_OPENING")
public ApiResponse<ModuleProgressView> getModuleProgress(@PathVariable String moduleCode) {
JwtUser user = AuthContextHolder.get();
return ApiResponse.success(
progressService.getModuleProgress(user.getUserId(), moduleCode), traceId());
}
@PostMapping("/complete")
@Operation(summary = "保存步骤完成状态",
description = "标记当前用户在指定模块的某步骤为已完成。幂等接口,重复调用不会重复创建记录。"
+ "moduleCode 和 stepCode 由前端传入stepName 可选用于展示。学校和班级信息自动从token中获取")
public ApiResponse<StepProgressView> completeStep(@Valid @RequestBody CompleteStepRequest request) {
JwtUser user = AuthContextHolder.get();
return ApiResponse.success(
progressService.completeStep(
user.getUserId(),
user.getSchoolId(), user.getSchoolName(),
user.getClassId(), user.getClassName(),
request.getModuleCode().trim(),
request.getStepCode().trim(),
request.getStepName()),
traceId());
}
private String traceId() {
return MDC.get(TraceIdFilter.MDC_KEY);
}
}
//package com.yau.digitalrmb.progress.interfaces.rest;
//
//import com.yau.digitalrmb.progress.application.ModuleProgressView;
//import com.yau.digitalrmb.progress.application.StepProgressView;
//import com.yau.digitalrmb.progress.application.UserStepProgressService;
//import com.yau.digitalrmb.progress.interfaces.rest.dto.CompleteStepRequest;
//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.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.RestController;
//
//import javax.annotation.Resource;
//import javax.validation.Valid;
//
//@RestController
//@RequestMapping("/api/v1/progress")
//@Tag(name = "公共模块 - 步骤进度",
// description = "提供跨模块的步骤完成进度查询与保存接口,前端可在完成任意模块的任意步骤后调用保存接口记录进度")
//public class UserStepProgressController {
//
// @Resource
// private UserStepProgressService progressService;
//
// @GetMapping("/{moduleCode}")
// @Operation(summary = "查询模块步骤进度",
// description = "查询当前用户在指定模块下所有步骤的完成状态。moduleCode 由前端约定,如 INSTITUTION_IDENTITY、WALLET_OPENING")
// public ApiResponse<ModuleProgressView> getModuleProgress(@PathVariable String moduleCode) {
// JwtUser user = AuthContextHolder.get();
// return ApiResponse.success(
// progressService.getModuleProgress(user.getUserId(), moduleCode), traceId());
// }
//
// @PostMapping("/complete")
// @Operation(summary = "保存步骤完成状态",
// description = "标记当前用户在指定模块的某步骤为已完成。幂等接口,重复调用不会重复创建记录。"
// + "moduleCode 和 stepCode 由前端传入stepName 可选用于展示。学校和班级信息自动从token中获取")
// public ApiResponse<StepProgressView> completeStep(@Valid @RequestBody CompleteStepRequest request) {
// JwtUser user = AuthContextHolder.get();
// return ApiResponse.success(
// progressService.completeStep(
// user.getUserId(),
// user.getSchoolId(), user.getSchoolName(),
// user.getClassId(), user.getClassName(),
// request.getModuleCode().trim(),
// request.getStepCode().trim(),
// request.getStepName()),
// traceId());
// }
//
// private String traceId() {
// 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),
signing_key_id VARCHAR(64),
request_message VARCHAR(2048),
submitted_private_key VARCHAR(512) COMMENT '用户提交的商业银行第二私钥(用于页面回显)',
status VARCHAR(32) NOT NULL,
user_id VARCHAR(36) NOT NULL,
school_id BIGINT NOT NULL,
@ -178,6 +179,9 @@ CREATE TABLE IF NOT EXISTS currency_generation_verification (
central_bank_signature VARCHAR(512),
confirmation_time CHAR(14),
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,
user_id VARCHAR(36) NOT NULL,
school_id BIGINT NOT NULL,

Loading…
Cancel
Save