Added Rest Template; Added sending update post query; Added ability to change package statuses

This commit is contained in:
Mikhail Trofimov 2025-06-11 15:34:29 +03:00
parent ebbbd1b575
commit c35498f8d5
10 changed files with 224 additions and 4 deletions

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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<String, ?> uriVariables) {
return super.expand(rootUri + uriTemplate, uriVariables);
}
@Override
public URI expand(String uriTemplate, Object... uriVariables) {
return super.expand(rootUri + uriTemplate, uriVariables);
}
}

View file

@ -19,4 +19,10 @@ public class CreditTrackerSettings {
private DataSourceSettings scoringDataSourceSettings; private DataSourceSettings scoringDataSourceSettings;
@NestedConfigurationProperty @NestedConfigurationProperty
private XsdValidation xsdValidation; private XsdValidation xsdValidation;
private String signalsRootUri;
private String signalsToken;
private String signalsuser;
private String tmpFilePath; // TODO throw exception if not created or create
} }

View file

@ -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.monitoring_request.MonitoringRequest;
import ru.nbch.credit_tracker.entities.signal_package.Signals; import ru.nbch.credit_tracker.entities.signal_package.Signals;
import ru.nbch.credit_tracker.enums.SignalError; 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.FailureAnswerGenerator;
import ru.nbch.credit_tracker.service.SignalService; import ru.nbch.credit_tracker.service.SignalService;
import ru.nbch.credit_tracker.service.indic.PhoneService; import ru.nbch.credit_tracker.service.indic.PhoneService;
import ru.nbch.credit_tracker.service.scoring.AuthorizationService; 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.IXmlProcessor;
import ru.nbch.credit_tracker.service.xml.XmlUtilService; import ru.nbch.credit_tracker.service.xml.XmlUtilService;
@ -29,17 +31,20 @@ public class SignalFacade {
private final CreditTrackerSettings config; private final CreditTrackerSettings config;
private final AuthorizationService authorizationService; private final AuthorizationService authorizationService;
private final SignalService signalService; private final SignalService signalService;
private final SignalRestService signalRestService;
private final FailureAnswerGenerator failureAnswerGenerator; private final FailureAnswerGenerator failureAnswerGenerator;
private final XmlUtilService xmlUtilService; private final XmlUtilService xmlUtilService;
public SignalFacade(CreditTrackerSettings config, public SignalFacade(CreditTrackerSettings config,
AuthorizationService authorizationService, AuthorizationService authorizationService,
SignalService signalService, SignalService signalService,
SignalRestService signalRestService,
FailureAnswerGenerator failureAnswerGenerator, FailureAnswerGenerator failureAnswerGenerator,
XmlUtilService xmlUtilService) { XmlUtilService xmlUtilService) {
this.config = config; this.config = config;
this.authorizationService = authorizationService; this.authorizationService = authorizationService;
this.signalService = signalService; this.signalService = signalService;
this.signalRestService = signalRestService;
this.failureAnswerGenerator = failureAnswerGenerator; this.failureAnswerGenerator = failureAnswerGenerator;
this.xmlUtilService = xmlUtilService; this.xmlUtilService = xmlUtilService;
} }
@ -129,9 +134,15 @@ public class SignalFacade {
List<PhoneService.FidsPhoneData> phoneFidsData = signalService.registerPackage(monitoringRequest); List<PhoneService.FidsPhoneData> phoneFidsData = signalService.registerPackage(monitoringRequest);
if(!phoneFidsData.isEmpty()) { if(!phoneFidsData.isEmpty()) {
Signals signals = signalService.setupMonitoring(monitoringRequest, phoneFidsData); Signals signals = signalService.buildSignals(monitoringRequest, phoneFidsData);
// TODO validate? // 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) { } catch (Exception e) {

View file

@ -20,4 +20,6 @@ public interface SignalMapper {
void insertPackage(@Param("request") MonitoringRequest request, @Param("creadedAt") LocalDateTime creadedAt, @Param("status") String status); 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 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);
} }

View file

@ -60,7 +60,11 @@ public class SignalService {
mapper.insertPackage(request, LocalDateTime.now(), Status.REJECTED.name()); mapper.insertPackage(request, LocalDateTime.now(), Status.REJECTED.name());
} }
public Signals setupMonitoring(MonitoringRequest request, List<PhoneService.FidsPhoneData> fids) { public void setPackageStatus(MonitoringRequest request, Status status) {
mapper.setPackageStatus(request, status.name());
}
public Signals buildSignals(MonitoringRequest request, List<PhoneService.FidsPhoneData> fids) {
Signals signals = new Signals(); Signals signals = new Signals();
signals.setOnline("2"); // Всегда=2 (только онлайн-сигналы) signals.setOnline("2"); // Всегда=2 (только онлайн-сигналы)
signals.setId(request.getUserId().substring(0, 6) + "_" + request.getPackageName()); // <MEMBERCODE>_<PackageName> signals.setId(request.getUserId().substring(0, 6) + "_" + request.getPackageName()); // <MEMBERCODE>_<PackageName>

View file

@ -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<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", fileResource);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.setBasicAuth(authToken);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
ResponseEntity<String> 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);
}
}
}

View file

@ -27,3 +27,8 @@ ct.scoring-data-source-settings.password=tester
# xsd paths # xsd paths
ct.xsd-validation.monitoring-request-path=monitoring-request.xsd ct.xsd-validation.monitoring-request-path=monitoring-request.xsd
ct.xsd-validation.signal-package-path=signal-package.xsd 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

View file

@ -36,4 +36,10 @@
WHERE package_id = #{packageId} AND subject_id = #{id} WHERE package_id = #{packageId} AND subject_id = #{id}
</update> </update>
<update id="setPackageStatus">
UPDATE signals_user_packages
SET status = #{status}
WHERE membercode = #{request.userId} AND package_name = #{request.packageName}
</update>
</mapper> </mapper>