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.
125 lines
6.4 KiB
Java
125 lines
6.4 KiB
Java
package com.yau.digitalrmb.institutionidentity.application;
|
|
|
|
import com.yau.digitalrmb.institutionidentity.domain.InstitutionIdentifierApplication;
|
|
import com.yau.digitalrmb.institutionidentity.domain.InstitutionIdentifierRepository;
|
|
import com.yau.digitalrmb.institutionidentity.domain.InstitutionIdentityCryptography;
|
|
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.Clock;
|
|
import java.time.LocalDateTime;
|
|
import java.time.ZoneOffset;
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
@Service
|
|
public class InstitutionIdentifierStepService {
|
|
private static final DateTimeFormatter TIMESTAMP = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
|
|
|
|
@Resource
|
|
private InstitutionIdentityCryptography cryptography;
|
|
|
|
@Resource
|
|
private InstitutionKeyService keyService;
|
|
|
|
@Resource
|
|
private InstitutionIdentifierRepository repository;
|
|
|
|
@Resource
|
|
private InstitutionTrainingErrorRecorder errorRecorder;
|
|
|
|
private final Clock clock = Clock.systemUTC();
|
|
|
|
@Transactional
|
|
public InstitutionInformationPreparationResult prepare(String bankCode, String operator) {
|
|
String normalized = normalize(bankCode);
|
|
int trainingRound = repository.nextTrainingRound(normalized, operator);
|
|
String timestamp = LocalDateTime.ofInstant(clock.instant(), ZoneOffset.UTC).format(TIMESTAMP);
|
|
InstitutionIdentifierApplication application = InstitutionIdentifierApplication.prepare(normalized, timestamp);
|
|
long applicationId = repository.save(application, trainingRound, operator);
|
|
return new InstitutionInformationPreparationResult(applicationId, application.getStatus().name(), normalized,
|
|
timestamp, normalized + "|" + timestamp, trainingRound, 0);
|
|
}
|
|
|
|
@Transactional
|
|
public InstitutionDigestResult digest(long applicationId, String operator) {
|
|
InstitutionIdentifierApplication application = requireApplication(applicationId);
|
|
requireStatus(application, InstitutionIdentifierApplication.Status.PREPARED, "当前步骤不是摘要计算,不能操作", operator);
|
|
InstitutionIdentifierApplication.Status expectedStatus = application.getStatus();
|
|
String text = application.getBankCode() + "|" + application.getTimestamp();
|
|
String digest = cryptography.sm3(text);
|
|
invokeDomain(() -> application.recordDigest(digest));
|
|
repository.update(application, expectedStatus, "DIGEST", "使用SM3计算并保存业务摘要", operator);
|
|
return new InstitutionDigestResult(applicationId, application.getStatus().name(), "SM3", text, digest);
|
|
}
|
|
|
|
@Transactional
|
|
public InstitutionSignatureResult sign(long applicationId, String keyId, InstitutionKeySubject subject,
|
|
String operator) {
|
|
InstitutionIdentifierApplication application = requireApplication(applicationId);
|
|
if (!InstitutionKeyService.BANK_SECOND_KEY.equals(keyId)) {
|
|
recordAndThrow(application, "WRONG_KEY", "SIGN", keyId,
|
|
"签名必须选择商业银行第二密钥", operator);
|
|
}
|
|
requireStatus(application, InstitutionIdentifierApplication.Status.DIGESTED,
|
|
"当前步骤不是商业银行签名,不能操作", operator);
|
|
InstitutionIdentifierApplication.Status expectedStatus = application.getStatus();
|
|
String signature = keyService.signCommercialBank(subject, application.getDigest());
|
|
invokeDomain(() -> application.recordBankSignature(signature));
|
|
repository.update(application, expectedStatus, "SIGN", "使用商业银行第二私钥完成SM2签名", operator);
|
|
return new InstitutionSignatureResult(applicationId, application.getStatus().name(), "SM2", keyId,
|
|
"COMMERCIAL_BANK_SECOND_PRIVATE_KEY", signature);
|
|
}
|
|
|
|
@Transactional
|
|
public InstitutionApplicationPackageResult packageApplication(long applicationId, String operator) {
|
|
InstitutionIdentifierApplication application = requireApplication(applicationId);
|
|
requireStatus(application, InstitutionIdentifierApplication.Status.SIGNED, "当前步骤不是申请组装,不能操作", operator);
|
|
InstitutionIdentifierApplication.Status expectedStatus = application.getStatus();
|
|
invokeDomain(application::packageApplication);
|
|
repository.update(application, expectedStatus, "PACKAGE", "组装机构标识申请材料并提交央行待验证", operator);
|
|
return new InstitutionApplicationPackageResult(applicationId, application.getStatus().name(),
|
|
application.getBankCode(), application.getTimestamp(), application.getDigest(),
|
|
application.getBankSignature());
|
|
}
|
|
|
|
private InstitutionIdentifierApplication requireApplication(long applicationId) {
|
|
return repository.findById(applicationId).orElseThrow(() ->
|
|
new BusinessException(ErrorCode.RESOURCE_NOT_FOUND, "机构标识申请不存在"));
|
|
}
|
|
|
|
private void requireStatus(InstitutionIdentifierApplication application,
|
|
InstitutionIdentifierApplication.Status expectedStatus,
|
|
String message, String operator) {
|
|
if (application.getStatus() != expectedStatus) {
|
|
recordAndThrow(application, "INVALID_STEP", expectedStatus.name(), null,
|
|
message + ",当前状态:" + application.getStatus().name(), operator);
|
|
}
|
|
}
|
|
|
|
private void recordAndThrow(InstitutionIdentifierApplication application, String errorType, String operationStep,
|
|
String providedKeyId, String message, String operator) {
|
|
int errorSequence = errorRecorder.record(application.getId(), errorType, operationStep, providedKeyId,
|
|
message, operator);
|
|
invalid(message + ",本次实训第" + errorSequence + "次错误");
|
|
}
|
|
|
|
private static void invokeDomain(Runnable operation) {
|
|
try {
|
|
operation.run();
|
|
} catch (IllegalArgumentException | IllegalStateException exception) {
|
|
invalid(exception.getMessage());
|
|
}
|
|
}
|
|
|
|
private static String normalize(String value) {
|
|
return value.trim().toUpperCase();
|
|
}
|
|
|
|
private static void invalid(String message) {
|
|
throw new BusinessException(ErrorCode.VALIDATION_ERROR, message);
|
|
}
|
|
}
|