Skip to content

Commit

Permalink
Merge branch 'main' into PAGOPA-2113
Browse files Browse the repository at this point in the history
  • Loading branch information
cap-ang authored Sep 26, 2024
2 parents 4b939e0 + db54d60 commit a9a8b0f
Show file tree
Hide file tree
Showing 25 changed files with 442 additions and 71 deletions.
4 changes: 2 additions & 2 deletions helm/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ apiVersion: v2
name: pagopa-wisp-converter
description: A service that permits to handle nodoInviaRPT and nodoInviaCarrelloRPT request from WISP, interfacing them with GPD system
type: application
version: 0.198.0
appVersion: 0.3.0-3-PAGOPA-2113
version: 0.208.0
appVersion: 0.3.5
dependencies:
- name: microservice-chart
version: 3.0.0
Expand Down
3 changes: 2 additions & 1 deletion helm/values-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ microservice-chart:
fullnameOverride: ""
image:
repository: ghcr.io/pagopa/pagopa-wisp-converter
tag: "0.3.0-3-PAGOPA-2113"
tag: "0.3.5"
pullPolicy: Always
livenessProbe:
httpGet:
Expand Down Expand Up @@ -82,6 +82,7 @@ microservice-chart:
RECEIPT_TIMER_QUEUE_NAME: "nodo_wisp_payment_timeout_queue"
ECOMMERCE_HANG_TIMER_QUEUE_NAME: "nodo_wisp_ecommerce_hang_timeout_queue"
ECOMMERCE_HANG_TIMEOUT: '1800'
APIM_PATH: 'api.dev.platform.pagopa.it'
CACHED_REQUESTID_MAPPING_TTL_MINUTES: "1440"
CACHE_REFRESH_CRON: "0 */60 * * * *"
CLIENT_GPD_READ_TIMEOUT: '5000'
Expand Down
3 changes: 2 additions & 1 deletion helm/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ microservice-chart:
fullnameOverride: ""
image:
repository: ghcr.io/pagopa/pagopa-wisp-converter
tag: "0.3.0-3-PAGOPA-2113"
tag: "0.3.5"
pullPolicy: Always
livenessProbe:
httpGet:
Expand Down Expand Up @@ -101,6 +101,7 @@ microservice-chart:
RECEIPT_TIMER_QUEUE_NAME: "nodo_wisp_payment_timeout_queue"
ECOMMERCE_HANG_TIMER_QUEUE_NAME: "nodo_wisp_ecommerce_hang_timeout_queue"
ECOMMERCE_HANG_TIMEOUT: '1800'
APIM_PATH: 'api.platform.pagopa.it'
CACHED_REQUESTID_MAPPING_TTL_MINUTES: "1440"
CACHE_REFRESH_CRON: "0 */60 * * * *"
CLIENT_GPD_READ_TIMEOUT: '5000'
Expand Down
3 changes: 2 additions & 1 deletion helm/values-uat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ microservice-chart:
fullnameOverride: ""
image:
repository: ghcr.io/pagopa/pagopa-wisp-converter
tag: "0.3.0-3-PAGOPA-2113"
tag: "0.3.5"
pullPolicy: Always
livenessProbe:
httpGet:
Expand Down Expand Up @@ -82,6 +82,7 @@ microservice-chart:
RECEIPT_TIMER_QUEUE_NAME: "nodo_wisp_payment_timeout_queue"
ECOMMERCE_HANG_TIMER_QUEUE_NAME: "nodo_wisp_ecommerce_hang_timeout_queue"
ECOMMERCE_HANG_TIMEOUT: '1800'
APIM_PATH: 'api.uat.platform.pagopa.it'
CACHED_REQUESTID_MAPPING_TTL_MINUTES: "1440"
CACHE_REFRESH_CRON: "0 */60 * * * *"
CLIENT_GPD_READ_TIMEOUT: '5000'
Expand Down
92 changes: 90 additions & 2 deletions openapi/openapi.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion openapi/openapi_redirect.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"openapi": "3.0.1",
"info": {
"title": "WISP-Converter-redirect",
"version": "0.3.0-3-PAGOPA-2113"
"version": "0.3.5"
},
"servers": [
{
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<groupId>it.gov.pagopa</groupId>
<artifactId>wisp-converter</artifactId>
<version>0.3.0-3-PAGOPA-2113</version>
<version>0.3.5</version>
<name>pagoPA WISP Converter</name>
<description>A service that permits to handle nodoInviaRPT and nodoInviaCarrelloRPT request from WISP, converting them in NMU payments.</description>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import it.gov.pagopa.wispconverter.controller.model.RecoveryProxyReceiptRequest;
import it.gov.pagopa.wispconverter.controller.model.RecoveryProxyReceiptResponse;
import it.gov.pagopa.wispconverter.controller.model.RecoveryReceiptResponse;
import it.gov.pagopa.wispconverter.exception.AppErrorCodeMessageEnum;
import it.gov.pagopa.wispconverter.exception.AppException;
Expand All @@ -19,10 +21,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.ErrorResponse;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/recovery")
Expand Down Expand Up @@ -92,4 +91,22 @@ public ResponseEntity<RecoveryReceiptResponse> recoverReceiptKOForCreditorInstit
}
}

