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.
214 lines
12 KiB
Java
214 lines
12 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.math.BigDecimal;
|
|
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 ControlSystemDigestResult digest(String originalText, InstitutionKeySubject subject, String operator) {
|
|
TransactionInformationIdentifierEntity transaction = requireQuotaVerified(subject);
|
|
String normalizedOriginalText = validateOriginalText(originalText, transaction, subject);
|
|
ControlSystemSignatureEntity current = latest(subject);
|
|
if (current != null) {
|
|
if (!current.getTransactionIdentifierId().equals(transaction.getId())) {
|
|
throw new BusinessException(ErrorCode.VALIDATION_ERROR,
|
|
"当前实训已有步骤七控制系统签名记录,如需重新开始请先调用重新实训接口");
|
|
}
|
|
String digest = cryptography.sm3(normalizedOriginalText);
|
|
update(current, current.getStatus(), "DIGESTED", operator,
|
|
new LambdaUpdateWrapper<ControlSystemSignatureEntity>()
|
|
.set(ControlSystemSignatureEntity::getOriginalText, normalizedOriginalText)
|
|
.set(ControlSystemSignatureEntity::getDigest, digest)
|
|
.set(ControlSystemSignatureEntity::getSigningKeyId, null)
|
|
.set(ControlSystemSignatureEntity::getSignature, null)
|
|
.set(ControlSystemSignatureEntity::getControlSignature, null)
|
|
.set(ControlSystemSignatureEntity::getResponseMessage, null));
|
|
return new ControlSystemDigestResult(digest);
|
|
}
|
|
|
|
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(normalizedOriginalText);
|
|
value.setDigest(cryptography.sm3(normalizedOriginalText));
|
|
value.setStatus("DIGESTED");
|
|
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 ControlSystemDigestResult(value.getDigest());
|
|
}
|
|
|
|
@Transactional
|
|
public ControlSystemSignatureResult sign(String privateKey, InstitutionKeySubject subject, String operator) {
|
|
ControlSystemSignatureEntity value = requireLatest(subject);
|
|
requireResult(value.getDigest(), "请先计算控制系统签名摘要");
|
|
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, value.getStatus(), "SIGNED", operator,
|
|
new LambdaUpdateWrapper<ControlSystemSignatureEntity>()
|
|
.set(ControlSystemSignatureEntity::getSigningKeyId, InstitutionKeyService.CENTRAL_FIRST_KEY)
|
|
.set(ControlSystemSignatureEntity::getSignature, signature)
|
|
.set(ControlSystemSignatureEntity::getControlSignature, signature)
|
|
.set(ControlSystemSignatureEntity::getResponseMessage, null));
|
|
return new ControlSystemSignatureResult(requireLatest(subject));
|
|
}
|
|
|
|
@Transactional
|
|
public ControlSystemSignatureResult packageResponse(InstitutionKeySubject subject, String operator) {
|
|
ControlSystemSignatureEntity value = requireLatest(subject);
|
|
requireResult(value.getControlSignature(), "请先完成中央银行控制系统签名");
|
|
String message = "{\"ctrlId\":\"" + value.getControlId() + "\",\"amount\":\""
|
|
+ value.getAmount().setScale(2).toPlainString() + "\",\"orgId\":\""
|
|
+ value.getInstitutionIdentifier() + "\",\"txnId\":\""
|
|
+ value.getTransactionIdentifier() + "\",\"cbCtrlSignature\":\""
|
|
+ value.getControlSignature() + "\"}";
|
|
update(value, value.getStatus(), "PACKAGED", operator,
|
|
new LambdaUpdateWrapper<ControlSystemSignatureEntity>()
|
|
.set(ControlSystemSignatureEntity::getResponseMessage, message));
|
|
return new ControlSystemSignatureResult(requireLatest(subject));
|
|
}
|
|
|
|
@Transactional
|
|
public ControlSystemSignatureResult send(InstitutionKeySubject subject, String operator) {
|
|
ControlSystemSignatureEntity value = requireLatest(subject);
|
|
requireResult(value.getResponseMessage(), "请先打包控制系统签名反馈报文");
|
|
update(value, value.getStatus(), "SENT", 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));
|
|
}
|
|
|
|
@Transactional(readOnly = true)
|
|
public CommercialBankControlSystemSignatureResult commercialBankMessage(InstitutionKeySubject subject) {
|
|
return new CommercialBankControlSystemSignatureResult(latest(subject));
|
|
}
|
|
|
|
private String validateOriginalText(String originalText, TransactionInformationIdentifierEntity transaction,
|
|
InstitutionKeySubject subject) {
|
|
String value = originalText == null ? null : originalText.trim();
|
|
if (value == null || value.isEmpty()) {
|
|
throw dataError(subject, "拼接请求原文不能为空");
|
|
}
|
|
String[] parts = value.split("\\|", -1);
|
|
if (parts.length != 3) {
|
|
throw dataError(subject, "拼接请求原文格式必须为:金额|机构标识|交易信息标识");
|
|
}
|
|
BigDecimal amount;
|
|
try {
|
|
amount = new BigDecimal(parts[0]);
|
|
} catch (NumberFormatException exception) {
|
|
throw dataError(subject, "拼接请求原文中的金额格式不正确");
|
|
}
|
|
if (amount.compareTo(transaction.getAmount()) != 0
|
|
|| !transaction.getInstitutionIdentifier().equals(parts[1])
|
|
|| !transaction.getTransactionIdentifier().equals(parts[2])) {
|
|
throw dataError(subject,
|
|
"拼接请求原文中的金额、机构标识或交易信息标识与当前用户前序数据不一致");
|
|
}
|
|
return value;
|
|
}
|
|
|
|
private BusinessException dataError(InstitutionKeySubject subject, String message) {
|
|
int errorSequence = errorRecorder.recordScoreError(subject.getUserId());
|
|
return new BusinessException(ErrorCode.VALIDATION_ERROR,
|
|
message + ",本次实训第" + errorSequence + "次错误");
|
|
}
|
|
|
|
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 void requireResult(String value, String message) {
|
|
if (value == null || value.trim().isEmpty()) {
|
|
throw new BusinessException(ErrorCode.VALIDATION_ERROR, message);
|
|
}
|
|
}
|
|
|
|
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, "步骤七状态已变化,不能重复或越级操作");
|
|
}
|
|
}
|
|
}
|