feat:文件上传的功能开发

master
jiazheng.zhao 2 weeks ago
parent c92d26bdce
commit 9a90eb1eee

@ -19,7 +19,9 @@ public class QuotaRequestSourceDataResult {
this.transactionIdentifier = value.getTransactionIdentifier(); this.transactionIdentifier = value.getTransactionIdentifier();
} }
public BigDecimal getAmount() { return amount; } public BigDecimal getAmount() { return amount; }
public String getInstitutionIdentifier() { return institutionIdentifier; } public String getInstitutionIdentifier() { return institutionIdentifier; }
public String getTransactionIdentifier() { return transactionIdentifier; } public String getTransactionIdentifier() { return transactionIdentifier; }
} }

@ -96,21 +96,11 @@ public class StandardCurrencyService {
} }
@Transactional @Transactional
public StandardCurrencyBatchResult confirmRule(String prefix, String idRule, String currencyStatus, public CurrencyIdRuleResult confirmIdRule(InstitutionKeySubject subject, String operator) {
InstitutionKeySubject subject, String operator) {
StandardCurrencyBatchEntity batch = requireLatest(subject); StandardCurrencyBatchEntity batch = requireLatest(subject);
if (batch.getDenominationSummary() == null || batch.getTotalAmount() == null) { if (batch.getDenominationSummary() == null || batch.getTotalAmount() == null) {
throw new BusinessException(ErrorCode.VALIDATION_ERROR, "请先执行面额拆解"); 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<StandardCurrencyBatchEntity>() int updated = batchMapper.update(null, new LambdaUpdateWrapper<StandardCurrencyBatchEntity>()
.eq(StandardCurrencyBatchEntity::getId, batch.getId()) .eq(StandardCurrencyBatchEntity::getId, batch.getId())
.eq(StandardCurrencyBatchEntity::getStatus, batch.getStatus()) .eq(StandardCurrencyBatchEntity::getStatus, batch.getStatus())
@ -122,7 +112,25 @@ public class StandardCurrencyService {
.set(StandardCurrencyBatchEntity::getUpdatedAt, LocalDateTime.now()) .set(StandardCurrencyBatchEntity::getUpdatedAt, LocalDateTime.now())
.set(StandardCurrencyBatchEntity::getUpdatedBy, operator)); .set(StandardCurrencyBatchEntity::getUpdatedBy, operator));
if (updated != 1) throw stateChanged(); 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<DenominationBreakdownResult> 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 @Transactional

@ -143,21 +143,64 @@ public class TransactionInformationIdentifierService {
return new TransactionIdentifierAssemblyResult(value); return new TransactionIdentifierAssemblyResult(value);
} }
@Transactional // @Transactional
public QuotaRequestSourceDataResult quotaRequestSourceData(InstitutionKeySubject subject) { // public QuotaRequestSourceDataResult quotaRequestSourceData(InstitutionKeySubject subject) {
TransactionInformationIdentifier value = repository.findLatestBySubject(subject.getUserId(), // TransactionInformationIdentifier value = repository.findLatestBySubject(subject.getUserId(),
subject.getSchoolId(), subject.getClassId()).orElseThrow(() -> // subject.getSchoolId(), subject.getClassId()).orElseThrow(() ->
new BusinessException(ErrorCode.VALIDATION_ERROR, // 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() if (value.getStatus().ordinal() < TransactionInformationIdentifier.Status.ASSEMBLED.ordinal()
|| value.getTransactionIdentifier() == null || value.getTransactionIdentifier() == null
|| !value.getTransactionIdentifier().matches("TXN_[0-9A-F]{64}")) { || !value.getTransactionIdentifier().matches("TXN_[0-9A-F]{64}")) {
throw new BusinessException(ErrorCode.VALIDATION_ERROR, return null;
"步骤四尚未生成交易信息标识,请先完成步骤四");
}
return new QuotaRequestSourceDataResult(value);
} }
// 正常返回
return new QuotaRequestSourceDataResult(value);
}
@Transactional @Transactional
public QuotaRequestDigestResult digestQuotaRequest(String originalText, public QuotaRequestDigestResult digestQuotaRequest(String originalText,
InstitutionKeySubject subject, InstitutionKeySubject subject,
@ -315,17 +358,31 @@ public class TransactionInformationIdentifierService {
return new QuotaVerificationResult(value); return new QuotaVerificationResult(value);
} }
@Transactional(readOnly = true) // @Transactional(readOnly = true)
public QuotaRequestMessageResult quotaRequestMessageDetail(InstitutionKeySubject subject) { // public QuotaRequestMessageResult quotaRequestMessageDetail(InstitutionKeySubject subject) {
return new QuotaRequestMessageResult(requireLatest(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: nullHTTP 200
} }
return new QuotaRequestMessageResult(value);
}
@Transactional(readOnly = true) @Transactional(readOnly = true)
public TransactionInformationIdentifierResult detail(InstitutionKeySubject subject) { public TransactionInformationIdentifierResult detail(InstitutionKeySubject subject) {
TransactionInformationIdentifier value = repository.findLatestBySubject(subject.getUserId(), TransactionInformationIdentifier value = repository.findLatestBySubject(
subject.getSchoolId(), subject.getClassId()).orElseThrow(() -> subject.getUserId(), subject.getSchoolId(), subject.getClassId())
new BusinessException(ErrorCode.RESOURCE_NOT_FOUND, "当前没有交易信息标识记录")); .orElse(null); // 查不到就返回 null
return new TransactionInformationIdentifierResult(value); // 注意:这里 value 可能为 null
return value != null ? new TransactionInformationIdentifierResult(value) : null;
} }
private CurrencyGenerationVerificationEntity requireCompletedVerification(InstitutionKeySubject subject) { private CurrencyGenerationVerificationEntity requireCompletedVerification(InstitutionKeySubject subject) {
@ -378,18 +435,21 @@ public class TransactionInformationIdentifierService {
return value; return value;
} }
// 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) { private TransactionInformationIdentifier requireLatest(InstitutionKeySubject subject) {
return repository.findLatestBySubject(subject.getUserId(), subject.getSchoolId(), subject.getClassId()) return repository.findLatestBySubject(subject.getUserId(), subject.getSchoolId(), subject.getClassId())
.orElseThrow(() -> new BusinessException(ErrorCode.RESOURCE_NOT_FOUND, .orElse(null);
"当前没有额度请求记录"));
} }
private TransactionInformationIdentifier requireStatus(InstitutionKeySubject subject, private TransactionInformationIdentifier requireStatus(InstitutionKeySubject subject,
TransactionInformationIdentifier.Status status, TransactionInformationIdentifier.Status status,
String message) { String message) {
return repository.findLatestBySubjectAndStatus(subject.getUserId(), subject.getSchoolId(), return repository.findLatestBySubjectAndStatus(subject.getUserId(), subject.getSchoolId(),
subject.getClassId(), status).orElseThrow(() -> subject.getClassId(), status).orElse(null);
new BusinessException(ErrorCode.VALIDATION_ERROR, message));
} }
private BusinessException keyError(InstitutionKeySubject subject, String message) { private BusinessException keyError(InstitutionKeySubject subject, String message) {

@ -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;
}

@ -1,12 +1,13 @@
package com.yau.digitalrmb.institutionidentity.interfaces.rest; 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.DenominationDecompositionResult;
import com.yau.digitalrmb.institutionidentity.application.InstitutionKeySubject; import com.yau.digitalrmb.institutionidentity.application.InstitutionKeySubject;
import com.yau.digitalrmb.institutionidentity.application.StandardCurrencyBatchResult; import com.yau.digitalrmb.institutionidentity.application.StandardCurrencyBatchResult;
import com.yau.digitalrmb.institutionidentity.application.StandardCurrencyListItemResult; import com.yau.digitalrmb.institutionidentity.application.StandardCurrencyListItemResult;
import com.yau.digitalrmb.institutionidentity.application.StandardCurrencyOperationResult; 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.application.StandardCurrencyService;
import com.yau.digitalrmb.institutionidentity.interfaces.dto.CurrencyRuleRequest;
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 com.yau.digitalrmb.security.context.AuthContextHolder; import com.yau.digitalrmb.security.context.AuthContextHolder;
@ -17,12 +18,10 @@ import org.slf4j.MDC;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
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.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 java.util.List; import java.util.List;
@Validated @Validated
@ -43,14 +42,22 @@ public class StandardCurrencyController {
result.getTotalCount(), result.getBreakdown()), traceId()); result.getTotalCount(), result.getBreakdown()), traceId());
} }
@PostMapping("/steps/confirm-rule") @PostMapping("/steps/confirm-id-rule")
@Operation(summary = "确认币串生成规则", description = "校验DC前缀、币串ID规则和待生效初始状态。") @Operation(summary = "确认币串ID生成规则", description = "无需请求体。后端自动设置DC前缀和批次号+枚序号+随机校验码ID规则返回ID规则明细表批次号、枚序号、随机校验码、完整币串ID。")
public ApiResponse<StandardCurrencyOperationResult> confirmRule(@Valid @RequestBody CurrencyRuleRequest request) { public ApiResponse<CurrencyIdRuleResult> confirmIdRule() {
JwtUser user = AuthContextHolder.get(); JwtUser user = AuthContextHolder.get();
StandardCurrencyBatchResult result = service.confirmRule(request.getPrefix(), request.getIdRule(), CurrencyIdRuleResult result = service.confirmIdRule(
request.getCurrencyStatus(), InstitutionKeySubject.from(user), user.getUsername()); InstitutionKeySubject.from(user), user.getUsername());
return ApiResponse.success(new StandardCurrencyOperationResult( return ApiResponse.success(result, traceId());
result.getStatus(), result.getTotalCount()), traceId()); }
@PostMapping("/steps/confirm-currency-rule")
@Operation(summary = "确认标准面额币串规则", description = "无需请求体。返回标准面额币串规则明细表前缀、币串ID、标准面额、机构标识、银行签名段、央行签名段、币串状态数据从步骤七步骤八动态获取。")
public ApiResponse<StandardCurrencyRuleResult> confirmCurrencyRule() {
JwtUser user = AuthContextHolder.get();
StandardCurrencyRuleResult result = service.confirmCurrencyRule(
InstitutionKeySubject.from(user), user.getUsername());
return ApiResponse.success(result, traceId());
} }
@PostMapping("/steps/generate") @PostMapping("/steps/generate")