@Operation(summary = "Execute reconciliation for passed receipts.", description = "Execute reconciliation of all receipts in the request, searching by passed identifier", security = {@SecurityRequirement(name = "ApiKey")}, tags = {"Recovery"})
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Reconciliation completed")
})
@PostMapping(value = "/proxy")
public ResponseEntity<RecoveryProxyReceiptResponse> recoverReceiptToBeSentByProxy(@RequestBody RecoveryProxyReceiptRequest request) {
try {
log.info("Invoking API operation recoverReceiptToBeSentByProxy - args: {}", request);
return ResponseEntity.ok(recoveryService.recoverReceiptToBeSentByProxy(request));
} catch (Exception ex) {
String operationId = MDC.get(Constants.MDC_OPERATION_ID);
log.error(String.format("GenericException: operation-id=[%s]", operationId != null ? operationId : "n/a"), ex);
AppException appException = new AppException(ex, AppErrorCodeMessageEnum.ERROR, ex.getMessage());
ErrorResponse errorResponse = errorUtil.forAppException(appException);
log.error("Failed API operation recoverReceiptToBeSentByProxy - error: {}", errorResponse);
throw ex;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package it.gov.pagopa.wispconverter.controller.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.*;

import java.util.List;

@Data
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
public class RecoveryProxyReceiptRequest {

private List<String> receiptIds;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package it.gov.pagopa.wispconverter.controller.model;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.*;
import org.springframework.data.util.Pair;

import java.util.List;

@Data
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
public class RecoveryProxyReceiptResponse {

private List<Pair<String, String>> receiptStatus;
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public enum AppErrorCodeMessageEnum {
CONFIGURATION_INVALID_STATION_SERVICE_URL(1204, "Station not correctly configured", "Error while retrieving data from cached configuration. The station with code [{0}] contains wrong on missing service URL configuration and it is not possible to generate valid URI.", HttpStatus.UNPROCESSABLE_ENTITY, "An error occurred while checking the station that will be used for the payment process. In particular, analyzing the station that is related to the segregation code extracted from a payment option's notice number, it turns out that the configuration is not correctly set to points towards GPD service endpoint for RT generator. So, a change in configuration is required."),
CONFIGURATION_NOT_GPD_STATION(1205, "Station not correctly configured for GPD", "Error while checking NAV and station from cached configuration. The NAV [{0}] is associated to a station with code [{1}] and is not correctly onboarded on GPD (or the payment position is created from ACA).", HttpStatus.UNPROCESSABLE_ENTITY, "An error occurred while checking the station that will be used for the payment process. In particular, analyzing the station that is related to the segregation code extracted from a payment option's notice number, it turns out that the configuration is not correctly set to points towards GPD service endpoint. So, a change in configuration is required."),
CONFIGURATION_INVALID_GPD_STATION(1206, "Station not correctly configured for GPD", "Error while checking NAV and station from cached configuration. The station with code [{0}] related to NAV [{1}] is onboarded on GPD but the primitive version is set to 1.", HttpStatus.UNPROCESSABLE_ENTITY, "An error occurred while checking the station that will be used for the payment process. In particular, analyzing the station that is related to the segregation code extracted from a payment option's notice number, it turns out that the configuration is correctly set to points towards GPD service endpoint but uses the 'v1' primitive version (and it must use the 'v2' version). So, a change in configuration is required."),
CONFIGURATION_INVALID_STATION_PROXY(1207, "Station not correctly configured", "Error while retrieving data from cached configuration. The station with code [{0}] contains wrong on missing proxy configuration and it is not possible to generate valid proxy parameters.", HttpStatus.UNPROCESSABLE_ENTITY, "An error occurred while checking the station that will be used for the receipt send process. In particular, analyzing the station it turns out that the configuration is not correctly set to configure proxy structure for RT generator. So, a change in configuration is required."),
// --- Payment position conversion errors ---
PAYMENT_POSITION_NOT_IN_PAYABLE_STATE(1300, "Existing payment position not in payable state", "Error while generating payment position. One or more of the payment position(s) associated to IUV(s) [{0}] exists but are not in a payable state.", HttpStatus.UNPROCESSABLE_ENTITY, "An error occurred while checking an existing payment position. One or more RPTs extracted from the request refers to existing payment positions in GPD that have a state from which it is impossible to execute a payment flow. If the execution of this flow is related to a RPT cart, all the payments that can be retrieved or generated ex novo from those RPTs are declared as atomically invalid (if one RPT in cart is bad, all RPTs in cart are bad) and not payable with this flow."),
PAYMENT_POSITION_IN_INCONSISTENT_STATE(1301, "Existing payment position in not consistent state", "Error while generating payment position. There is a payment position associated to IUV [{0}] but it is in an inconsistent state.", HttpStatus.UNPROCESSABLE_ENTITY, "An error occurred while checking an existing payment position in GPD system. The retrieved payment position, previously inserted in GPD by this same flow or by other procedures, is in an invalid state, not mappable to an existing value. This can be related to a wrong setting in GPD or a corruption of the retrieved data."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public class RTRequestEntity {

private String url;

private String proxyAddress;

private List<String> headers;

private Integer retry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import it.gov.pagopa.wispconverter.service.model.re.ReEventDto;
import it.gov.pagopa.wispconverter.util.Constants;
import it.gov.pagopa.wispconverter.util.JaxbElementUtil;
import it.gov.pagopa.wispconverter.util.ProxyUtility;
import it.gov.pagopa.wispconverter.util.ReUtil;
import jakarta.xml.soap.SOAPMessage;
import lombok.RequiredArgsConstructor;
Expand All @@ -22,11 +23,13 @@
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestClient;

import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Set;


@Service
@RequiredArgsConstructor
public class PaaInviaRTSenderService {
Expand All @@ -40,31 +43,39 @@ public class PaaInviaRTSenderService {
@Value("${wisp-converter.rt-send.avoid-scheduling-on-states}")
private Set<String> avoidSchedulingOnStates;

public void sendToCreditorInstitution(String url, List<Pair<String, String>> headers, String payload) {
public void sendToCreditorInstitution(URI uri, InetSocketAddress proxyAddress, List<Pair<String, String>> headers, String payload) {

try {

// Generating the REST client and send the passed request payload to the passed URL
RestClient client = restClientBuilder.build();
// Generating the REST client, setting proxy specification if needed
RestClient client;
if (proxyAddress != null) {
client = RestClient.builder(ProxyUtility.getProxiedClient(proxyAddress))
.build();
} else {
client = restClientBuilder.build();
}

// Send the passed request payload to the passed URL
RestClient.RequestBodySpec bodySpec = client.post()
.uri(URI.create(url))
.uri(uri)
.body(payload);
for (Pair<String, String> header : headers) {
bodySpec.header(header.getFirst(), header.getSecond());
}

// Save an RE event in order to track the communication with creditor institution
generateREForRequestToCreditorInstitution(url, headers, payload);
generateREForRequestToCreditorInstitution(uri.toString(), headers, payload);

// Communicating with creditor institution sending the paaInviaRT request
ResponseEntity<String> response = bodySpec.retrieve().toEntity(String.class);

// check SOAP response and extract body if it is valid
String bodyPayload = response.getBody();
PaaInviaRTRisposta body = checkResponseValidity(response, bodyPayload);

// Save an RE event in order to track the response from creditor institution
generateREForResponseFromCreditorInstitution(url, response.getStatusCode().value(), response.getHeaders(), bodyPayload, OutcomeEnum.RECEIVED, null);
generateREForResponseFromCreditorInstitution(uri.toString(), response.getStatusCode().value(), response.getHeaders(), bodyPayload, OutcomeEnum.RECEIVED, null);

// check SOAP response and extract body if it is valid
PaaInviaRTRisposta body = checkResponseValidity(response, bodyPayload);

// check the response and if the outcome is KO, throw an exception
EsitoPaaInviaRT esitoPaaInviaRT = body.getPaaInviaRTRisposta();
Expand Down Expand Up @@ -99,7 +110,7 @@ public void sendToCreditorInstitution(String url, List<Pair<String, String>> hea
int statusCode = error.getStatusCode().value();
String responseBody = error.getResponseBodyAsString();
String otherInfo = error.getStatusText();
generateREForResponseFromCreditorInstitution(url, statusCode, error.getResponseHeaders(), responseBody, OutcomeEnum.RECEIVED_FAILURE, otherInfo);
generateREForResponseFromCreditorInstitution(uri.toString(), statusCode, error.getResponseHeaders(), responseBody, OutcomeEnum.RECEIVED_FAILURE, otherInfo);
}

throw new AppException(AppErrorCodeMessageEnum.RECEIPT_GENERATION_GENERIC_ERROR, e.getMessage());
Expand All @@ -120,7 +131,7 @@ private PaaInviaRTRisposta checkResponseValidity(ResponseEntity<String> response
SOAPMessage soapMessage = jaxbElementUtil.getMessage(rawBody.getBytes(StandardCharsets.UTF_8));
PaaInviaRTRisposta body = this.jaxbElementUtil.getBody(soapMessage, PaaInviaRTRisposta.class);
if (body.getPaaInviaRTRisposta() == null) {
throw new AppException(AppErrorCodeMessageEnum.RECEIPT_GENERATION_WRONG_RESPONSE_FROM_CREDITOR_INSTITUTION, "Passed null paaInviaRTRisposta tag");
throw new AppException(AppErrorCodeMessageEnum.RECEIPT_GENERATION_WRONG_RESPONSE_FROM_CREDITOR_INSTITUTION, String.format("Passed null paaInviaRTRisposta tag. Body: [%s]", rawBody));
}

return body;
Expand Down
Loading

0 comments on commit a9a8b0f

Please sign in to comment.