From 9a90eb1eee385581b1cdc04e22005f5be85aecf2 Mon Sep 17 00:00:00 2001 From: "jiazheng.zhao" <2624533894@qq.com> Date: Wed, 19 Aug 2026 18:35:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rest/CorporateWalletController.java | 2 +- .../QuotaRequestSourceDataResult.java | 2 + .../application/StandardCurrencyService.java | 32 +++-- ...ansactionInformationIdentifierService.java | 110 ++++++++++++++---- .../interfaces/dto/CurrencyRuleRequest.java | 19 --- .../rest/StandardCurrencyController.java | 27 +++-- .../UserStepProgressNewService.java | 1 + .../application/WalletOpeningService.java | 75 ++++++------ .../rest/WalletOpeningController.java | 15 +-- .../rest/dto/WalletApplicationRequest.java | 9 ++ 10 files changed, 180 insertions(+), 112 deletions(-) delete mode 100644 src/main/java/com/yau/digitalrmb/institutionidentity/interfaces/dto/CurrencyRuleRequest.java diff --git a/src/main/java/com/yau/digitalrmb/corporatewallet/interfaces/rest/CorporateWalletController.java b/src/main/java/com/yau/digitalrmb/corporatewallet/interfaces/rest/CorporateWalletController.java index ed445aa..5b48a8d 100644 --- a/src/main/java/com/yau/digitalrmb/corporatewallet/interfaces/rest/CorporateWalletController.java +++ b/src/main/java/com/yau/digitalrmb/corporatewallet/interfaces/rest/CorporateWalletController.java @@ -39,7 +39,7 @@ public class CorporateWalletController { @PostMapping("/keys") @Operation(summary = "获取全部密钥信息", description = "复用央行第一密钥和商业银行第二密钥,新生成企业法人、数币操作员、数币复核员、监管机构密钥,存储到数据库并返回") - public ApiResponse> getAllKeys() { + public ApiResponse> getAllKeys() { JwtUser jwtUser = AuthContextHolder.get(); return ApiResponse.success(corporateWalletKeyService.getAllKeys( InstitutionKeySubject.from(jwtUser), jwtUser.getUsername()), traceId()); diff --git a/src/main/java/com/yau/digitalrmb/institutionidentity/application/QuotaRequestSourceDataResult.java b/src/main/java/com/yau/digitalrmb/institutionidentity/application/QuotaRequestSourceDataResult.java index c7f04d8..3250721 100644 --- a/src/main/java/com/yau/digitalrmb/institutionidentity/application/QuotaRequestSourceDataResult.java +++ b/src/main/java/com/yau/digitalrmb/institutionidentity/application/QuotaRequestSourceDataResult.java @@ -19,7 +19,9 @@ public class QuotaRequestSourceDataResult { this.transactionIdentifier = value.getTransactionIdentifier(); } + public BigDecimal getAmount() { return amount; } public String getInstitutionIdentifier() { return institutionIdentifier; } public String getTransactionIdentifier() { return transactionIdentifier; } + } diff --git a/src/main/java/com/yau/digitalrmb/institutionidentity/application/StandardCurrencyService.java b/src/main/java/com/yau/digitalrmb/institutionidentity/application/StandardCurrencyService.java index 97ad52e..e680c97 100644 --- a/src/main/java/com/yau/digitalrmb/institutionidentity/application/StandardCurrencyService.java +++ b/src/main/java/com/yau/digitalrmb/institutionidentity/application/StandardCurrencyService.java @@ -96,21 +96,11 @@ public class StandardCurrencyService { } @Transactional - public StandardCurrencyBatchResult confirmRule(String prefix, String idRule, String currencyStatus, - InstitutionKeySubject subject, String operator) { + public CurrencyIdRuleResult confirmIdRule(InstitutionKeySubject subject, String operator) { StandardCurrencyBatchEntity batch = requireLatest(subject); if (batch.getDenominationSummary() == null || batch.getTotalAmount() == null) { throw new BusinessException(ErrorCode.VALIDATION_ERROR, "请先执行面额拆解"); } - if (!"DC".equals(prefix == null ? null : prefix.trim().toUpperCase())) { - throw inputError(subject, "币串前缀必须为DC"); - } - if (!ID_RULE.equals(idRule == null ? null : idRule.trim())) { - throw inputError(subject, "币串ID规则必须为“批次号+枚序号+随机校验码”"); - } - if (!"待生效".equals(currencyStatus == null ? null : currencyStatus.trim())) { - throw inputError(subject, "币串初始状态必须为“待生效”"); - } int updated = batchMapper.update(null, new LambdaUpdateWrapper() .eq(StandardCurrencyBatchEntity::getId, batch.getId()) .eq(StandardCurrencyBatchEntity::getStatus, batch.getStatus()) @@ -122,7 +112,25 @@ public class StandardCurrencyService { .set(StandardCurrencyBatchEntity::getUpdatedAt, LocalDateTime.now()) .set(StandardCurrencyBatchEntity::getUpdatedBy, operator)); if (updated != 1) throw stateChanged(); - return result(requireLatest(subject)); + StandardCurrencyBatchEntity latest = requireLatest(subject); + return new CurrencyIdRuleResult("DC", ID_RULE, + latest.getBatchNumber(), latest.getTotalCount(), latest.getStatus()); + } + + @Transactional + public StandardCurrencyRuleResult confirmCurrencyRule(InstitutionKeySubject subject, String operator) { + StandardCurrencyBatchEntity batch = requireLatest(subject); + if (batch.getPrefix() == null || batch.getIdRule() == null) { + throw new BusinessException(ErrorCode.VALIDATION_ERROR, "请先确认币串ID生成规则"); + } + // 从步骤八获取真实数据 + QuotaControlBitEntity step8 = requireStepEight(subject); + List breakdown = decode(batch.getDenominationSummary()); + BigDecimal firstDenomination = breakdown.isEmpty() ? new BigDecimal("100.00") : breakdown.get(0).getDenomination(); + return new StandardCurrencyRuleResult(batch.getPrefix(), batch.getCurrencyStatus(), + batch.getBatchNumber(), batch.getTotalCount(), batch.getStatus(), + firstDenomination, step8.getInstitutionIdentifier(), + step8.getBankSignature(), step8.getCentralBankSignatureSegment()); } @Transactional diff --git a/src/main/java/com/yau/digitalrmb/institutionidentity/application/TransactionInformationIdentifierService.java b/src/main/java/com/yau/digitalrmb/institutionidentity/application/TransactionInformationIdentifierService.java index 26ff412..97e5e7e 100644 --- a/src/main/java/com/yau/digitalrmb/institutionidentity/application/TransactionInformationIdentifierService.java +++ b/src/main/java/com/yau/digitalrmb/institutionidentity/application/TransactionInformationIdentifierService.java @@ -143,21 +143,64 @@ public class TransactionInformationIdentifierService { return new TransactionIdentifierAssemblyResult(value); } - @Transactional - public QuotaRequestSourceDataResult quotaRequestSourceData(InstitutionKeySubject subject) { - TransactionInformationIdentifier value = repository.findLatestBySubject(subject.getUserId(), - subject.getSchoolId(), subject.getClassId()).orElseThrow(() -> - new BusinessException(ErrorCode.VALIDATION_ERROR, - "步骤四尚未完成交易信息标识组装,不能查询步骤五前序数据")); - if (value.getStatus().ordinal() < TransactionInformationIdentifier.Status.ASSEMBLED.ordinal() - || value.getTransactionIdentifier() == null - || !value.getTransactionIdentifier().matches("TXN_[0-9A-F]{64}")) { - throw new BusinessException(ErrorCode.VALIDATION_ERROR, - "步骤四尚未生成交易信息标识,请先完成步骤四"); - } - return new QuotaRequestSourceDataResult(value); +// @Transactional +// public QuotaRequestSourceDataResult quotaRequestSourceData(InstitutionKeySubject subject) { +// TransactionInformationIdentifier value = repository.findLatestBySubject(subject.getUserId(), +// subject.getSchoolId(), subject.getClassId()).orElseThrow(() -> +// new BusinessException(ErrorCode.VALIDATION_ERROR, +// "步骤四尚未完成交易信息标识组装,不能查询步骤五前序数据")); +// if (value.getStatus().ordinal() < TransactionInformationIdentifier.Status.ASSEMBLED.ordinal() +// || value.getTransactionIdentifier() == null +// || !value.getTransactionIdentifier().matches("TXN_[0-9A-F]{64}")) { +// throw new BusinessException(ErrorCode.VALIDATION_ERROR, +// "步骤四尚未生成交易信息标识,请先完成步骤四"); +// } +// return new QuotaRequestSourceDataResult(value); +// } +//@Transactional(readOnly = true) // 既然只查询,用 readOnly 优化 +//public QuotaRequestSourceDataResult quotaRequestSourceData(InstitutionKeySubject subject) { +// // 1. 尝试查询,查不到则直接返回空结果 +// TransactionInformationIdentifier value = repository.findLatestBySubject( +// subject.getUserId(), subject.getSchoolId(), subject.getClassId()) +// .orElse(null); +// +// // 2. 如果查不到,或者状态/标识不满足条件,返回一个“空”结果对象 +// if (value == null || +// value.getStatus().ordinal() < TransactionInformationIdentifier.Status.ASSEMBLED.ordinal() || +// value.getTransactionIdentifier() == null || +// !value.getTransactionIdentifier().matches("TXN_[0-9A-F]{64}")) { +// +// // 这里返回一个代表“未就绪”的空对象,前端通过检查关键字段(如 transactionIdentifier)是否为 null 来判断 +// return new QuotaRequestSourceDataResult(null); // 假设你在 Result 类里增加了 static empty() 方法 +// } +// +// // 3. 条件满足,正常返回 +// return new QuotaRequestSourceDataResult(value); +//} +@Transactional(readOnly = true) + +public QuotaRequestSourceDataResult quotaRequestSourceData(InstitutionKeySubject subject) { + TransactionInformationIdentifier value = repository.findLatestBySubject( + subject.getUserId(), + subject.getSchoolId(), + subject.getClassId() + ).orElse(null); + + // 无记录 → 返回 null + if (value == null) { + return null; + } + + // 状态或标识不满足条件 → 返回 null + if (value.getStatus().ordinal() < TransactionInformationIdentifier.Status.ASSEMBLED.ordinal() + || value.getTransactionIdentifier() == null + || !value.getTransactionIdentifier().matches("TXN_[0-9A-F]{64}")) { + return null; } + // 正常返回 + return new QuotaRequestSourceDataResult(value); +} @Transactional public QuotaRequestDigestResult digestQuotaRequest(String originalText, InstitutionKeySubject subject, @@ -315,17 +358,31 @@ public class TransactionInformationIdentifierService { return new QuotaVerificationResult(value); } - @Transactional(readOnly = true) - public QuotaRequestMessageResult quotaRequestMessageDetail(InstitutionKeySubject subject) { - return new QuotaRequestMessageResult(requireLatest(subject)); +// @Transactional(readOnly = true) +// public QuotaRequestMessageResult quotaRequestMessageDetail(InstitutionKeySubject subject) { +// return new QuotaRequestMessageResult(requireLatest(subject)); +// } +@Transactional(readOnly = true) +public QuotaRequestMessageResult quotaRequestMessageDetail(InstitutionKeySubject subject) { + TransactionInformationIdentifier value = repository.findLatestBySubject( + subject.getUserId(), + subject.getSchoolId(), + subject.getClassId() + ).orElse(null); + + if (value == null) { + return null; // 返回 null,前端收到 data: null,HTTP 200 } + return new QuotaRequestMessageResult(value); +} @Transactional(readOnly = true) public TransactionInformationIdentifierResult detail(InstitutionKeySubject subject) { - TransactionInformationIdentifier value = repository.findLatestBySubject(subject.getUserId(), - subject.getSchoolId(), subject.getClassId()).orElseThrow(() -> - new BusinessException(ErrorCode.RESOURCE_NOT_FOUND, "当前没有交易信息标识记录")); - return new TransactionInformationIdentifierResult(value); + TransactionInformationIdentifier value = repository.findLatestBySubject( + subject.getUserId(), subject.getSchoolId(), subject.getClassId()) + .orElse(null); // 查不到就返回 null + // 注意:这里 value 可能为 null + return value != null ? new TransactionInformationIdentifierResult(value) : null; } private CurrencyGenerationVerificationEntity requireCompletedVerification(InstitutionKeySubject subject) { @@ -378,18 +435,21 @@ public class TransactionInformationIdentifierService { return value; } - private TransactionInformationIdentifier requireLatest(InstitutionKeySubject subject) { +// private TransactionInformationIdentifier requireLatest(InstitutionKeySubject subject) { +// return repository.findLatestBySubject(subject.getUserId(), subject.getSchoolId(), subject.getClassId()) +// .orElseThrow(() -> new BusinessException(ErrorCode.RESOURCE_NOT_FOUND, +// "当前没有额度请求记录")); +// } + private TransactionInformationIdentifier requireLatest(InstitutionKeySubject subject) { return repository.findLatestBySubject(subject.getUserId(), subject.getSchoolId(), subject.getClassId()) - .orElseThrow(() -> new BusinessException(ErrorCode.RESOURCE_NOT_FOUND, - "当前没有额度请求记录")); + .orElse(null); } private TransactionInformationIdentifier requireStatus(InstitutionKeySubject subject, TransactionInformationIdentifier.Status status, String message) { return repository.findLatestBySubjectAndStatus(subject.getUserId(), subject.getSchoolId(), - subject.getClassId(), status).orElseThrow(() -> - new BusinessException(ErrorCode.VALIDATION_ERROR, message)); + subject.getClassId(), status).orElse(null); } private BusinessException keyError(InstitutionKeySubject subject, String message) { diff --git a/src/main/java/com/yau/digitalrmb/institutionidentity/interfaces/dto/CurrencyRuleRequest.java b/src/main/java/com/yau/digitalrmb/institutionidentity/interfaces/dto/CurrencyRuleRequest.java deleted file mode 100644 index 33c621e..0000000 --- a/src/main/java/com/yau/digitalrmb/institutionidentity/interfaces/dto/CurrencyRuleRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.yau.digitalrmb.institutionidentity.interfaces.dto; - -import lombok.Getter; -import lombok.Setter; - -import javax.validation.constraints.NotBlank; - -@Getter -@Setter -public class CurrencyRuleRequest { - @NotBlank(message = "币串前缀不能为空") - private String prefix; - - @NotBlank(message = "币串ID规则不能为空") - private String idRule; - - @NotBlank(message = "币串初始状态不能为空") - private String currencyStatus; -} diff --git a/src/main/java/com/yau/digitalrmb/institutionidentity/interfaces/rest/StandardCurrencyController.java b/src/main/java/com/yau/digitalrmb/institutionidentity/interfaces/rest/StandardCurrencyController.java index b7737f4..c04085f 100644 --- a/src/main/java/com/yau/digitalrmb/institutionidentity/interfaces/rest/StandardCurrencyController.java +++ b/src/main/java/com/yau/digitalrmb/institutionidentity/interfaces/rest/StandardCurrencyController.java @@ -1,12 +1,13 @@ package com.yau.digitalrmb.institutionidentity.interfaces.rest; +import com.yau.digitalrmb.institutionidentity.application.CurrencyIdRuleResult; import com.yau.digitalrmb.institutionidentity.application.DenominationDecompositionResult; import com.yau.digitalrmb.institutionidentity.application.InstitutionKeySubject; import com.yau.digitalrmb.institutionidentity.application.StandardCurrencyBatchResult; import com.yau.digitalrmb.institutionidentity.application.StandardCurrencyListItemResult; import com.yau.digitalrmb.institutionidentity.application.StandardCurrencyOperationResult; +import com.yau.digitalrmb.institutionidentity.application.StandardCurrencyRuleResult; import com.yau.digitalrmb.institutionidentity.application.StandardCurrencyService; -import com.yau.digitalrmb.institutionidentity.interfaces.dto.CurrencyRuleRequest; import com.yau.digitalrmb.shared.api.ApiResponse; import com.yau.digitalrmb.shared.web.TraceIdFilter; import com.yau.digitalrmb.security.context.AuthContextHolder; @@ -17,12 +18,10 @@ import org.slf4j.MDC; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; 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; import java.util.List; @Validated @@ -43,14 +42,22 @@ public class StandardCurrencyController { result.getTotalCount(), result.getBreakdown()), traceId()); } - @PostMapping("/steps/confirm-rule") - @Operation(summary = "确认币串生成规则", description = "校验DC前缀、币串ID规则和待生效初始状态。") - public ApiResponse confirmRule(@Valid @RequestBody CurrencyRuleRequest request) { + @PostMapping("/steps/confirm-id-rule") + @Operation(summary = "确认币串ID生成规则", description = "无需请求体。后端自动设置DC前缀和批次号+枚序号+随机校验码ID规则,返回ID规则明细表(批次号、枚序号、随机校验码、完整币串ID)。") + public ApiResponse confirmIdRule() { JwtUser user = AuthContextHolder.get(); - StandardCurrencyBatchResult result = service.confirmRule(request.getPrefix(), request.getIdRule(), - request.getCurrencyStatus(), InstitutionKeySubject.from(user), user.getUsername()); - return ApiResponse.success(new StandardCurrencyOperationResult( - result.getStatus(), result.getTotalCount()), traceId()); + CurrencyIdRuleResult result = service.confirmIdRule( + InstitutionKeySubject.from(user), user.getUsername()); + return ApiResponse.success(result, traceId()); + } + + @PostMapping("/steps/confirm-currency-rule") + @Operation(summary = "确认标准面额币串规则", description = "无需请求体。返回标准面额币串规则明细表(前缀、币串ID、标准面额、机构标识、银行签名段、央行签名段、币串状态),数据从步骤七步骤八动态获取。") + public ApiResponse confirmCurrencyRule() { + JwtUser user = AuthContextHolder.get(); + StandardCurrencyRuleResult result = service.confirmCurrencyRule( + InstitutionKeySubject.from(user), user.getUsername()); + return ApiResponse.success(result, traceId()); } @PostMapping("/steps/generate") diff --git a/src/main/java/com/yau/digitalrmb/progress/application/UserStepProgressNewService.java b/src/main/java/com/yau/digitalrmb/progress/application/UserStepProgressNewService.java index e1f3856..f82503b 100644 --- a/src/main/java/com/yau/digitalrmb/progress/application/UserStepProgressNewService.java +++ b/src/main/java/com/yau/digitalrmb/progress/application/UserStepProgressNewService.java @@ -64,6 +64,7 @@ public class UserStepProgressNewService { .eq(UserStepProgressNewEntity::getUserId, userId) .eq(UserStepProgressNewEntity::getModuleCode, moduleCode) .eq(UserStepProgressNewEntity::getStepCode, stepCode) + .eq(UserStepProgressNewEntity::getDeleted,0) .last("LIMIT 1")); } diff --git a/src/main/java/com/yau/digitalrmb/walletopening/application/WalletOpeningService.java b/src/main/java/com/yau/digitalrmb/walletopening/application/WalletOpeningService.java index 561d9bc..6971efd 100644 --- a/src/main/java/com/yau/digitalrmb/walletopening/application/WalletOpeningService.java +++ b/src/main/java/com/yau/digitalrmb/walletopening/application/WalletOpeningService.java @@ -4,6 +4,7 @@ import com.yau.digitalrmb.institutionidentity.application.InstitutionKeySubject; import com.yau.digitalrmb.institutionidentity.infrastructure.InstitutionIdentifierApplicationEntity; import com.yau.digitalrmb.institutionidentity.infrastructure.InstitutionIdentifierApplicationMapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.yau.digitalrmb.security.context.JwtUser; import com.yau.digitalrmb.shared.api.ErrorCode; import com.yau.digitalrmb.shared.exception.BusinessException; import com.yau.digitalrmb.walletopening.domain.BankReceivedApplication; @@ -29,26 +30,45 @@ public class WalletOpeningService { @Resource private InstitutionIdentifierApplicationMapper institutionIdentifierMapper; - @Transactional - public UserWalletPageResult getPage(InstitutionKeySubject subject) { - WalletApplication app = findOrCreate(subject); - refreshCurrentUserInfo(subject, app); + @Transactional(readOnly = true) + public UserWalletPageResult getPage(InstitutionKeySubject subject, JwtUser jwtUser) { + WalletApplication app = walletRepository.findLatest(subject.getUserId(), subject.getSchoolId(), subject.getClassId()) + .orElseGet(() -> { + // 未创建记录时,返回一个只包含JWT用户信息的临时对象,不保存到数据库 + WalletApplication temp = WalletApplication.create( + subject.getUserId(), subject.getSchoolId(), subject.getClassId(), + jwtUser.getUserName(), jwtUser.getPhone()); + return temp; + }); return new UserWalletPageResult(app); } @Transactional - public FaceRecognitionResult updateFaceRecognition(InstitutionKeySubject subject, int status) { - WalletApplication app = findRequired(subject); - refreshCurrentUserInfo(subject, app); + public FaceRecognitionResult updateFaceRecognition(InstitutionKeySubject subject, JwtUser jwtUser, int status) { + WalletApplication app = walletRepository.findLatest(subject.getUserId(), subject.getSchoolId(), subject.getClassId()) + .orElseGet(() -> { + // 首次人脸识别时创建记录 + WalletApplication newApp = WalletApplication.create( + subject.getUserId(), subject.getSchoolId(), subject.getClassId(), + jwtUser.getUserName(), jwtUser.getPhone()); + return walletRepository.save(newApp); + }); app.updateFaceRecognition(status); walletRepository.update(app); return new FaceRecognitionResult(status); } @Transactional - public WalletApplicationMessageResult outputApplication(InstitutionKeySubject subject, WalletApplicationRequest request) { - WalletApplication app = findRequired(subject); - refreshCurrentUserInfo(subject, app); + public WalletApplicationMessageResult outputApplication(InstitutionKeySubject subject, JwtUser jwtUser, WalletApplicationRequest request) { + WalletApplication app = walletRepository.findLatest(subject.getUserId(), subject.getSchoolId(), subject.getClassId()) + .orElseGet(() -> { + // 首次输出申请报文时创建记录 + WalletApplication newApp = WalletApplication.create( + subject.getUserId(), subject.getSchoolId(), subject.getClassId(), + jwtUser.getUserName(), jwtUser.getPhone()); + return walletRepository.save(newApp); + }); + if (app.getStatus() != null && app.getStatus().ordinal() >= WalletApplication.Status.OUTPUT.ordinal()) { throw new BusinessException(ErrorCode.VALIDATION_ERROR, "申请报文已输出,请勿重复操作"); } @@ -58,8 +78,11 @@ public class WalletOpeningService { if (request.getWalletType() == null || request.getWalletType().trim().isEmpty()) { throw new BusinessException(ErrorCode.VALIDATION_ERROR, "请选择数字钱包类型"); } + + // 输出申请报文时才存储身份证号、银行卡号等敏感信息 app.fillForm(request.getSelectedBank(), request.getWalletType(), request.getInputPhone(), - request.getInputIdNumber(), request.getInputBankCardNumber(), request.getSignaturePhotoPath()); + request.getInputIdNumber(), request.getInputBankCardNumber(), request.getSignaturePhotoPath(), + request.getIdNumber(), request.getAccountBank(), request.getBankCardNumber(), request.getAccountBalance()); String applyTime = LocalDateTime.now().format(TIMESTAMP_FORMAT); String applicationId = "APP_" + applyTime; @@ -72,8 +95,9 @@ public class WalletOpeningService { } @Transactional - public WalletSendResult sendApplication(InstitutionKeySubject subject) { - WalletApplication app = findRequired(subject); + public WalletSendResult sendApplication(InstitutionKeySubject subject, JwtUser jwtUser) { + WalletApplication app = walletRepository.findLatest(subject.getUserId(), subject.getSchoolId(), subject.getClassId()) + .orElseThrow(() -> new BusinessException(ErrorCode.RESOURCE_NOT_FOUND, "钱包申请不存在,请先输出申请报文")); if (app.getStatus() == null || app.getStatus().ordinal() < WalletApplication.Status.OUTPUT.ordinal()) { throw new BusinessException(ErrorCode.VALIDATION_ERROR, "请先输出申请报文"); } @@ -101,31 +125,6 @@ public class WalletOpeningService { return new WalletSendResult("已提交"); } - private WalletApplication findOrCreate(InstitutionKeySubject subject) { - return walletRepository.findLatest(subject.getUserId(), subject.getSchoolId(), subject.getClassId()) - .orElseGet(() -> walletRepository.save( - WalletApplication.newDraft(subject.getUserId(), subject.getSchoolId(), subject.getClassId(), - subject.getUserName(), subject.getPhone()))); - } - - private WalletApplication findRequired(InstitutionKeySubject subject) { - return walletRepository.findLatest(subject.getUserId(), subject.getSchoolId(), subject.getClassId()) - .orElseThrow(() -> new BusinessException(ErrorCode.RESOURCE_NOT_FOUND, "钱包申请不存在,请先初始化页面")); - } - - private void refreshCurrentUserInfo(InstitutionKeySubject subject, WalletApplication app) { - String beforeUserName = app.getUserName(); - String beforePhone = app.getPhone(); - app.refreshTokenUserInfo(subject.getUserName(), subject.getPhone()); - if (!equals(beforeUserName, app.getUserName()) || !equals(beforePhone, app.getPhone())) { - walletRepository.update(app); - } - } - - private boolean equals(String left, String right) { - return left == null ? right == null : left.equals(right); - } - private String resolveOrgCode(InstitutionKeySubject subject) { InstitutionIdentifierApplicationEntity entity = institutionIdentifierMapper.selectOne( new LambdaQueryWrapper() diff --git a/src/main/java/com/yau/digitalrmb/walletopening/interfaces/rest/WalletOpeningController.java b/src/main/java/com/yau/digitalrmb/walletopening/interfaces/rest/WalletOpeningController.java index 5af5c51..a17046d 100644 --- a/src/main/java/com/yau/digitalrmb/walletopening/interfaces/rest/WalletOpeningController.java +++ b/src/main/java/com/yau/digitalrmb/walletopening/interfaces/rest/WalletOpeningController.java @@ -33,30 +33,31 @@ public class WalletOpeningController { @GetMapping("/page") @Operation(summary = "查询用户端钱包开通申请页面数据", - description = "返回页面完整数据;首次访问自动创建草稿申请,预填用户信息。尚未完成的阶段字段返回null。") + description = "返回页面完整数据,用户名和手机号从JWT token获取;尚未产生的字段返回null。不会自动创建数据库记录。") public ApiResponse page() { + JwtUser jwtUser = AuthContextHolder.get(); return ApiResponse.success(walletOpeningService.getPage( - InstitutionKeySubject.from(AuthContextHolder.get())), traceId()); + InstitutionKeySubject.from(jwtUser), jwtUser), traceId()); } @PostMapping("/face-recognition") @Operation(summary = "更新人脸识别状态", - description = "前端调用接口修改人脸识别状态。参数1=未成功,2=已成功。") + description = "前端调用接口修改人脸识别状态。参数1=未成功,2=已成功。首次调用时自动创建申请记录。") public ApiResponse faceRecognition( @Valid @RequestBody FaceRecognitionRequest request) { JwtUser jwtUser = AuthContextHolder.get(); return ApiResponse.success(walletOpeningService.updateFaceRecognition( - InstitutionKeySubject.from(jwtUser), request.getStatus()), traceId()); + InstitutionKeySubject.from(jwtUser), jwtUser, request.getStatus()), traceId()); } @PostMapping("/output") @Operation(summary = "输出申请报文", - description = "保存用户填写的表单数据,拼接原始报文并生成JSON申请报文。") + description = "保存用户填写的表单数据(包括身份证号、银行卡号等敏感信息),拼接原始报文并生成JSON申请报文。") public ApiResponse output( @Valid @RequestBody WalletApplicationRequest request) { JwtUser jwtUser = AuthContextHolder.get(); return ApiResponse.success(walletOpeningService.outputApplication( - InstitutionKeySubject.from(jwtUser), request), traceId()); + InstitutionKeySubject.from(jwtUser), jwtUser, request), traceId()); } @PostMapping("/send") @@ -65,7 +66,7 @@ public class WalletOpeningController { public ApiResponse send() { JwtUser jwtUser = AuthContextHolder.get(); return ApiResponse.success(walletOpeningService.sendApplication( - InstitutionKeySubject.from(jwtUser)), traceId()); + InstitutionKeySubject.from(jwtUser), jwtUser), traceId()); } private String traceId() { diff --git a/src/main/java/com/yau/digitalrmb/walletopening/interfaces/rest/dto/WalletApplicationRequest.java b/src/main/java/com/yau/digitalrmb/walletopening/interfaces/rest/dto/WalletApplicationRequest.java index 1e51b6f..d6e43a6 100644 --- a/src/main/java/com/yau/digitalrmb/walletopening/interfaces/rest/dto/WalletApplicationRequest.java +++ b/src/main/java/com/yau/digitalrmb/walletopening/interfaces/rest/dto/WalletApplicationRequest.java @@ -5,6 +5,7 @@ import lombok.Getter; import lombok.Setter; import javax.validation.constraints.NotBlank; +import java.math.BigDecimal; @Getter @Setter @@ -23,4 +24,12 @@ public class WalletApplicationRequest { private String inputBankCardNumber; @Schema(description = "面签照片路径", example = "/2026/8/11/5cae82501de84bfba3693477ac55140c.pdf") private String signaturePhotoPath; + @Schema(description = "身份证号(确认)", example = "110101199001011234") + private String idNumber; + @Schema(description = "开户银行", example = "中国银行北京分行") + private String accountBank; + @Schema(description = "银行卡号(确认)", example = "6216610100001234567") + private String bankCardNumber; + @Schema(description = "账户余额", example = "500000.00") + private BigDecimal accountBalance; }