package de.adorsys.ledgers.oba.service.impl.service; import de.adorsys.ledgers.middleware.api.domain.payment.PaymentTO; import de.adorsys.ledgers.middleware.api.domain.payment.PaymentTypeTO; import de.adorsys.ledgers.middleware.api.domain.payment.TransactionStatusTO; import de.adorsys.ledgers.middleware.api.domain.sca.SCAPaymentResponseTO; import de.adorsys.ledgers.middleware.api.domain.sca.ScaStatusTO; import de.adorsys.ledgers.middleware.api.domain.um.BearerTokenTO; import de.adorsys.ledgers.middleware.api.service.TokenStorageService; import de.adorsys.ledgers.middleware.client.mappers.PaymentMapperTO; import de.adorsys.ledgers.middleware.client.rest.AuthRequestInterceptor; import de.adorsys.ledgers.middleware.client.rest.OauthRestClient; import de.adorsys.ledgers.middleware.client.rest.PaymentRestClient; import de.adorsys.ledgers.oba.service.api.domain.ConsentReference; import de.adorsys.ledgers.oba.service.api.domain.ConsentType; import de.adorsys.ledgers.oba.service.api.domain.PaymentAuthorizeResponse; import de.adorsys.ledgers.oba.service.api.domain.PaymentWorkflow; import de.adorsys.ledgers.oba.service.api.domain.exception.AuthorizationException; import de.adorsys.ledgers.oba.service.api.domain.exception.ObaException; import de.adorsys.ledgers.oba.service.api.service.AuthorizationService; import de.adorsys.ledgers.oba.service.api.service.ConsentReferencePolicy; import de.adorsys.psd2.consent.api.pis.CmsCommonPayment; import de.adorsys.psd2.consent.api.pis.CmsPaymentResponse; import de.adorsys.psd2.consent.psu.api.CmsPsuAuthorisation; import de.adorsys.psd2.consent.psu.api.CmsPsuPisService; import de.adorsys.psd2.xs2a.core.exception.AuthorisationIsExpiredException; import de.adorsys.psd2.xs2a.core.exception.RedirectUrlIsExpiredException; import de.adorsys.psd2.xs2a.core.pis.TransactionStatus; import de.adorsys.psd2.xs2a.core.profile.PaymentType; import de.adorsys.psd2.xs2a.core.sca.ScaStatus; import org.adorsys.ledgers.consent.xs2a.rest.client.AspspConsentDataClient; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.ResponseEntity; import java.io.IOException; import java.util.Optional; import static de.adorsys.ledgers.middleware.api.domain.payment.TransactionStatusTO.*; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class CommonPaymentServiceImplTest { private static final String ENCRYPTED_ID = "ENC_123"; private static final String AUTH_ID = "AUTH_1"; private static final String METHOD_ID = "SCA_1"; private static final String COOKIE = "COOKIE"; private static final String PSU_ID = "PSU_1"; private static final String PAYMENT_ID = "PAYMENT_1"; private static final String OK_REDIRECT_URI = "www.ok.ua"; private static final String NOK_REDIRECT_URI = "www.nok.ua"; private static final String AUTH_CODE = "123456"; @InjectMocks CommonPaymentServiceImpl service; @Mock private ConsentReferencePolicy referencePolicy; @Mock private AuthRequestInterceptor authInterceptor; @Mock private CmsPsuPisService cmsPsuPisService; @Mock private PaymentRestClient paymentRestClient; @Mock private AspspConsentDataClient aspspConsentDataClient; @Mock private TokenStorageService tokenStorageService; @Mock private PaymentMapperTO paymentMapper; @Mock private OauthRestClient oauthRestClient; @Mock private AuthorizationService authService; @Test void selectScaForPayment() throws RedirectUrlIsExpiredException { // Given when(paymentMapper.toAbstractPayment(anyString(), anyString(), anyString())).thenReturn(getPaymentTO(ACCP)); when(referencePolicy.fromRequest(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(getConsentReference()); when(cmsPsuPisService.checkRedirectAndGetPayment(anyString(), anyString())).thenReturn(getCmsPaymentResponse()); when(paymentRestClient.selectMethod(anyString(), anyString(), anyString())).thenReturn(ResponseEntity.ok(getSelectMethodResponse(TransactionStatus.ACCP.name()))); // When PaymentWorkflow result = service.selectScaForPayment(ENCRYPTED_ID, AUTH_ID, METHOD_ID, COOKIE, false, PSU_ID, new BearerTokenTO()); // Then assertThat(result).isEqualToComparingFieldByFieldRecursively(getExpectedWorkflow(TransactionStatus.ACCP.name(), TransactionStatus.ACCP.name())); } @Test void identifyPayment() throws RedirectUrlIsExpiredException { // Given when(referencePolicy.fromRequest(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(getConsentReference()); when(cmsPsuPisService.checkRedirectAndGetPayment(anyString(), anyString())).thenReturn(getCmsPaymentResponse()); when(paymentMapper.toAbstractPayment(anyString(), anyString(), anyString())).thenReturn(getPaymentTO(ACCP)); // When PaymentWorkflow result = service.identifyPayment(ENCRYPTED_ID, AUTH_ID, false, COOKIE, PSU_ID, new BearerTokenTO()); // Then assertThat(result).isEqualToComparingFieldByFieldRecursively(getExpectedWorkflow(null, TransactionStatus.ACCP.name())); } @Test void identifyPayment_fail() throws RedirectUrlIsExpiredException { // Given when(referencePolicy.fromRequest(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(getConsentReference()); when(cmsPsuPisService.checkRedirectAndGetPayment(anyString(), anyString())).thenThrow(RedirectUrlIsExpiredException.class); // Then assertThrows(ObaException.class, () -> service.identifyPayment(ENCRYPTED_ID, AUTH_ID, false, COOKIE, PSU_ID, new BearerTokenTO())); } @Test void updateAspspConsentData_exception() throws IOException { // Given when(tokenStorageService.toBase64String(any())).thenThrow(IOException.class); // Then assertThrows(AuthorizationException.class, () -> service.updateAspspConsentData(getExpectedWorkflow("RJCT", "RJCT"))); } @Test void resolveRedirectUrl() throws RedirectUrlIsExpiredException { // Given when(referencePolicy.fromRequest(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(getConsentReference()); when(cmsPsuPisService.checkRedirectAndGetPayment(anyString(), anyString())).thenReturn(getCmsPaymentResponse()); when(paymentMapper.toAbstractPayment(anyString(), anyString(), anyString())).thenReturn(getPaymentTO(ACCP)); when(cmsPsuPisService.getAuthorisationByAuthorisationId(anyString(), anyString())).thenReturn(geCmsPsuAuth(ScaStatus.FINALISED)); when(authService.resolveAuthConfirmationCodeRedirectUri(anyString(), anyString())).thenReturn("www.ok.ua"); // When String result = service.resolveRedirectUrl(ENCRYPTED_ID, AUTH_ID, COOKIE, false, PSU_ID, new BearerTokenTO(), ""); // Then assertEquals(OK_REDIRECT_URI, result); } @Test void resolveRedirectUrl_fail() throws RedirectUrlIsExpiredException { // Given when(referencePolicy.fromRequest(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(getConsentReference()); when(cmsPsuPisService.checkRedirectAndGetPayment(anyString(), anyString())).thenReturn(getCmsPaymentResponse()); when(paymentMapper.toAbstractPayment(anyString(), anyString(), anyString())).thenReturn(getPaymentTO(ACCP)); when(cmsPsuPisService.getAuthorisationByAuthorisationId(anyString(), anyString())).thenReturn(Optional.empty()); when(authService.resolveAuthConfirmationCodeRedirectUri(anyString(), anyString())).thenReturn("www.ok.ua"); // Then assertThrows(ObaException.class, () -> service.resolveRedirectUrl(ENCRYPTED_ID, AUTH_ID, COOKIE, false, PSU_ID, new BearerTokenTO(), "")); } @Test void resolveRedirectUrl_not_final_status() throws RedirectUrlIsExpiredException { // Given when(referencePolicy.fromRequest(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(getConsentReference()); when(cmsPsuPisService.checkRedirectAndGetPayment(anyString(), anyString())).thenReturn(getCmsPaymentResponse()); when(paymentMapper.toAbstractPayment(anyString(), anyString(), anyString())).thenReturn(getPaymentTO(ACCP)); when(cmsPsuPisService.getAuthorisationByAuthorisationId(anyString(), anyString())).thenReturn(geCmsPsuAuth(ScaStatus.SCAMETHODSELECTED)); when(authService.resolveAuthConfirmationCodeRedirectUri(anyString(), anyString())).thenReturn("www.ok.ua"); // When String result = service.resolveRedirectUrl(ENCRYPTED_ID, AUTH_ID, COOKIE, false, PSU_ID, new BearerTokenTO(), ""); // Then assertEquals(NOK_REDIRECT_URI, result); } @Test void initiatePayment() { // Given when(paymentRestClient.initiatePayment(any(), any())).thenReturn(ResponseEntity.ok(getSelectMethodResponse(TransactionStatus.ACCP.name()))); // When PaymentWorkflow result = service.initiatePayment(getExpectedWorkflow(RCVD.name(), null), PSU_ID); // Then assertThat(result).isEqualToComparingFieldByFieldRecursively(getExpectedWorkflow(TransactionStatus.ACCP.name(), TransactionStatus.ACCP.name())); } @Test void initiatePayment_fail() throws AuthorisationIsExpiredException { // Given when(paymentRestClient.initiatePayment(any(), any())).thenReturn(ResponseEntity.ok(getSelectMethodResponse(TransactionStatus.ACCP.name()))); when(cmsPsuPisService.updateAuthorisationStatus(any(), anyString(), anyString(), any(), anyString(), any())).thenThrow(AuthorisationIsExpiredException.class); // Then assertThrows(ObaException.class, () -> service.initiatePayment(getExpectedWorkflow(RCVD.name(), null), PSU_ID)); } @Test void initiateCancelPayment() { // Given when(paymentRestClient.initiatePmtCancellation(anyString())).thenReturn(ResponseEntity.ok(getSelectMethodResponse(TransactionStatus.ACCP.name()))); // When PaymentWorkflow result = service.initiateCancelPayment(getExpectedWorkflow(RCVD.name(), null), PSU_ID); // Then assertThat(result).isEqualToComparingFieldByFieldRecursively(getExpectedWorkflow(TransactionStatus.ACCP.name(), TransactionStatus.ACCP.name())); } @Test void authorizePayment() { // Given when(paymentRestClient.authorizePayment(anyString(), anyString(), anyString())).thenReturn(ResponseEntity.ok(getSelectMethodResponse(ACSC.name()))); // When PaymentWorkflow result = service.authorizePayment(getExpectedWorkflow(RCVD.name(), null), PSU_ID, AUTH_CODE); // Then assertThat(result).isEqualToComparingFieldByFieldRecursively(getExpectedWorkflow(ACSC.name(), ACSC.name())); } @Test void authorizeCancelPayment() { // Given when(paymentRestClient.authorizeCancelPayment(anyString(), anyString(), anyString())).thenReturn(ResponseEntity.ok(getSelectMethodResponse(ACSC.name()))); // When PaymentWorkflow result = service.authorizeCancelPayment(getExpectedWorkflow(RCVD.name(), null), PSU_ID, AUTH_CODE); // Then assertThat(result).isEqualToComparingFieldByFieldRecursively(getExpectedWorkflow(ACSC.name(), CANC.name())); } private PaymentWorkflow getExpectedWorkflow(String scaResponseStatus, String status) { PaymentWorkflow workflow = new PaymentWorkflow(getCmsPaymentResponse().get(), getConsentReference()); workflow.setScaResponse(getSelectMethodResponse(scaResponseStatus)); workflow.setAuthResponse(getAuthResponse(ACCP)); workflow.setPaymentStatus(status); Optional.ofNullable(status).map(TransactionStatusTO::valueOf).map(this::getAuthResponse).ifPresent(workflow::setAuthResponse); return workflow; } private PaymentAuthorizeResponse getAuthResponse(TransactionStatusTO status) { return new PaymentAuthorizeResponse(getPaymentTO(status)); } private SCAPaymentResponseTO getSelectMethodResponse(String status) { SCAPaymentResponseTO response = new SCAPaymentResponseTO(); Optional.ofNullable(status).map(TransactionStatusTO::valueOf).ifPresent(response::setTransactionStatus); response.setScaStatus(ScaStatusTO.SCAMETHODSELECTED); response.setBearerToken(new BearerTokenTO()); response.setAuthorisationId(AUTH_ID); return response; } private PaymentTO getPaymentTO(TransactionStatusTO status) { PaymentTO payment = new PaymentTO(); payment.setPaymentId(PAYMENT_ID); payment.setPaymentType(PaymentTypeTO.SINGLE); payment.setPaymentProduct("sepa"); payment.setTransactionStatus(status); return payment; } private Optional<CmsPaymentResponse> getCmsPaymentResponse() { return Optional.of(new CmsPaymentResponse(getCommonPayment(), AUTH_ID, OK_REDIRECT_URI, NOK_REDIRECT_URI)); } private CmsCommonPayment getCommonPayment() { CmsCommonPayment payment = new CmsCommonPayment("sepa"); payment.setPaymentId(PAYMENT_ID); payment.setPaymentData(getPaymentString()); payment.setPaymentType(PaymentType.SINGLE); payment.setTransactionStatus(TransactionStatus.ACCP); return payment; } private ConsentReference getConsentReference() { ConsentReference cr = new ConsentReference(); cr.setConsentType(ConsentType.AIS); cr.setRedirectId(AUTH_ID); cr.setEncryptedConsentId(ENCRYPTED_ID); cr.setAuthorizationId(AUTH_ID); cr.setCookieString(null); return cr; } private byte[] getPaymentString() { String s = "{\n" + " \"endToEndIdentification\": \"WBG-123456789\",\n" + " \"requestedExecutionDate\": \"2019-12-12\",\n" + " \"debtorAccount\": {\n" + " \"currency\": \"USD\",\n" + " \"iban\": \"DE40500105178578796457\"\n" + " },\n" + " \"instructedAmount\": {\n" + " \"currency\": \"CHF\",\n" + " \"amount\": \"1.00\"\n" + " },\n" + " \"creditorAccount\": {\n" + " \"currency\": \"EUR\",\n" + " \"iban\": \"DE40500105178578796457\"\n" + " },\n" + " \"creditorAgent\" : \"AAAADEBBXXX\",\n" + " \"creditorName\": \"WBG\",\n" + " \"creditorAddress\": {\n" + " \"buildingNumber\": \"56\",\n" + " \"townName\": \"Nürnberg\",\n" + " \"country\": \"DE\",\n" + " \"postCode\": \"90543\",\n" + " \"streetName\": \"WBG Straße\"\n" + " },\n" + " \"remittanceInformationUnstructured\": \"Ref. Number WBG-1222\"\n" + "}\n"; return s.getBytes(); } private Optional<CmsPsuAuthorisation> geCmsPsuAuth(ScaStatus status) { CmsPsuAuthorisation auth = new CmsPsuAuthorisation(); auth.setScaStatus(status); return Optional.of(auth); } }