diff --git a/.env.example b/.env.example index 4f8e30038..d4aeff63f 100644 --- a/.env.example +++ b/.env.example @@ -68,7 +68,7 @@ CLOSURE_RETRY_INTERVAL=30 JWT_ECOMMERCE_SECRET=ODMzNUZBNTZENDg3NTYyREUyNDhGNDdCRUZDNzI3NDMzMzQwNTFEREZGQ0MyQzA5Mjc1RjY2NTQ1NDk5MDMxNzU5NDc0NUVFMTdDMDhGNzk4Q0Q3RENFMEJBODE1NURDREExNEY2Mzk4QzFEMTU0NTExNjUyMEExMzMwMTdDMDk PERSONAL_DATA_VAULT_API_KEY=personal-data-vault-api-key -PERSONAL_DATA_VAULT_API_BASE_PATH="http://pagopa-pdv-mock:8092" +PERSONAL_DATA_VAULT_API_BASE_PATH="http://pagopa-pdv-mock:8092/tokenizer/v1/transaction/" CHECKOUT_BASE_PATH=http://test.pagopa.it/ @@ -78,6 +78,12 @@ NPG_CONNECTION_TIMEOUT=10000 NPG_API_KEY="npg-api-key" NPG_CARDS_PSP_LIST=CIPBITMM,BNLIITRR,BCITITMM,UNCRITMM,BPPIITRRXXX,PPAYITR1XXX NPG_CARDS_PSP_KEYS={"CIPBITMM":"CIPBITMM-api-key","BNLIITRR":"BNLIITRR-api-key","BCITITMM":"BCITITMM-api-key","UNCRITMM":"UNCRITMM-api-key","BPPIITRRXXX":"BPPIITRRXXX-api-key","PPAYITR1XXX":"PPAYITR1XXX-api-key"} +NPG_PAYPAL_PSP_LIST=BCITITMM +NPG_PAYPAL_PSP_KEYS={"BCITITMM":"BCITITMM-api-key-paypal"} +NPG_BANCOMATPAY_PSP_LIST=BCITITMM +NPG_BANCOMATPAY_PSP_KEYS={"BCITITMM":"BCITITMM-api-key-bancomatpay"} +NPG_MYBANK_PSP_LIST=BCITITMM +NPG_MYBANK_PSP_KEYS={"BCITITMM":"BCITITMM-api-key-mybank"} TRANSACTION_DOCUMENT_TTL=600 ECOMMERCE_EVENT_VERSION=V2 @@ -97,3 +103,4 @@ NODE_FORWARDER_URL=http://localhost:8096 REDIRECT_URL_MAPPING={'REDIRECT-RBPR':'http://localhost:8096/redirections'} NODE_FORWARDER_READ_TIMEOUT=10000 NODE_FORWARDER_CONNECTION_TIMEOUT=10000 +NPG_AUTHORIZATION_REQUEST_TIMEOUT_SECONDS=600 \ No newline at end of file diff --git a/README.md b/README.md index 478088df7..86233c7f0 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,12 @@ These are all environment variables needed by the application: | NODE_FORWARDER_CONNECTION_TIMEOUT | | Node forwarder request connection timeout | number | | | TRANSACTIONS_AUTHORIZATION_REQUESTED_QUEUE_NAME | | Name of the queue for transaction payment gateway polling for authorization requested transactions | string | | | NPG_AUTHORIZATION_REQUEST_TIMEOUT_SECONDS | | Timeout for npg authorization state query | number | | +| NPG_PAYPAL_PSP_KEYS | | Secret structure that holds psp - api keys association for authorization request used for APM PAYPAL payment method | string | | +| NPG_PAYPAL_PSP_LIST | | List of all psp ids that are expected to be found into the NPG_PAYPAL_PSP_KEYS configuration (used for configuration cross validation) | string | | +| NPG_BANCOMATPAY_PSP_KEYS | | Secret structure that holds psp - api keys association for authorization request used for APM Bancomat pay payment method | string | | +| NPG_BANCOMATPAY_PSP_LIST | | List of all psp ids that are expected to be found into the NPG_BANCOMATPAY_PSP_KEYS configuration (used for configuration cross validation) | string | | +| NPG_MYBANK_PSP_KEYS | | Secret structure that holds psp - api keys association for authorization request used for APM My bank payment method | string | | +| NPG_MYBANK_PSP_LIST | | List of all psp ids that are expected to be found into the NPG_MYBANK_PSP_LIST configuration (used for configuration cross validation) | string | | An example configuration of these environment variables is in the `.env.example` file. diff --git a/helm/values-dev.yaml b/helm/values-dev.yaml index 809acf3e5..bcbf0400a 100644 --- a/helm/values-dev.yaml +++ b/helm/values-dev.yaml @@ -130,7 +130,10 @@ microservice-chart: NPG_URI: "https://stg-ta.nexigroup.com/api/phoenix-0.0" NPG_READ_TIMEOUT: "10000" NPG_CONNECTION_TIMEOUT: "10000" - NPG_CARDS_PSP_LIST: "BCITITMM,CIPBITMM,BIC36019,UNCRITMM,BPPIITRRXXX,PPAYITR1XXX" + NPG_CARDS_PSP_LIST: "BCITITMM,CIPBITMM,BIC36019,UNCRITMM,BPPIITRRXXX,PPAYITR1XXX,BNLIITRR" + NPG_PAYPAL_PSP_LIST: "BCITITMM" + NPG_MYBANK_PSP_LIST: "BCITITMM" + NPG_BANCOMATPAY_PSP_LIST: "BCITITMM" NPG_AUTHORIZATION_REQUEST_TIMEOUT_SECONDS: "60" TRANSACTION_DOCUMENT_TTL: "600" CHECKOUT_BASE_PATH: "https://dev.checkout.pagopa.it" @@ -162,6 +165,9 @@ microservice-chart: JWT_NPG_NOTIFICATION_SECRET: npg-notification-signing-key NODE_FORWARDER_API_KEY: node-forwarder-api-key REDIRECT_URL_MAPPING: redirect-url-mapping + NPG_PAYPAL_PSP_KEYS: npg-paypal-psp-keys + NPG_BANCOMATPAY_PSP_KEYS: npg-bancomatpay-psp-keys + NPG_MYBANK_PSP_KEYS: npg-mybank-psp-keys keyvault: name: "pagopa-d-ecommerce-kv" tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d" diff --git a/helm/values-prod.yaml b/helm/values-prod.yaml index 3ed56b6c0..ce64d1995 100644 --- a/helm/values-prod.yaml +++ b/helm/values-prod.yaml @@ -155,6 +155,9 @@ microservice-chart: NPG_READ_TIMEOUT: "10000" NPG_CONNECTION_TIMEOUT: "10000" NPG_CARDS_PSP_LIST: "BCITITMM,CIPBITMM,BIC36019,UNCRITMM,BPPIITRRXXX,PPAYITR1XXX" + NPG_PAYPAL_PSP_LIST: "" + NPG_MYBANK_PSP_LIST: "" + NPG_BANCOMATPAY_PSP_LIST: "" NPG_AUTHORIZATION_REQUEST_TIMEOUT_SECONDS: "60" TRANSACTION_DOCUMENT_TTL: "600" CHECKOUT_BASE_PATH: "https://checkout.pagopa.it" @@ -186,6 +189,9 @@ microservice-chart: JWT_NPG_NOTIFICATION_SECRET: npg-notification-signing-key NODE_FORWARDER_API_KEY: node-forwarder-api-key REDIRECT_URL_MAPPING: redirect-url-mapping + NPG_PAYPAL_PSP_KEYS: npg-paypal-psp-keys + NPG_BANCOMATPAY_PSP_KEYS: npg-bancomatpay-psp-keys + NPG_MYBANK_PSP_KEYS: npg-mybank-psp-keys keyvault: name: "pagopa-p-ecommerce-kv" tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d" diff --git a/helm/values-uat.yaml b/helm/values-uat.yaml index e5bec235a..0b4574230 100644 --- a/helm/values-uat.yaml +++ b/helm/values-uat.yaml @@ -148,7 +148,10 @@ microservice-chart: NPG_URI: "https://stg-ta.nexigroup.com/api/phoenix-0.0" NPG_READ_TIMEOUT: "10000" NPG_CONNECTION_TIMEOUT: "10000" - NPG_CARDS_PSP_LIST: "" #TODO to be filled with psp id list that are expected to be present into psp api keys configuration + NPG_CARDS_PSP_LIST: "BCITITMM,CIPBITMM,BIC36019,UNCRITMM,BPPIITRRXXX,PPAYITR1XXX,BNLIITRR" + NPG_PAYPAL_PSP_LIST: "BCITITMM" + NPG_MYBANK_PSP_LIST: "BCITITMM" + NPG_BANCOMATPAY_PSP_LIST: "BCITITMM" NPG_AUTHORIZATION_REQUEST_TIMEOUT_SECONDS: "60" TRANSACTION_DOCUMENT_TTL: "600" CHECKOUT_BASE_PATH: "https://uat.checkout.pagopa.it" @@ -180,6 +183,9 @@ microservice-chart: JWT_NPG_NOTIFICATION_SECRET: npg-notification-signing-key NODE_FORWARDER_API_KEY: node-forwarder-api-key REDIRECT_URL_MAPPING: redirect-url-mapping + NPG_PAYPAL_PSP_KEYS: npg-paypal-psp-keys + NPG_BANCOMATPAY_PSP_KEYS: npg-bancomatpay-psp-keys + NPG_MYBANK_PSP_KEYS: npg-mybank-psp-keys keyvault: name: "pagopa-u-ecommerce-kv" tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d" diff --git a/pom.xml b/pom.xml index 2ad22bc53..a573ba3d5 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ 17 4.0.0 0.8.8 - 1.10.2 + 1.11.0 2.28.0 1.5.0 4.11.0 diff --git a/src/main/java/it/pagopa/transactions/client/PaymentGatewayClient.java b/src/main/java/it/pagopa/transactions/client/PaymentGatewayClient.java index e100d6f29..79415ac13 100644 --- a/src/main/java/it/pagopa/transactions/client/PaymentGatewayClient.java +++ b/src/main/java/it/pagopa/transactions/client/PaymentGatewayClient.java @@ -15,7 +15,7 @@ import it.pagopa.ecommerce.commons.generated.npg.v1.dto.StateResponseDto; import it.pagopa.ecommerce.commons.generated.npg.v1.dto.WorkflowStateDto; import it.pagopa.ecommerce.commons.utils.JwtTokenUtils; -import it.pagopa.ecommerce.commons.utils.NpgPspApiKeysConfig; +import it.pagopa.ecommerce.commons.utils.NpgApiKeyConfiguration; import it.pagopa.ecommerce.commons.utils.UniqueIdUtils; import it.pagopa.generated.ecommerce.gateway.v1.api.VposInternalApi; import it.pagopa.generated.ecommerce.gateway.v1.api.XPayInternalApi; @@ -74,9 +74,7 @@ public class PaymentGatewayClient { private final NpgSessionUrlConfig npgSessionUrlConfig; - private final NpgPspApiKeysConfig npgPspApiKeysConfig; private final UniqueIdUtils uniqueIdUtils; - private final String npgDefaultApiKey; private final SecretKey npgNotificationSigningKey; private final int npgJwtKeyValidityTime; private final SecretKey ecommerceSigningKey; @@ -96,6 +94,7 @@ public class PaymentGatewayClient { RedirectPaymentMethodId.RBPS, "SCRIGNO Internet Banking" ); + private final NpgApiKeyConfiguration npgApiKeyConfiguration; public enum RedirectPaymentMethodId { RBPR, @@ -127,16 +126,15 @@ public PaymentGatewayClient( UUIDUtils uuidUtils, ConfidentialMailUtils confidentialMailUtils, NpgClient npgClient, - NpgPspApiKeysConfig npgPspApiKeysConfig, NpgSessionUrlConfig npgSessionUrlConfig, UniqueIdUtils uniqueIdUtils, - @Value("${npg.client.apiKey}") String npgDefaultApiKey, SecretKey npgNotificationSigningKey, @Value("${npg.notification.jwt.validity.time}") int npgJwtKeyValidityTime, SecretKey ecommerceSigningKey, @Value("${payment.token.validity}") int jwtEcommerceValidityTimeInSeconds, NodeForwarderClient nodeForwarderRedirectApiClient, - Map redirectBeApiCallUriMap + Map redirectBeApiCallUriMap, + NpgApiKeyConfiguration npgApiKeyConfiguration ) { this.paymentTransactionGatewayXPayWebClient = paymentTransactionGatewayXPayWebClient; this.creditCardInternalApiClient = creditCardInternalApiClient; @@ -144,16 +142,15 @@ public PaymentGatewayClient( this.uuidUtils = uuidUtils; this.confidentialMailUtils = confidentialMailUtils; this.npgClient = npgClient; - this.npgPspApiKeysConfig = npgPspApiKeysConfig; this.npgSessionUrlConfig = npgSessionUrlConfig; this.uniqueIdUtils = uniqueIdUtils; - this.npgDefaultApiKey = npgDefaultApiKey; this.npgNotificationSigningKey = npgNotificationSigningKey; this.npgJwtKeyValidityTime = npgJwtKeyValidityTime; this.nodeForwarderRedirectApiClient = nodeForwarderRedirectApiClient; this.redirectBeApiCallUriMap = redirectBeApiCallUriMap; this.ecommerceSigningKey = ecommerceSigningKey; this.jwtEcommerceValidityTimeInSeconds = jwtEcommerceValidityTimeInSeconds; + this.npgApiKeyConfiguration = npgApiKeyConfiguration; } public Mono requestXPayAuthorization(AuthorizationRequestData authorizationData) { @@ -340,11 +337,14 @@ private Mono> requestNpgBuildSession( /* * FIXME: here we are using the same api key used for CARDS but they have to * been differentiated for each payment methods. This issue is tracked with Jira - * task CHK-2265 + * task CHK-2265 and will be fixed in CHK-2686 implementation */ - Either buildApiKey = isApmPayment - ? npgPspApiKeysConfig.get(authorizationData.pspId()) - : Either.right(npgDefaultApiKey); + Either buildApiKey = isApmPayment + ? npgApiKeyConfiguration.getApiKeyForPaymentMethod( + NpgClient.PaymentMethod.CARDS, + authorizationData.pspId() + ) + : Either.right(npgApiKeyConfiguration.getDefaultApiKey()); return buildApiKey.fold( Mono::error, apiKey -> { @@ -488,7 +488,8 @@ public Mono requestNpgCardsAuthorization( ) ); } - final var pspNpgApiKey = npgPspApiKeysConfig.get(authorizationData.pspId()); + final var pspNpgApiKey = npgApiKeyConfiguration + .getApiKeyForPaymentMethod(NpgClient.PaymentMethod.CARDS, authorizationData.pspId()); return pspNpgApiKey.fold( Mono::error, apiKey -> npgClient.confirmPayment( diff --git a/src/main/java/it/pagopa/transactions/configurations/NpgPspApiKeysConfigBuilder.java b/src/main/java/it/pagopa/transactions/configurations/NpgPspApiKeysConfigBuilder.java index b1760f818..7c8f5562b 100644 --- a/src/main/java/it/pagopa/transactions/configurations/NpgPspApiKeysConfigBuilder.java +++ b/src/main/java/it/pagopa/transactions/configurations/NpgPspApiKeysConfigBuilder.java @@ -2,8 +2,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import it.pagopa.ecommerce.commons.client.NpgClient; +import it.pagopa.ecommerce.commons.utils.NpgApiKeyConfiguration; +import it.pagopa.ecommerce.commons.utils.NpgPspApiKeysConfig; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -29,7 +30,6 @@ public class NpgPspApiKeysConfigBuilder { * @param apiKeys - the secret api keys configuration json * @return the parsed map */ - @Qualifier("npgCardsApiKeys") @Bean public it.pagopa.ecommerce.commons.utils.NpgPspApiKeysConfig npgCardsApiKeys( @Value( @@ -38,11 +38,114 @@ public it.pagopa.ecommerce.commons.utils.NpgPspApiKeysConfig npgCardsApiKeys( @Value( "${npg.authorization.cards.pspList}" ) Set pspToHandle + ) { + return parseApiKeysMap( + apiKeys, + pspToHandle, + NpgClient.PaymentMethod.CARDS + ); + } + + /** + * Return a map where valued with each psp id - api keys entries + * + * @param apiKeys - the secret api keys configuration json + * @return the parsed map + */ + @Bean + public it.pagopa.ecommerce.commons.utils.NpgPspApiKeysConfig npgPaypalApiKeys( + @Value( + "${npg.authorization.paypal.keys}" + ) String apiKeys, + @Value( + "${npg.authorization.paypal.pspList}" + ) Set pspToHandle + ) { + return parseApiKeysMap( + apiKeys, + pspToHandle, + NpgClient.PaymentMethod.PAYPAL + ); + } + + /** + * Return a map where valued with each psp id - api keys entries + * + * @param apiKeys - the secret api keys configuration json + * @return the parsed map + */ + @Bean + public it.pagopa.ecommerce.commons.utils.NpgPspApiKeysConfig npgMyBankApiKeys( + @Value( + "${npg.authorization.mybank.keys}" + ) String apiKeys, + @Value( + "${npg.authorization.mybank.pspList}" + ) Set pspToHandle + ) { + return parseApiKeysMap( + apiKeys, + pspToHandle, + NpgClient.PaymentMethod.MYBANK + ); + } + + /** + * Return a map where valued with each psp id - api keys entries + * + * @param apiKeys - the secret api keys configuration json + * @return the parsed map + */ + @Bean + public it.pagopa.ecommerce.commons.utils.NpgPspApiKeysConfig npgBancomatpayApiKeys( + @Value( + "${npg.authorization.bancomatpay.keys}" + ) String apiKeys, + @Value( + "${npg.authorization.bancomatpay.pspList}" + ) Set pspToHandle + ) { + return parseApiKeysMap( + apiKeys, + pspToHandle, + NpgClient.PaymentMethod.BANCOMATPAY + ); + } + + @Bean + public NpgApiKeyConfiguration npgApiKeyConfiguration( + NpgPspApiKeysConfig npgCardsApiKeys, + NpgPspApiKeysConfig npgBancomatpayApiKeys, + NpgPspApiKeysConfig npgMyBankApiKeys, + NpgPspApiKeysConfig npgPaypalApiKeys, + @Value("${npg.client.apiKey}") String defaultApiKey + ) { + return new NpgApiKeyConfiguration.Builder() + .setDefaultApiKey(defaultApiKey) + .withMethodPspMapping(NpgClient.PaymentMethod.CARDS, npgCardsApiKeys) + .withMethodPspMapping(NpgClient.PaymentMethod.BANCOMATPAY, npgBancomatpayApiKeys) + .withMethodPspMapping(NpgClient.PaymentMethod.MYBANK, npgMyBankApiKeys) + .withMethodPspMapping(NpgClient.PaymentMethod.PAYPAL, npgPaypalApiKeys) + .build(); + } + + /** + * Return a map where valued with each psp id - api keys entries + * + * @param apiKeys - the secret api keys configuration json + * @return the parsed map + */ + private it.pagopa.ecommerce.commons.utils.NpgPspApiKeysConfig parseApiKeysMap( + + String apiKeys, + Set pspToHandle, + NpgClient.PaymentMethod paymentMethod + ) { return it.pagopa.ecommerce.commons.utils.NpgPspApiKeysConfig.parseApiKeyConfiguration( apiKeys, pspToHandle, - NpgClient.PaymentMethod.CARDS, + paymentMethod, objectMapper ) .fold(exception -> { diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 0f0cd009f..8d542a3d4 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -80,6 +80,12 @@ npg.connectionTimeout=${NPG_CONNECTION_TIMEOUT} npg.client.apiKey=${NPG_API_KEY} npg.authorization.cards.keys=${NPG_CARDS_PSP_KEYS} npg.authorization.cards.pspList=${NPG_CARDS_PSP_LIST} +npg.authorization.paypal.keys=${NPG_PAYPAL_PSP_KEYS} +npg.authorization.paypal.pspList=${NPG_PAYPAL_PSP_LIST} +npg.authorization.bancomatpay.keys=${NPG_BANCOMATPAY_PSP_KEYS} +npg.authorization.bancomatpay.pspList=${NPG_BANCOMATPAY_PSP_LIST} +npg.authorization.mybank.keys=${NPG_MYBANK_PSP_KEYS} +npg.authorization.mybank.pspList=${NPG_MYBANK_PSP_LIST} npg.authorization.request.timeout.seconds=${NPG_AUTHORIZATION_REQUEST_TIMEOUT_SECONDS} ecommerce.event.version=${ECOMMERCE_EVENT_VERSION} diff --git a/src/test/java/it/pagopa/transactions/client/PaymentGatewayClientTest.java b/src/test/java/it/pagopa/transactions/client/PaymentGatewayClientTest.java index 411b16e06..e9aadb68f 100644 --- a/src/test/java/it/pagopa/transactions/client/PaymentGatewayClientTest.java +++ b/src/test/java/it/pagopa/transactions/client/PaymentGatewayClientTest.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import io.vavr.control.Either; import it.pagopa.ecommerce.commons.client.NodeForwarderClient; import it.pagopa.ecommerce.commons.client.NpgClient; import it.pagopa.ecommerce.commons.documents.v1.Transaction; @@ -14,6 +15,7 @@ import it.pagopa.ecommerce.commons.generated.npg.v1.dto.FieldsDto; import it.pagopa.ecommerce.commons.generated.npg.v1.dto.StateResponseDto; import it.pagopa.ecommerce.commons.generated.npg.v1.dto.WorkflowStateDto; +import it.pagopa.ecommerce.commons.utils.NpgApiKeyConfiguration; import it.pagopa.ecommerce.commons.utils.NpgPspApiKeysConfig; import it.pagopa.ecommerce.commons.utils.UniqueIdUtils; import it.pagopa.ecommerce.commons.v1.TransactionTestUtils; @@ -135,6 +137,8 @@ class PaymentGatewayClientTest { Collectors.toMap("pspId-%s"::formatted, p -> URI.create("http://redirect/%s".formatted(p))) ); + private final NpgApiKeyConfiguration npgApiKeyHandler = Mockito.mock(NpgApiKeyConfiguration.class); + @BeforeEach private void init() { client = new PaymentGatewayClient( @@ -144,16 +148,16 @@ private void init() { mockUuidUtils, confidentialMailUtils, npgClient, - npgPspApiKeysConfig, sessionUrlConfig, uniqueIdUtils, - npgDefaultApiKey, jwtSecretKey, TOKEN_VALIDITY_TIME_SECONDS, jwtSecretKey, TOKEN_VALIDITY_TIME_SECONDS, nodeForwarderClient, - redirectBeApiCallUriMap + redirectBeApiCallUriMap, + npgApiKeyHandler + ); Hooks.onOperatorDebug(); @@ -463,6 +467,7 @@ void shouldReturnAuthorizationResponseForCardsWithNpg() throws Exception { /* preconditions */ Mockito.when(npgClient.confirmPayment(any(), any(), any(), any())).thenReturn(Mono.just(ngpStateResponse)); + Mockito.when(npgApiKeyHandler.getApiKeyForPaymentMethod(any(), any())).thenReturn(Either.right("pspKey1")); /* test */ StepVerifier.create(client.requestNpgCardsAuthorization(authorizationData, UUID.randomUUID().toString())) .expectNext(ngpStateResponse) @@ -478,6 +483,7 @@ void shouldReturnAuthorizationResponseForCardsWithNpg() throws Exception { ); verify(npgClient, times(1)) .confirmPayment(any(), eq(expectedSessionId), eq(expectedGranTotalAmount), eq(expectedApiKey)); + verify(npgApiKeyHandler, times(1)).getApiKeyForPaymentMethod(NpgClient.PaymentMethod.CARDS, "pspId1"); } @Test @@ -546,6 +552,8 @@ void shouldThrowAlreadyProcessedOn401ForCardsWithNpg() throws Exception { ) ) ); + + Mockito.when(npgApiKeyHandler.getApiKeyForPaymentMethod(any(), any())).thenReturn(Either.right("pspKey1")); /* test */ StepVerifier.create(client.requestNpgCardsAuthorization(authorizationData, UUID.randomUUID().toString())) @@ -555,6 +563,7 @@ void shouldThrowAlreadyProcessedOn401ForCardsWithNpg() throws Exception { .equals(transaction.getTransactionId()) ) .verify(); + verify(npgApiKeyHandler, times(1)).getApiKeyForPaymentMethod(NpgClient.PaymentMethod.CARDS, "pspId1"); } @Test @@ -623,12 +632,15 @@ void shouldThrowGatewayTimeoutExceptionForCardsWithNpg() throws Exception { ) ) ); + + Mockito.when(npgApiKeyHandler.getApiKeyForPaymentMethod(any(), any())).thenReturn(Either.right("pspKey1")); /* test */ StepVerifier.create(client.requestNpgCardsAuthorization(authorizationData, UUID.randomUUID().toString())) .expectErrorMatches( error -> error instanceof BadGatewayException ) .verify(); + verify(npgApiKeyHandler, times(1)).getApiKeyForPaymentMethod(NpgClient.PaymentMethod.CARDS, "pspId1"); } @Test @@ -697,12 +709,15 @@ void shouldThrowInternalServerErrorExceptionForCardsWithNpg() throws Exception { ) ) ); + + Mockito.when(npgApiKeyHandler.getApiKeyForPaymentMethod(any(), any())).thenReturn(Either.right("pspKey1")); /* test */ StepVerifier.create(client.requestNpgCardsAuthorization(authorizationData, UUID.randomUUID().toString())) .expectErrorMatches( error -> error instanceof BadGatewayException ) .verify(); + verify(npgApiKeyHandler, times(1)).getApiKeyForPaymentMethod(NpgClient.PaymentMethod.CARDS, "pspId1"); } @Test @@ -1392,6 +1407,8 @@ void shouldReturnBuildSessionResponseForWalletWithNpgWithCards() { ) ).thenReturn(Mono.just(npgBuildSessionResponse)); + Mockito.when(npgApiKeyHandler.getDefaultApiKey()).thenReturn(npgDefaultApiKey); + Tuple2 responseRequestNpgBuildSession = Tuples.of(orderId, npgBuildSessionResponse); /* test */ StepVerifier.create(client.requestNpgBuildSession(authorizationData, correlationId, true)) @@ -1459,6 +1476,7 @@ void shouldReturnBuildSessionResponseForWalletWithNpgWithCards() { ); verify(npgClient, times(0)) .buildFormForPayment(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); + verify(npgApiKeyHandler, times(1)).getDefaultApiKey(); } @Test @@ -1805,6 +1823,8 @@ void shouldReturnBadGatewayExceptionFromBuildSessionForWalletWithNpg(FieldsDto n ) ).thenReturn(Mono.just(npgBuildSessionResponse)); + Mockito.when(npgApiKeyHandler.getDefaultApiKey()).thenReturn(npgDefaultApiKey); + StepVerifier.create(client.requestNpgBuildSession(authorizationData, correlationId, true)) .expectErrorMatches(error -> error instanceof BadGatewayException) .verify(); @@ -1870,6 +1890,7 @@ void shouldReturnBadGatewayExceptionFromBuildSessionForWalletWithNpg(FieldsDto n ); verify(npgClient, times(0)) .buildFormForPayment(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); + verify(npgApiKeyHandler, times(1)).getDefaultApiKey(); } private static Stream buildSessionInvalidBodyResponse() { @@ -1970,6 +1991,8 @@ void shouldReturnBuildSessionResponseForWalletWithNpgForWalletApmMethod() { ) ).thenReturn(Mono.just(npgBuildSessionResponse)); + Mockito.when(npgApiKeyHandler.getApiKeyForPaymentMethod(any(), any())).thenReturn(Either.right("pspKey1")); + Tuple2 responseRequestNpgBuildSession = Tuples.of(orderId, npgBuildSessionResponse); /* test */ StepVerifier.create(client.requestNpgBuildApmPayment(authorizationData, correlationId, true)) @@ -2038,6 +2061,7 @@ void shouldReturnBuildSessionResponseForWalletWithNpgForWalletApmMethod() { ); verify(npgClient, times(0)) .buildForm(any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); + verify(npgApiKeyHandler, times(1)).getApiKeyForPaymentMethod(NpgClient.PaymentMethod.CARDS, "pspId1"); } @Test @@ -2161,6 +2185,8 @@ void shouldThrowErrorForWalletWithNpgForGenericApmMethodAndMissingKey() { ) ).thenReturn(Mono.just(npgBuildSessionResponse)); + Mockito.when(npgApiKeyHandler.getApiKeyForPaymentMethod(any(), any())) + .thenReturn(Either.left(new NpgApiKeyMissingPspRequestedException("pspId2", Set.of()))); /* test */ StepVerifier.create(client.requestNpgBuildApmPayment(authorizationData, correlationId, true)) .expectError(NpgApiKeyMissingPspRequestedException.class) @@ -2170,6 +2196,7 @@ void shouldThrowErrorForWalletWithNpgForGenericApmMethodAndMissingKey() { .buildFormForPayment(any(), any(), any(), any(), any(), eq(orderId), any(), any(), any(), any(), any()); verify(npgClient, times(0)) .buildForm(any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); + verify(npgApiKeyHandler, times(1)).getApiKeyForPaymentMethod(NpgClient.PaymentMethod.CARDS, "pspId2"); } @Test @@ -2245,6 +2272,7 @@ void shouldReturnBuildSessionResponseForWalletWithNpgForApmMethod() { eq(totalAmount) ) ).thenReturn(Mono.just(npgBuildSessionResponse)); + Mockito.when(npgApiKeyHandler.getApiKeyForPaymentMethod(any(), any())).thenReturn(Either.right("pspKey1")); Tuple2 responseRequestNpgBuildSession = Tuples.of(orderId, npgBuildSessionResponse); /* test */ @@ -2311,6 +2339,7 @@ void shouldReturnBuildSessionResponseForWalletWithNpgForApmMethod() { ); verify(npgClient, times(0)) .buildForm(any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); + verify(npgApiKeyHandler, times(1)).getApiKeyForPaymentMethod(NpgClient.PaymentMethod.CARDS, "pspId1"); } private static Stream redirectRetrieveUrlPaymentMethodsTestMethodSource() { @@ -2683,16 +2712,15 @@ void shouldReturnErrorDuringRedirectPaymentTransactionForInvalidPspURL() { mockUuidUtils, confidentialMailUtils, npgClient, - npgPspApiKeysConfig, sessionUrlConfig, uniqueIdUtils, - npgDefaultApiKey, jwtSecretKey, TOKEN_VALIDITY_TIME_SECONDS, jwtSecretKey, TOKEN_VALIDITY_TIME_SECONDS, nodeForwarderClient, - redirectUrlMapping + redirectUrlMapping, + npgApiKeyHandler ); /* test */ StepVerifier.create( diff --git a/src/test/java/it/pagopa/transactions/configurations/NpgPspApiKeysConfigTest.java b/src/test/java/it/pagopa/transactions/configurations/NpgPspApiKeysConfigTest.java index ba1b3f84e..5a72f6ed2 100644 --- a/src/test/java/it/pagopa/transactions/configurations/NpgPspApiKeysConfigTest.java +++ b/src/test/java/it/pagopa/transactions/configurations/NpgPspApiKeysConfigTest.java @@ -1,12 +1,18 @@ package it.pagopa.transactions.configurations; +import io.vavr.control.Either; +import it.pagopa.ecommerce.commons.client.NpgClient; import it.pagopa.ecommerce.commons.exceptions.NpgApiKeyConfigurationException; +import it.pagopa.ecommerce.commons.utils.NpgApiKeyConfiguration; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import java.util.HashSet; import java.util.Set; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; @@ -47,7 +53,7 @@ void shouldThrowErrorWhenRetrievingUnknownPspApiKey() { var apiKey = pspConfiguration.get("unknown"); assertTrue(apiKey.isLeft()); assertEquals( - "Requested API key for PSP unknown. Available PSPs: [psp1, psp2, psp3]", + "Requested API key for PSP: [unknown]. Available PSPs: [psp1, psp2, psp3]", apiKey.getLeft().getMessage() ); } @@ -78,4 +84,106 @@ void shouldThrowExceptionForMissingPspId() { exception.getMessage() ); } + + private static Stream npgApiKeyHandlerTestMethodSource() { + return Stream.of( + Arguments.of(NpgClient.PaymentMethod.CARDS, "psp1"), + Arguments.of(NpgClient.PaymentMethod.CARDS, "psp2"), + Arguments.of(NpgClient.PaymentMethod.CARDS, "psp3"), + Arguments.of(NpgClient.PaymentMethod.PAYPAL, "psp1"), + Arguments.of(NpgClient.PaymentMethod.PAYPAL, "psp2"), + Arguments.of(NpgClient.PaymentMethod.PAYPAL, "psp3"), + Arguments.of(NpgClient.PaymentMethod.MYBANK, "psp1"), + Arguments.of(NpgClient.PaymentMethod.PAYPAL, "psp2"), + Arguments.of(NpgClient.PaymentMethod.PAYPAL, "psp3"), + Arguments.of(NpgClient.PaymentMethod.BANCOMATPAY, "psp1"), + Arguments.of(NpgClient.PaymentMethod.BANCOMATPAY, "psp2"), + Arguments.of(NpgClient.PaymentMethod.BANCOMATPAY, "psp3") + ); + } + + @ParameterizedTest + @MethodSource("npgApiKeyHandlerTestMethodSource") + void shouldBuildNpgApiKeyHandlerSuccessfully( + NpgClient.PaymentMethod paymentMethod, + String pspId + ) { + // pre-requisites + String pspConfigurationJson = """ + { + "psp1" : "%1$s-key-psp1", + "psp2" : "%1$s-key-psp2", + "psp3" : "%1$s-key-psp3" + } + """; + String expectedDefaultApiKey = "defaultApiKey"; + String expectedPspApiKey = "%s-key-%s".formatted(paymentMethod, pspId); + NpgApiKeyConfiguration npgApiKeyHandler = npgPspApiKeysConfig.npgApiKeyConfiguration( + npgPspApiKeysConfig.npgCardsApiKeys( + pspConfigurationJson.formatted(NpgClient.PaymentMethod.CARDS), + pspToHandle + ), + npgPspApiKeysConfig.npgCardsApiKeys( + pspConfigurationJson.formatted(NpgClient.PaymentMethod.BANCOMATPAY), + pspToHandle + ), + npgPspApiKeysConfig.npgCardsApiKeys( + pspConfigurationJson.formatted(NpgClient.PaymentMethod.MYBANK), + pspToHandle + ), + npgPspApiKeysConfig.npgCardsApiKeys( + pspConfigurationJson.formatted(NpgClient.PaymentMethod.PAYPAL), + pspToHandle + ), + expectedDefaultApiKey + ); + Either apiKey = npgApiKeyHandler + .getApiKeyForPaymentMethod(paymentMethod, pspId); + String defaultNpgApiKey = npgApiKeyHandler.getDefaultApiKey(); + + assertEquals(expectedDefaultApiKey, defaultNpgApiKey); + + assertEquals(expectedPspApiKey, apiKey.get()); + + } + + @ParameterizedTest + @MethodSource("npgApiKeyHandlerTestMethodSource") + void shouldReturnErrorForMissingPspApiKey(NpgClient.PaymentMethod paymentMethod) { + // pre-requisites + String pspConfigurationJson = """ + { + "psp1" : "%1$s-key-psp1", + "psp2" : "%1$s-key-psp2", + "psp3" : "%1$s-key-psp3" + } + """; + NpgApiKeyConfiguration npgApiKeyHandler = npgPspApiKeysConfig.npgApiKeyConfiguration( + npgPspApiKeysConfig.npgCardsApiKeys( + pspConfigurationJson.formatted(NpgClient.PaymentMethod.CARDS), + pspToHandle + ), + npgPspApiKeysConfig.npgCardsApiKeys( + pspConfigurationJson.formatted(NpgClient.PaymentMethod.BANCOMATPAY), + pspToHandle + ), + npgPspApiKeysConfig.npgCardsApiKeys( + pspConfigurationJson.formatted(NpgClient.PaymentMethod.MYBANK), + pspToHandle + ), + npgPspApiKeysConfig.npgCardsApiKeys( + pspConfigurationJson.formatted(NpgClient.PaymentMethod.PAYPAL), + pspToHandle + ), + "defaultApiKey" + ); + Either apiKey = npgApiKeyHandler + .getApiKeyForPaymentMethod(paymentMethod, "missingPspId"); + assertEquals( + "Cannot retrieve api key for payment method: [%s]. Cause: Requested API key for PSP: [missingPspId]. Available PSPs: [psp1, psp2, psp3]" + .formatted(paymentMethod), + apiKey.getLeft().getMessage() + ); + + } } diff --git a/src/test/resources/application-tests.properties b/src/test/resources/application-tests.properties index f1297f677..ba3666ce4 100644 --- a/src/test/resources/application-tests.properties +++ b/src/test/resources/application-tests.properties @@ -67,8 +67,14 @@ npg.uri=http://localhost/npg npg.readTimeout=10000 npg.connectionTimeout=10000 npg.client.apiKey=npg_key -npg.authorization.cards.keys={"psp1":"key1","psp2":"key2"} +npg.authorization.cards.keys={"psp1":"cards-key1","psp2":"cards-key2"} npg.authorization.cards.pspList=psp1,psp2 +npg.authorization.paypal.keys={"psp1":"paypal-key1","psp2":"paypal-key2"} +npg.authorization.paypal.pspList=psp1,psp2 +npg.authorization.bancomatpay.keys={"psp1":"bancomatpay-key1","psp2":"bancomatpay-key2"} +npg.authorization.bancomatpay.pspList=psp1,psp2 +npg.authorization.mybank.keys={"psp1":"mybank-key1","psp2":"mybank-key2"} +npg.authorization.mybank.pspList=psp1,psp2 npg.authorization.request.timeout.seconds=600 ecommerce.event.version=V2 transactionDocument.ttl=1000