diff --git a/src/main/java/ru/nbch/credit_tracker/config/rest/ResponseErrorHandler.java b/src/main/java/ru/nbch/credit_tracker/config/rest/ResponseErrorHandler.java new file mode 100644 index 0000000..d322448 --- /dev/null +++ b/src/main/java/ru/nbch/credit_tracker/config/rest/ResponseErrorHandler.java @@ -0,0 +1,32 @@ +package ru.nbch.credit_tracker.config.rest; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; + +import java.io.IOException; + +@Slf4j +public class ResponseErrorHandler extends DefaultResponseErrorHandler { + @Override + public void handleError(ClientHttpResponse response) throws IOException { + if (response.getStatusCode().is4xxClientError()) { + throw new HttpClientErrorException( + response.getStatusCode(), + "Client error: " + response.getStatusText(), + response.getBody().readAllBytes(), + null + ); + } else if (response.getStatusCode().is5xxServerError()) { + throw new HttpServerErrorException( + response.getStatusCode(), + "Server error: " + response.getStatusText(), + response.getBody().readAllBytes(), + null + ); + } + super.handleError(response); + } +} diff --git a/src/main/java/ru/nbch/credit_tracker/config/rest/RestConfig.java b/src/main/java/ru/nbch/credit_tracker/config/rest/RestConfig.java new file mode 100644 index 0000000..9d3f44c --- /dev/null +++ b/src/main/java/ru/nbch/credit_tracker/config/rest/RestConfig.java @@ -0,0 +1,18 @@ +package ru.nbch.credit_tracker.config.rest; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; +import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings; + +@Configuration +public class RestConfig { + + @Bean(name = "restTemplate") + public RestTemplate restTemplate(CreditTrackerSettings config) { + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setUriTemplateHandler(new RootUriTemplateHandler(config.getSignalsRootUri())); + restTemplate.setErrorHandler(new ResponseErrorHandler()); + return restTemplate; + } +} diff --git a/src/main/java/ru/nbch/credit_tracker/config/rest/RootUriTemplateHandler.java b/src/main/java/ru/nbch/credit_tracker/config/rest/RootUriTemplateHandler.java new file mode 100644 index 0000000..49aed43 --- /dev/null +++ b/src/main/java/ru/nbch/credit_tracker/config/rest/RootUriTemplateHandler.java @@ -0,0 +1,25 @@ +package ru.nbch.credit_tracker.config.rest; + +import org.springframework.web.util.DefaultUriBuilderFactory; + +import java.net.URI; +import java.util.Map; + +public class RootUriTemplateHandler extends DefaultUriBuilderFactory { + private final String rootUri; + + public RootUriTemplateHandler(String rootUri) { + super(rootUri); + this.rootUri = rootUri; + } + + @Override + public URI expand(String uriTemplate, Map uriVariables) { + return super.expand(rootUri + uriTemplate, uriVariables); + } + + @Override + public URI expand(String uriTemplate, Object... uriVariables) { + return super.expand(rootUri + uriTemplate, uriVariables); + } +} \ No newline at end of file diff --git a/src/main/java/ru/nbch/credit_tracker/config/settings/CreditTrackerSettings.java b/src/main/java/ru/nbch/credit_tracker/config/settings/CreditTrackerSettings.java index 146d130..f58dcd9 100644 --- a/src/main/java/ru/nbch/credit_tracker/config/settings/CreditTrackerSettings.java +++ b/src/main/java/ru/nbch/credit_tracker/config/settings/CreditTrackerSettings.java @@ -19,4 +19,10 @@ public class CreditTrackerSettings { private DataSourceSettings scoringDataSourceSettings; @NestedConfigurationProperty private XsdValidation xsdValidation; + + private String signalsRootUri; + private String signalsToken; + private String signalsuser; + + private String tmpFilePath; // TODO throw exception if not created or create } diff --git a/src/main/java/ru/nbch/credit_tracker/facade/SignalFacade.java b/src/main/java/ru/nbch/credit_tracker/facade/SignalFacade.java index c4f4fb2..de8f7c6 100644 --- a/src/main/java/ru/nbch/credit_tracker/facade/SignalFacade.java +++ b/src/main/java/ru/nbch/credit_tracker/facade/SignalFacade.java @@ -10,10 +10,12 @@ import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings; import ru.nbch.credit_tracker.entities.monitoring_request.MonitoringRequest; import ru.nbch.credit_tracker.entities.signal_package.Signals; import ru.nbch.credit_tracker.enums.SignalError; +import ru.nbch.credit_tracker.enums.Status; import ru.nbch.credit_tracker.service.FailureAnswerGenerator; import ru.nbch.credit_tracker.service.SignalService; import ru.nbch.credit_tracker.service.indic.PhoneService; import ru.nbch.credit_tracker.service.scoring.AuthorizationService; +import ru.nbch.credit_tracker.service.signal.SignalRestService; import ru.nbch.credit_tracker.service.xml.IXmlProcessor; import ru.nbch.credit_tracker.service.xml.XmlUtilService; @@ -29,17 +31,20 @@ public class SignalFacade { private final CreditTrackerSettings config; private final AuthorizationService authorizationService; private final SignalService signalService; + private final SignalRestService signalRestService; private final FailureAnswerGenerator failureAnswerGenerator; private final XmlUtilService xmlUtilService; public SignalFacade(CreditTrackerSettings config, AuthorizationService authorizationService, SignalService signalService, + SignalRestService signalRestService, FailureAnswerGenerator failureAnswerGenerator, XmlUtilService xmlUtilService) { this.config = config; this.authorizationService = authorizationService; this.signalService = signalService; + this.signalRestService = signalRestService; this.failureAnswerGenerator = failureAnswerGenerator; this.xmlUtilService = xmlUtilService; } @@ -129,9 +134,15 @@ public class SignalFacade { List phoneFidsData = signalService.registerPackage(monitoringRequest); if(!phoneFidsData.isEmpty()) { - Signals signals = signalService.setupMonitoring(monitoringRequest, phoneFidsData); + Signals signals = signalService.buildSignals(monitoringRequest, phoneFidsData); // TODO validate? - // TODO marshall to xml and send to nbki signal service + String response = signalRestService.update(signals); + if (response == null) { + signalService.setPackageStatus(monitoringRequest, Status.ON_MONITORING); + } else { + signalService.setPackageStatus(monitoringRequest, Status.ERROR); + return getBadResponse(SignalError.ERROR_100); // TODO ??? Ошибка от офф сервиса или вынос этой логики? + } } } catch (Exception e) { diff --git a/src/main/java/ru/nbch/credit_tracker/mapper/signal/SignalMapper.java b/src/main/java/ru/nbch/credit_tracker/mapper/signal/SignalMapper.java index 024af3c..aeef50e 100644 --- a/src/main/java/ru/nbch/credit_tracker/mapper/signal/SignalMapper.java +++ b/src/main/java/ru/nbch/credit_tracker/mapper/signal/SignalMapper.java @@ -20,4 +20,6 @@ public interface SignalMapper { void insertPackage(@Param("request") MonitoringRequest request, @Param("creadedAt") LocalDateTime creadedAt, @Param("status") String status); void registerSubjectsFidAndDebts(@Param("id") String id, @Param("fid") Integer fid, @Param("flagDebt5000") Integer flagDebt5000, @Param("flag90") Integer flag90, @Param("packageId") Integer packageId); + + void setPackageStatus(@Param("request") MonitoringRequest request, @Param("status") String status); } diff --git a/src/main/java/ru/nbch/credit_tracker/service/SignalService.java b/src/main/java/ru/nbch/credit_tracker/service/SignalService.java index a5a8f92..0f14316 100644 --- a/src/main/java/ru/nbch/credit_tracker/service/SignalService.java +++ b/src/main/java/ru/nbch/credit_tracker/service/SignalService.java @@ -60,7 +60,11 @@ public class SignalService { mapper.insertPackage(request, LocalDateTime.now(), Status.REJECTED.name()); } - public Signals setupMonitoring(MonitoringRequest request, List fids) { + public void setPackageStatus(MonitoringRequest request, Status status) { + mapper.setPackageStatus(request, status.name()); + } + + public Signals buildSignals(MonitoringRequest request, List fids) { Signals signals = new Signals(); signals.setOnline("2"); // Всегда=2 (только онлайн-сигналы) signals.setId(request.getUserId().substring(0, 6) + "_" + request.getPackageName()); // _ diff --git a/src/main/java/ru/nbch/credit_tracker/service/signal/SignalRestService.java b/src/main/java/ru/nbch/credit_tracker/service/signal/SignalRestService.java new file mode 100644 index 0000000..7406b09 --- /dev/null +++ b/src/main/java/ru/nbch/credit_tracker/service/signal/SignalRestService.java @@ -0,0 +1,111 @@ +package ru.nbch.credit_tracker.service.signal; + +import jakarta.xml.bind.DatatypeConverter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FileUtils; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.core.io.PathResource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; +import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings; +import ru.nbch.credit_tracker.entities.signal_package.Signals; +import ru.nbch.credit_tracker.service.xml.IXmlProcessor; +import ru.nbch.credit_tracker.service.xml.XmlUtilService; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.Base64; +import java.util.UUID; +import java.util.zip.GZIPOutputStream; + +@Slf4j +@Service +public class SignalRestService { + + private static String UPDATE_URI = "update"; + + private final RestTemplate restTemplate; + private final XmlUtilService xmlUtilService; + private final String authToken; + private final String tmpFilePath; + + public SignalRestService(@Qualifier(value = "restTemplate") RestTemplate restTemplate, + XmlUtilService xmlUtilService, + CreditTrackerSettings config) throws Exception { + this.restTemplate = restTemplate; + this.xmlUtilService = xmlUtilService; + this.authToken = buildToken(config.getSignalsToken(), config.getSignalsuser()); + this.tmpFilePath = config.getTmpFilePath(); + } + + public String update(Signals signals) throws Exception { + String folder = tmpFilePath + File.separator + UUID.randomUUID(); + String path = folder + File.separator + "reply.xml"; + IXmlProcessor processor = xmlUtilService.createJaxbProcessor(); + processor.write(path, signals, false); + + String archivePath = compressFile(path, folder); + PathResource fileResource = new PathResource(archivePath); + + MultiValueMap body = new LinkedMultiValueMap<>(); + body.add("file", fileResource); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + headers.setBasicAuth(authToken); + + HttpEntity> requestEntity = new HttpEntity<>(body, headers); + + ResponseEntity response = restTemplate.postForEntity(UPDATE_URI, requestEntity, String.class); + + FileUtils.delete(FileUtils.getFile(path)); + FileUtils.delete(FileUtils.getFile(archivePath)); + + if (response.getStatusCode().value() == 302) { + // good response + return null; + } else if (response.getStatusCode().value() == 200 && response.getBody() != null) { + // bad response + return response.getBody(); + } + return "Непредвиденная ошибка"; + } + + private String compressFile(String filePath, String folderPath) throws Exception { + byte[] buffer = new byte[1024]; + String archivePath = folderPath + "arhive.gz"; + + FileInputStream fis = new FileInputStream(filePath); + GZIPOutputStream gzos = new GZIPOutputStream(new FileOutputStream(archivePath)); + + int bytesRead; + while ((bytesRead = fis.read(buffer)) != -1) { + gzos.write(buffer, 0, bytesRead); + } + gzos.close(); + fis.close(); + return archivePath; + } + + private String buildToken(String signalsToken, String signalsuser) throws Exception { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] messageDigest = md.digest((signalsuser + "|" + signalsToken).getBytes(StandardCharsets.UTF_8)); + String hash = DatatypeConverter.printHexBinary(messageDigest).toLowerCase(); + Base64.Encoder encoder = Base64.getEncoder(); + return encoder.encodeToString(hash.getBytes(StandardCharsets.UTF_8)); + } catch (Exception e) { + log.error("Error building token", e); + throw new Exception("Error building token", e); + } + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 10b22c5..6d5d1e3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -26,4 +26,9 @@ ct.scoring-data-source-settings.password=tester # xsd paths ct.xsd-validation.monitoring-request-path=monitoring-request.xsd -ct.xsd-validation.signal-package-path=signal-package.xsd \ No newline at end of file +ct.xsd-validation.signal-package-path=signal-package.xsd + +ct.signals-root-uri=http://reports.test-alfa.nbki.ru/signalRUalfa/ +ct.signals-token=gttcHxwcGojoAvZK +ct.signals-user=0001ZZ +ct.tmp-file-path=temp_folder \ No newline at end of file diff --git a/src/main/resources/mybatis/mapper/signal/SignalMapper.xml b/src/main/resources/mybatis/mapper/signal/SignalMapper.xml index 04e1ff0..958403f 100644 --- a/src/main/resources/mybatis/mapper/signal/SignalMapper.xml +++ b/src/main/resources/mybatis/mapper/signal/SignalMapper.xml @@ -36,4 +36,10 @@ WHERE package_id = #{packageId} AND subject_id = #{id} + + UPDATE signals_user_packages + SET status = #{status} + WHERE membercode = #{request.userId} AND package_name = #{request.packageName} + + \ No newline at end of file