@ -64,6 +64,7 @@ public class UserStepProgressNewService {
.eq(UserStepProgressNewEntity::getUserId, userId) .eq(UserStepProgressNewEntity::getUserId, userId)
.eq(UserStepProgressNewEntity::getModuleCode, moduleCode) .eq(UserStepProgressNewEntity::getModuleCode, moduleCode)
.eq(UserStepProgressNewEntity::getStepCode, stepCode) .eq(UserStepProgressNewEntity::getStepCode, stepCode)
.eq(UserStepProgressNewEntity::getDeleted,0)
.last("LIMIT 1")); .last("LIMIT 1"));
} }

@ -4,6 +4,7 @@ import com.yau.digitalrmb.institutionidentity.application.InstitutionKeySubject;
import com.yau.digitalrmb.institutionidentity.infrastructure.InstitutionIdentifierApplicationEntity; import com.yau.digitalrmb.institutionidentity.infrastructure.InstitutionIdentifierApplicationEntity;
import com.yau.digitalrmb.institutionidentity.infrastructure.InstitutionIdentifierApplicationMapper; import com.yau.digitalrmb.institutionidentity.infrastructure.InstitutionIdentifierApplicationMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 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.api.ErrorCode;
import com.yau.digitalrmb.shared.exception.BusinessException; import com.yau.digitalrmb.shared.exception.BusinessException;
import com.yau.digitalrmb.walletopening.domain.BankReceivedApplication; import com.yau.digitalrmb.walletopening.domain.BankReceivedApplication;
@ -29,26 +30,45 @@ public class WalletOpeningService {
@Resource @Resource
private InstitutionIdentifierApplicationMapper institutionIdentifierMapper; private InstitutionIdentifierApplicationMapper institutionIdentifierMapper;
@Transactional @Transactional(readOnly = true)
public UserWalletPageResult getPage(InstitutionKeySubject subject) { public UserWalletPageResult getPage(InstitutionKeySubject subject, JwtUser jwtUser) {
WalletApplication app = findOrCreate(subject); WalletApplication app = walletRepository.findLatest(subject.getUserId(), subject.getSchoolId(), subject.getClassId())
refreshCurrentUserInfo(subject, app); .orElseGet(() -> {
// 未创建记录时返回一个只包含JWT用户信息的临时对象不保存到数据库
WalletApplication temp = WalletApplication.create(
subject.getUserId(), subject.getSchoolId(), subject.getClassId(),
jwtUser.getUserName(), jwtUser.getPhone());
return temp;
});
return new UserWalletPageResult(app); return new UserWalletPageResult(app);
} }
@Transactional @Transactional
public FaceRecognitionResult updateFaceRecognition(InstitutionKeySubject subject, int status) { public FaceRecognitionResult updateFaceRecognition(InstitutionKeySubject subject, JwtUser jwtUser, int status) {
WalletApplication app = findRequired(subject); WalletApplication app = walletRepository.findLatest(subject.getUserId(), subject.getSchoolId(), subject.getClassId())
refreshCurrentUserInfo(subject, app); .orElseGet(() -> {
// 首次人脸识别时创建记录
WalletApplication newApp = WalletApplication.create(
subject.getUserId(), subject.getSchoolId(), subject.getClassId(),
jwtUser.getUserName(), jwtUser.getPhone());
return walletRepository.save(newApp);
});
app.updateFaceRecognition(status); app.updateFaceRecognition(status);
walletRepository.update(app); walletRepository.update(app);
return new FaceRecognitionResult(status); return new FaceRecognitionResult(status);
} }
@Transactional @Transactional
public WalletApplicationMessageResult outputApplication(InstitutionKeySubject subject, WalletApplicationRequest request) { public WalletApplicationMessageResult outputApplication(InstitutionKeySubject subject, JwtUser jwtUser, WalletApplicationRequest request) {
WalletApplication app = findRequired(subject); WalletApplication app = walletRepository.findLatest(subject.getUserId(), subject.getSchoolId(), subject.getClassId())
refreshCurrentUserInfo(subject, app); .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()) { if (app.getStatus() != null && app.getStatus().ordinal() >= WalletApplication.Status.OUTPUT.ordinal()) {
throw new BusinessException(ErrorCode.VALIDATION_ERROR, "申请报文已输出,请勿重复操作"); throw new BusinessException(ErrorCode.VALIDATION_ERROR, "申请报文已输出,请勿重复操作");
} }
@ -58,8 +78,11 @@ public class WalletOpeningService {
if (request.getWalletType() == null || request.getWalletType().trim().isEmpty()) { if (request.getWalletType() == null || request.getWalletType().trim().isEmpty()) {
throw new BusinessException(ErrorCode.VALIDATION_ERROR, "请选择数字钱包类型"); throw new BusinessException(ErrorCode.VALIDATION_ERROR, "请选择数字钱包类型");
} }
// 输出申请报文时才存储身份证号、银行卡号等敏感信息
app.fillForm(request.getSelectedBank(), request.getWalletType(), request.getInputPhone(), 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 applyTime = LocalDateTime.now().format(TIMESTAMP_FORMAT);
String applicationId = "APP_" + applyTime; String applicationId = "APP_" + applyTime;
@ -72,8 +95,9 @@ public class WalletOpeningService {
} }
@Transactional @Transactional
public WalletSendResult sendApplication(InstitutionKeySubject subject) { public WalletSendResult sendApplication(InstitutionKeySubject subject, JwtUser jwtUser) {
WalletApplication app = findRequired(subject); 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()) { if (app.getStatus() == null || app.getStatus().ordinal() < WalletApplication.Status.OUTPUT.ordinal()) {
throw new BusinessException(ErrorCode.VALIDATION_ERROR, "请先输出申请报文"); throw new BusinessException(ErrorCode.VALIDATION_ERROR, "请先输出申请报文");
} }
@ -101,31 +125,6 @@ public class WalletOpeningService {
return new WalletSendResult("已提交"); 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) { private String resolveOrgCode(InstitutionKeySubject subject) {
InstitutionIdentifierApplicationEntity entity = institutionIdentifierMapper.selectOne( InstitutionIdentifierApplicationEntity entity = institutionIdentifierMapper.selectOne(
new LambdaQueryWrapper<InstitutionIdentifierApplicationEntity>() new LambdaQueryWrapper<InstitutionIdentifierApplicationEntity>()

@ -33,30 +33,31 @@ public class WalletOpeningController {
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "查询用户端钱包开通申请页面数据", @Operation(summary = "查询用户端钱包开通申请页面数据",
description = "返回页面完整数据首次访问自动创建草稿申请预填用户信息。尚未完成的阶段字段返回null。") description = "返回页面完整数据用户名和手机号从JWT token获取尚未产生的字段返回null。不会自动创建数据库记录。")
public ApiResponse<UserWalletPageResult> page() { public ApiResponse<UserWalletPageResult> page() {
JwtUser jwtUser = AuthContextHolder.get();
return ApiResponse.success(walletOpeningService.getPage( return ApiResponse.success(walletOpeningService.getPage(
InstitutionKeySubject.from(AuthContextHolder.get())), traceId()); InstitutionKeySubject.from(jwtUser), jwtUser), traceId());
} }
@PostMapping("/face-recognition") @PostMapping("/face-recognition")
@Operation(summary = "更新人脸识别状态", @Operation(summary = "更新人脸识别状态",
description = "前端调用接口修改人脸识别状态。参数1=未成功2=已成功。") description = "前端调用接口修改人脸识别状态。参数1=未成功2=已成功。首次调用时自动创建申请记录。")
public ApiResponse<FaceRecognitionResult> faceRecognition( public ApiResponse<FaceRecognitionResult> faceRecognition(
@Valid @RequestBody FaceRecognitionRequest request) { @Valid @RequestBody FaceRecognitionRequest request) {
JwtUser jwtUser = AuthContextHolder.get(); JwtUser jwtUser = AuthContextHolder.get();
return ApiResponse.success(walletOpeningService.updateFaceRecognition( return ApiResponse.success(walletOpeningService.updateFaceRecognition(
InstitutionKeySubject.from(jwtUser), request.getStatus()), traceId()); InstitutionKeySubject.from(jwtUser), jwtUser, request.getStatus()), traceId());
} }
@PostMapping("/output") @PostMapping("/output")
@Operation(summary = "输出申请报文", @Operation(summary = "输出申请报文",
description = "保存用户填写的表单数据拼接原始报文并生成JSON申请报文。") description = "保存用户填写的表单数据(包括身份证号、银行卡号等敏感信息)拼接原始报文并生成JSON申请报文。")
public ApiResponse<WalletApplicationMessageResult> output( public ApiResponse<WalletApplicationMessageResult> output(
@Valid @RequestBody WalletApplicationRequest request) { @Valid @RequestBody WalletApplicationRequest request) {
JwtUser jwtUser = AuthContextHolder.get(); JwtUser jwtUser = AuthContextHolder.get();
return ApiResponse.success(walletOpeningService.outputApplication( return ApiResponse.success(walletOpeningService.outputApplication(
InstitutionKeySubject.from(jwtUser), request), traceId()); InstitutionKeySubject.from(jwtUser), jwtUser, request), traceId());
} }
@PostMapping("/send") @PostMapping("/send")
@ -65,7 +66,7 @@ public class WalletOpeningController {
public ApiResponse<WalletSendResult> send() { public ApiResponse<WalletSendResult> send() {
JwtUser jwtUser = AuthContextHolder.get(); JwtUser jwtUser = AuthContextHolder.get();
return ApiResponse.success(walletOpeningService.sendApplication( return ApiResponse.success(walletOpeningService.sendApplication(
InstitutionKeySubject.from(jwtUser)), traceId()); InstitutionKeySubject.from(jwtUser), jwtUser), traceId());
} }
private String traceId() { private String traceId() {

@ -5,6 +5,7 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import java.math.BigDecimal;
@Getter @Getter
@Setter @Setter
@ -23,4 +24,12 @@ public class WalletApplicationRequest {
private String inputBankCardNumber; private String inputBankCardNumber;
@Schema(description = "面签照片路径", example = "/2026/8/11/5cae82501de84bfba3693477ac55140c.pdf") @Schema(description = "面签照片路径", example = "/2026/8/11/5cae82501de84bfba3693477ac55140c.pdf")
private String signaturePhotoPath; 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;
} }

Loading…
Cancel
Save