package com.yau.digitalrmb.walletopening.application; 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; import com.yau.digitalrmb.walletopening.domain.BankReceivedApplicationRepository; import com.yau.digitalrmb.walletopening.domain.WalletApplication; import com.yau.digitalrmb.walletopening.domain.WalletApplicationRepository; import com.yau.digitalrmb.walletopening.interfaces.rest.dto.WalletApplicationRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @Service public class WalletOpeningService { private static final DateTimeFormatter TIMESTAMP_FORMAT = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); @Resource private WalletApplicationRepository walletRepository; @Resource private BankReceivedApplicationRepository bankReceivedRepository; @Resource private InstitutionIdentifierApplicationMapper institutionIdentifierMapper; @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, 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, 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, "申请报文已输出,请勿重复操作"); } if (app.getFaceRecognitionStatus() == null || app.getFaceRecognitionStatus() != 2) { throw new BusinessException(ErrorCode.VALIDATION_ERROR, "请先完成人脸识别"); } 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.getIdNumber(), request.getAccountBank(), request.getBankCardNumber(), request.getAccountBalance()); String applyTime = LocalDateTime.now().format(TIMESTAMP_FORMAT); String applicationId = "APP_" + applyTime; String concatenatedMessage = buildConcatenatedMessage(app, applyTime); String applicationMessage = buildApplicationMessage(app, applicationId, applyTime); app.outputApplication(applicationId, concatenatedMessage, applicationMessage, applyTime); walletRepository.update(app); return new WalletApplicationMessageResult(app); } @Transactional 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, "请先输出申请报文"); } if (app.getStatus() == WalletApplication.Status.SUBMITTED) { throw new BusinessException(ErrorCode.VALIDATION_ERROR, "申请已发送,请勿重复操作"); } app.submit(); walletRepository.update(app); String receiveTime = LocalDateTime.now().format(TIMESTAMP_FORMAT); String receiveId = "BK_RECEIVE_" + receiveTime; String orgCode = resolveOrgCode(subject); String effectiveIdNumber = app.getInputIdNumber() != null ? app.getInputIdNumber() : app.getIdNumber(); String effectivePhone = app.getInputPhone() != null ? app.getInputPhone() : app.getPhone(); String effectiveBankCardNumber = app.getInputBankCardNumber() != null ? app.getInputBankCardNumber() : app.getBankCardNumber(); BankReceivedApplication received = BankReceivedApplication.receive( subject.getUserId(), subject.getSchoolId(), subject.getClassId(), receiveId, app.getApplicationId(), orgCode, receiveTime, app.getUserName(), effectiveIdNumber, effectivePhone, effectiveBankCardNumber, app.getWalletType(), app.getApplyTime()); bankReceivedRepository.save(received); return new WalletSendResult("已提交"); } private String resolveOrgCode(InstitutionKeySubject subject) { InstitutionIdentifierApplicationEntity entity = institutionIdentifierMapper.selectOne( new LambdaQueryWrapper() .eq(InstitutionIdentifierApplicationEntity::getUserId, subject.getUserId()) .eq(InstitutionIdentifierApplicationEntity::getSchoolId, subject.getSchoolId()) .eq(InstitutionIdentifierApplicationEntity::getClassId, subject.getClassId()) .eq(InstitutionIdentifierApplicationEntity::getDeleted, false) .isNotNull(InstitutionIdentifierApplicationEntity::getInstitutionIdentifier) .orderByDesc(InstitutionIdentifierApplicationEntity::getCreatedAt) .last("LIMIT 1")); return entity == null ? null : entity.getBankCode(); } private String buildConcatenatedMessage(WalletApplication app, String applyTime) { String idNumber = app.getInputIdNumber() != null ? app.getInputIdNumber() : app.getIdNumber(); String phone = app.getInputPhone() != null ? app.getInputPhone() : app.getPhone(); String bankCardNumber = app.getInputBankCardNumber() != null ? app.getInputBankCardNumber() : app.getBankCardNumber(); return "APPLY|" + app.getUserName() + "|" + idNumber + "|" + phone + "|" + bankCardNumber + "|" + app.getWalletType() + "|" + applyTime; } private String buildApplicationMessage(WalletApplication app, String applicationId, String applyTime) { String idNumber = app.getInputIdNumber() != null ? app.getInputIdNumber() : app.getIdNumber(); String phone = app.getInputPhone() != null ? app.getInputPhone() : app.getPhone(); String bankCardNumber = app.getInputBankCardNumber() != null ? app.getInputBankCardNumber() : app.getBankCardNumber(); return "{\"applicationId\":\"" + applicationId + "\"," + "\"userName\":\"" + app.getUserName() + "\"," + "\"idNumber\":\"" + idNumber + "\"," + "\"phone\":\"" + phone + "\"," + "\"bankCardNumber\":\"" + bankCardNumber + "\"," + "\"walletType\":\"" + app.getWalletType() + "\"," + "\"applyTime\":\"" + applyTime + "\"," + "\"status\":\"已提交\"}"; } }