You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
digital-rmb-backend/src/main/java/com/yau/digitalrmb/institutionidentity/application/ControlSystemSignatureServi...

171 lines
10 KiB
Java

package com.yau.digitalrmb.institutionidentity.application;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yau.digitalrmb.institutionidentity.domain.InstitutionIdentityCryptography;
import com.yau.digitalrmb.institutionidentity.infrastructure.ControlSystemSignatureEntity;
import com.yau.digitalrmb.institutionidentity.infrastructure.ControlSystemSignatureMapper;
import com.yau.digitalrmb.institutionidentity.infrastructure.TransactionInformationIdentifierEntity;
import com.yau.digitalrmb.institutionidentity.infrastructure.TransactionInformationIdentifierMapper;
import com.yau.digitalrmb.shared.api.ErrorCode;
import com.yau.digitalrmb.shared.exception.BusinessException;
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 ControlSystemSignatureService {
private static final DateTimeFormatter DATE = DateTimeFormatter.ofPattern("yyyyMMdd");
@Resource private TransactionInformationIdentifierMapper transactionMapper;
@Resource private ControlSystemSignatureMapper mapper;
@Resource private InstitutionIdentityCryptography cryptography;
@Resource private InstitutionKeyService keyService;
@Resource private InstitutionTrainingScoreService scoreService;
@Resource private InstitutionTrainingErrorRecorder errorRecorder;
@Transactional
public ControlSystemSignatureResult prepare(InstitutionKeySubject subject, String operator) {
TransactionInformationIdentifierEntity transaction = requireQuotaVerified(subject);
ControlSystemSignatureEntity current = latest(subject);
if (current != null) {
if (current.getTransactionIdentifierId().equals(transaction.getId())) {
return new ControlSystemSignatureResult(current);
}
throw new BusinessException(ErrorCode.VALIDATION_ERROR,
"当前实训已有步骤七控制系统签名记录,如需重新开始请先调用重新实训接口");
}
ControlSystemSignatureEntity value = new ControlSystemSignatureEntity();
value.setTransactionIdentifierId(transaction.getId());
value.setControlId("CTRL_" + LocalDateTime.now().format(DATE) + "_" + String.format("%03d", transaction.getId() % 1000));
value.setAmount(transaction.getAmount());
value.setInstitutionIdentifier(transaction.getInstitutionIdentifier());
value.setTransactionIdentifier(transaction.getTransactionIdentifier());
value.setOriginalText(value.getControlId() + "|" + transaction.getAmount().setScale(2).toPlainString() + "|"
+ transaction.getInstitutionIdentifier() + "|" + transaction.getTransactionIdentifier());
value.setStatus("PREPARED");
value.setUserId(subject.getUserId());
value.setSchoolId(subject.getSchoolId());
value.setClassId(subject.getClassId());
value.setCreatedAt(LocalDateTime.now());
value.setUpdatedAt(value.getCreatedAt());
value.setCreatedBy(operator);
value.setUpdatedBy(operator);
value.setDeleted(false);
mapper.insert(value);
return new ControlSystemSignatureResult(value);
}
@Transactional
public ControlSystemSignatureResult digest(InstitutionKeySubject subject, String operator) {
ControlSystemSignatureEntity value = requireStatus(subject, "PREPARED", "请先生成控制系统签名基础数据");
update(value, "PREPARED", "DIGESTED", operator,
new LambdaUpdateWrapper<ControlSystemSignatureEntity>()
.set(ControlSystemSignatureEntity::getDigest, cryptography.sm3(value.getOriginalText())));
return new ControlSystemSignatureResult(requireLatest(subject));
}
@Transactional
public ControlSystemSignatureResult sign(String privateKey, InstitutionKeySubject subject, String operator) {
ControlSystemSignatureEntity value = requireStatus(subject, "DIGESTED", "请先计算控制系统签名摘要");
String signature = keyService.signCentralBank(subject, privateKey, value.getDigest());
if (signature == null) {
int errorSequence = errorRecorder.recordScoreError(subject.getUserId());
throw new BusinessException(ErrorCode.VALIDATION_ERROR,
"中央银行第一私钥不正确,本次实训第" + errorSequence + "次错误");
}
update(value, "DIGESTED", "SIGNED", operator,
new LambdaUpdateWrapper<ControlSystemSignatureEntity>()
.set(ControlSystemSignatureEntity::getSigningKeyId, InstitutionKeyService.CENTRAL_FIRST_KEY)
.set(ControlSystemSignatureEntity::getSignature, signature)
.set(ControlSystemSignatureEntity::getControlSignature, signature));
return new ControlSystemSignatureResult(requireLatest(subject));
}
@Transactional
public ControlSystemSignatureResult packageResponse(InstitutionKeySubject subject, String operator) {
ControlSystemSignatureEntity value = requireStatus(subject, "SIGNED", "请先完成中央银行控制系统签名");
String message = "{\"ctrlId\":\"" + value.getControlId() + "\",\"amount\":\""
+ value.getAmount().setScale(2).toPlainString() + "\",\"orgId\":\""
+ value.getInstitutionIdentifier() + "\",\"txnId\":\""
+ value.getTransactionIdentifier() + "\",\"cbCtrlSignature\":\""
+ value.getControlSignature() + "\"}";
update(value, "SIGNED", "PACKAGED", operator,
new LambdaUpdateWrapper<ControlSystemSignatureEntity>()
.set(ControlSystemSignatureEntity::getResponseMessage, message));
return new ControlSystemSignatureResult(requireLatest(subject));
}
@Transactional
public ControlSystemSignatureResult send(InstitutionKeySubject subject, String operator) {
ControlSystemSignatureEntity value = requireStatus(subject, "PACKAGED", "请先打包控制系统签名反馈报文");
update(value, "PACKAGED", "SENT", operator, new LambdaUpdateWrapper<ControlSystemSignatureEntity>());
return new ControlSystemSignatureResult(requireLatest(subject));
}
@Transactional
public ControlSystemSignatureResult receive(InstitutionKeySubject subject, String operator) {
ControlSystemSignatureEntity value = requireStatus(subject, "SENT", "中央银行尚未发送控制系统签名报文");
update(value, "SENT", "RECEIVED", operator, new LambdaUpdateWrapper<ControlSystemSignatureEntity>());
scoreService.markStepCompleted(subject.getUserId(), 7);
return new ControlSystemSignatureResult(requireLatest(subject));
}
@Transactional(readOnly = true)
public ControlSystemSignatureResult detail(InstitutionKeySubject subject) {
return new ControlSystemSignatureResult(requireLatest(subject));
}
private TransactionInformationIdentifierEntity requireQuotaVerified(InstitutionKeySubject subject) {
TransactionInformationIdentifierEntity value = transactionMapper.selectOne(
new LambdaQueryWrapper<TransactionInformationIdentifierEntity>()
.eq(TransactionInformationIdentifierEntity::getUserId, subject.getUserId())
.eq(TransactionInformationIdentifierEntity::getSchoolId, subject.getSchoolId())
.eq(TransactionInformationIdentifierEntity::getClassId, subject.getClassId())
.eq(TransactionInformationIdentifierEntity::getStatus, "QUOTA_VERIFIED")
.eq(TransactionInformationIdentifierEntity::getDeleted, false)
.orderByDesc(TransactionInformationIdentifierEntity::getCreatedAt).last("LIMIT 1"));
if (value == null) throw new BusinessException(ErrorCode.VALIDATION_ERROR, "步骤六尚未完成额度验证,不能进入步骤七");
return value;
}
private ControlSystemSignatureEntity requireStatus(InstitutionKeySubject subject, String status, String message) {
ControlSystemSignatureEntity value = requireLatest(subject);
if (!status.equals(value.getStatus())) {
throw new BusinessException(ErrorCode.VALIDATION_ERROR, message + ",当前状态:" + value.getStatus());
}
return value;
}
private ControlSystemSignatureEntity requireLatest(InstitutionKeySubject subject) {
ControlSystemSignatureEntity value = latest(subject);
if (value == null) throw new BusinessException(ErrorCode.RESOURCE_NOT_FOUND, "当前没有步骤七控制系统签名记录");
return value;
}
private ControlSystemSignatureEntity latest(InstitutionKeySubject subject) {
return mapper.selectOne(new LambdaQueryWrapper<ControlSystemSignatureEntity>()
.eq(ControlSystemSignatureEntity::getUserId, subject.getUserId())
.eq(ControlSystemSignatureEntity::getSchoolId, subject.getSchoolId())
.eq(ControlSystemSignatureEntity::getClassId, subject.getClassId())
.eq(ControlSystemSignatureEntity::getDeleted, false)
.orderByDesc(ControlSystemSignatureEntity::getCreatedAt).last("LIMIT 1"));
}
private void update(ControlSystemSignatureEntity value, String from, String to, String operator,
LambdaUpdateWrapper<ControlSystemSignatureEntity> fields) {
fields.eq(ControlSystemSignatureEntity::getId, value.getId())
.eq(ControlSystemSignatureEntity::getStatus, from)
.eq(ControlSystemSignatureEntity::getDeleted, false)
.set(ControlSystemSignatureEntity::getStatus, to)
.set(ControlSystemSignatureEntity::getUpdatedAt, LocalDateTime.now())
.set(ControlSystemSignatureEntity::getUpdatedBy, operator);
if (mapper.update(null, fields) != 1) {
throw new BusinessException(ErrorCode.VALIDATION_ERROR, "步骤七状态已变化,不能重复或越级操作");
}
}
}