diff --git a/src/main/java/com/unzer/payment/Basket.java b/src/main/java/com/unzer/payment/Basket.java index 889ecd78..47dfec0a 100644 --- a/src/main/java/com/unzer/payment/Basket.java +++ b/src/main/java/com/unzer/payment/Basket.java @@ -1,11 +1,14 @@ package com.unzer.payment; +import lombok.EqualsAndHashCode; + import java.math.BigDecimal; import java.util.ArrayList; import java.util.Currency; import java.util.List; import java.util.Objects; +@EqualsAndHashCode(callSuper = false) public class Basket extends BaseResource implements Resource { private String id; @@ -147,6 +150,7 @@ public Basket setAmountTotalGross(BigDecimal amountTotalGross) { } @Override + @EqualsAndHashCode.Include protected String getResourceUrl() { return Objects.isNull(this.totalValueGross) ? "/v1/baskets/" diff --git a/src/main/java/com/unzer/payment/BasketV3.java b/src/main/java/com/unzer/payment/BasketV3.java new file mode 100644 index 00000000..becf565e --- /dev/null +++ b/src/main/java/com/unzer/payment/BasketV3.java @@ -0,0 +1,8 @@ +package com.unzer.payment; + +public class BasketV3 extends Basket { + @Override + protected String getResourceUrl() { + return "/v3/baskets/"; + } +} diff --git a/src/main/java/com/unzer/payment/service/PaymentService.java b/src/main/java/com/unzer/payment/service/PaymentService.java index 15ebbf4c..29f64956 100644 --- a/src/main/java/com/unzer/payment/service/PaymentService.java +++ b/src/main/java/com/unzer/payment/service/PaymentService.java @@ -3,6 +3,7 @@ import com.unzer.payment.Authorization; import com.unzer.payment.BasePayment; import com.unzer.payment.Basket; +import com.unzer.payment.BasketV3; import com.unzer.payment.Cancel; import com.unzer.payment.Charge; import com.unzer.payment.Chargeback; @@ -326,15 +327,11 @@ public T updatePaymentType(T paymentType) public Customer createCustomer(Customer customer) throws HttpCommunicationException { ApiConfig apiConfig = customer instanceof CustomerV2 ? ApiConfigs.PAYMENT_API_BEARER_AUTH : ApiConfigs.PAYMENT_API; - String authentication = unzer.getPrivateKey(); - if (apiConfig.getAuthMethod() == ApiConfig.AuthMethod.BEARER) { - unzer.prepareJwtToken(); - authentication = unzer.getJwtToken(); - } + String response = restCommunication.httpPost( urlUtil.getUrl(customer), - authentication, + getAuthentication(apiConfig), apiToSdkMapper.map(customer), apiConfig ); @@ -370,11 +367,7 @@ private static boolean isUUIDResource(String customerId) { public Customer updateCustomer(String id, Customer customer) throws HttpCommunicationException { ApiConfig apiConfig = customer instanceof CustomerV2 ? ApiConfigs.PAYMENT_API_BEARER_AUTH : ApiConfigs.PAYMENT_API; - String authentication = unzer.getPrivateKey(); - if (apiConfig.getAuthMethod() == ApiConfig.AuthMethod.BEARER) { - unzer.prepareJwtToken(); - authentication = unzer.getJwtToken(); - } + String authentication = getAuthentication(apiConfig); customer.setId(id); restCommunication.httpPut( urlUtil.getUrl(customer), @@ -386,27 +379,30 @@ public Customer updateCustomer(String id, Customer customer) throws HttpCommunic } public Basket updateBasket(Basket basket) throws HttpCommunicationException { - restCommunication.httpPut(urlUtil.getUrl(basket), unzer.getPrivateKey(), basket); + ApiConfig apiConfig = basket instanceof BasketV3 ? ApiConfigs.PAYMENT_API_BEARER_AUTH : ApiConfigs.PAYMENT_API; + restCommunication.httpPut(urlUtil.getUrl(basket), getAuthentication(apiConfig), basket, apiConfig); return fetchBasket(basket.getId()); } public Basket fetchBasket(String id) throws HttpCommunicationException { String response; + boolean isUUID = isUUIDResource(id); + ApiConfig apiConfig = isUUID ? ApiConfigs.PAYMENT_API_BEARER_AUTH : ApiConfigs.PAYMENT_API; try { - // Try fetch Basket version 2 - + // Try fetch Basket version 2 or 3 + Basket basket = isUUID ? new BasketV3() : new Basket(); // basket v2 has totalvaluegross. this object is not sent to api - Basket basket = new Basket() - .setId(id) + basket.setId(id) .setTotalValueGross(BigDecimal.ONE); response = restCommunication.httpGet( urlUtil.getUrl(basket), - unzer.getPrivateKey() + getAuthentication(apiConfig), + apiConfig ); } catch (PaymentException ex) { // ... or Basket version 1 - if (ex.getStatusCode() == 404) { // not found + if (ex.getStatusCode() == 404 && !isUUID) { // not found response = restCommunication.httpGet( urlUtil.getUrl(new Basket().setId(id)), unzer.getPrivateKey() @@ -446,10 +442,12 @@ public Metadata fetchMetadata(String id) throws HttpCommunicationException { } public Basket createBasket(Basket basket) throws HttpCommunicationException { + ApiConfig apiConfig = basket instanceof BasketV3 ? ApiConfigs.PAYMENT_API_BEARER_AUTH : ApiConfigs.PAYMENT_API; String response = restCommunication.httpPost( urlUtil.getUrl(basket), - unzer.getPrivateKey(), - basket + getAuthentication(apiConfig), + basket, + apiConfig ); Basket jsonBasket = jsonParser.fromJson(response, Basket.class); basket.setId(jsonBasket.getId()); @@ -896,14 +894,13 @@ public String deleteCustomer(String customerId) throws HttpCommunicationExceptio boolean isV2Id = isUUIDResource(customerId); ApiConfig apiConfig = isV2Id ? ApiConfigs.PAYMENT_API_BEARER_AUTH : ApiConfigs.PAYMENT_API; Customer customer = isV2Id ? new CustomerV2("", "") : new Customer("", ""); - String authentication = isV2Id ? unzer.getJwtToken() : unzer.getPrivateKey(); - customer.setId(customerId); customer.setCustomerId(customerId); + String response = restCommunication.httpDelete( urlUtil.getUrl(customer), - authentication, + getAuthentication(apiConfig), apiConfig ); if (response == null || response.isEmpty()) { @@ -913,6 +910,15 @@ public String deleteCustomer(String customerId) throws HttpCommunicationExceptio return idResponse.getId(); } + private String getAuthentication(ApiConfig apiConfig) { + String authentication = unzer.getPrivateKey(); + if (apiConfig.getAuthMethod() == ApiConfig.AuthMethod.BEARER) { + unzer.prepareJwtToken(); + authentication = unzer.getJwtToken(); + } + return authentication; + } + public Authorization fetchAuthorization(String paymentId) throws HttpCommunicationException { return fetchPayment(paymentId).getAuthorization(); } diff --git a/src/test/java/com/unzer/payment/business/BasketV3Test.java b/src/test/java/com/unzer/payment/business/BasketV3Test.java new file mode 100644 index 00000000..80a6b4fb --- /dev/null +++ b/src/test/java/com/unzer/payment/business/BasketV3Test.java @@ -0,0 +1,85 @@ +package com.unzer.payment.business; + +import com.unzer.payment.Basket; +import com.unzer.payment.Charge; +import com.unzer.payment.Payment; +import com.unzer.payment.integration.resources.BearerAuthBaseTest; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; + +import static com.unzer.payment.business.BasketV3TestData.getMaxTestBasketV3; +import static com.unzer.payment.business.BasketV3TestData.getMinTestBasketV3; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class BasketV3Test extends BearerAuthBaseTest { + @Test + void testCreateFetchBasket() { + Basket maxBasket = getMaxTestBasketV3(); + Basket basket = getUnzer().createBasket(maxBasket); + + // when + Basket basketFetched = getUnzer().fetchBasket(basket.getId()); + + // then + assertNotNull(basketFetched); + assertNotNull(basketFetched.getId()); + assertBasketEquals(maxBasket, basketFetched); + } + + @Test + void testCreateFetchMinBasket() { + Basket minBasket = getMinTestBasketV3(); + Basket basket = getUnzer().createBasket(minBasket); + + // when + Basket basketFetched = getUnzer().fetchBasket(basket.getId()); + + // then + assertBasketEquals(minBasket, basketFetched); + } + + @Test + void testUpdateBasket() { + Basket minBasket = getMinTestBasketV3(); + Basket basket = getUnzer().createBasket(minBasket); + Basket maxBasket = getMaxTestBasketV3(); + maxBasket.setOrderId(basket.getOrderId()); + + // when + Basket updatedBasket = getUnzer().updateBasket(maxBasket, basket.getId()); + + //then + assertBasketEquals(maxBasket, updatedBasket); + } + + @Test + void testChargeWithBasket() { + Basket basket = getUnzer().createBasket(getMaxTestBasketV3()); + Charge chargeReq = + getCharge(createPaymentTypeCard(getUnzer(), "4711100000000000").getId(), null, null, null, + basket.getId(), null); + chargeReq.setAmount(BigDecimal.valueOf(684.47)); + Charge charge = getUnzer().charge(chargeReq); + + //when + Payment payment = getUnzer().fetchPayment(charge.getPayment().getId()); + + //then + assertNotNull(payment); + assertNotNull(payment.getId()); + assertNotNull(payment.getCharge(0)); + assertNotNull(payment.getCharge(0).getId()); + assertEquals(basket.getId(), payment.getBasketId()); + assertEquals(basket.getId(), payment.getCharge(0).getBasketId()); + } + + private void assertBasketEquals(Basket expected, Basket actual) { + assertThat(expected) + .usingComparatorForType(BigDecimal::compareTo, BigDecimal.class) + .usingRecursiveComparison() + .isEqualTo(actual); + } +} diff --git a/src/test/java/com/unzer/payment/business/BasketV3TestData.java b/src/test/java/com/unzer/payment/business/BasketV3TestData.java new file mode 100644 index 00000000..3f4e8108 --- /dev/null +++ b/src/test/java/com/unzer/payment/business/BasketV3TestData.java @@ -0,0 +1,79 @@ +package com.unzer.payment.business; + +import com.unzer.payment.Basket; +import com.unzer.payment.BasketItem; +import com.unzer.payment.BasketV3; + +import java.math.BigDecimal; +import java.util.Currency; + +import static com.unzer.payment.util.Types.unsafeUrl; +import static com.unzer.payment.util.Uuid.generateUuid; + +public class BasketV3TestData { + public static Basket getMaxTestBasketV3() { + return new BasketV3() + .setTotalValueGross(new BigDecimal("380.48")) + .setCurrencyCode(Currency.getInstance("EUR")) + .setOrderId(generateUuid()) + .addBasketItem(getMaxTestBasketItem1V2()) // 14.48 - 1.0 + .addBasketItem(getMaxTestBasketItem2V2()); // 366 // 122 * 3 + } + + public static BasketItem getMaxTestBasketItem2V2() { + return new BasketItem() + .setBasketItemReferenceId("Artikelnummer4712") + .setAmountPerUnitGross(new BigDecimal("122")) + .setQuantity(3) + .setTitle("Apple iPad Air") + .setUnit("Pc.") + .setAmountDiscountPerUnitGross(BigDecimal.ZERO) + .setVat(BigDecimal.valueOf(20)) + .setSubTitle("Nicht nur Pros brauchen Power.") + .setType(BasketItem.Type.GOODS) + .setImageUrl(unsafeUrl("https://store.storeimages.cdn-apple.com/4668/as-images.apple.com/is/iphone-12-pro-family-hero")); + } + + + public static BasketItem getMaxTestBasketItem1V2() { + return new BasketItem() + .setBasketItemReferenceId("Artikelnummer4711") + .setAmountPerUnitGross(new BigDecimal("24.48")) + .setAmountDiscountPerUnitGross(BigDecimal.TEN) + .setQuantity(1) + .setTitle("Apple iPhone") + .setUnit("Pc.") + .setVat(BigDecimal.valueOf(19)) + .setSubTitle("XS in Red").setType(BasketItem.Type.GOODS) + .setImageUrl(unsafeUrl("https://store.storeimages.cdn-apple.com/4668/as-images.apple.com/is/iphone-12-pro-family-hero")); + } + + public static Basket getMaxTestBasketV3(BigDecimal amount) { + return new BasketV3() + .setTotalValueGross(amount) + .setCurrencyCode(Currency.getInstance("EUR")) + .setOrderId(generateUuid()) + .addBasketItem(getMaxTestBasketItem1V2()) + .addBasketItem(getMaxTestBasketItem2V2()); + } + + + public static BasketItem getMinTestBasketItemV2() { + return new BasketItem() + .setBasketItemReferenceId("Artikelnummer4711") + .setQuantity(5) + .setVat(BigDecimal.ZERO) + .setAmountDiscountPerUnitGross(BigDecimal.ZERO) + .setAmountPerUnitGross(new BigDecimal("100.1")) + .setTitle("Apple iPhone"); + } + + + public static Basket getMinTestBasketV3() { + return new BasketV3() + .setTotalValueGross(new BigDecimal("500.5")) + .setCurrencyCode(Currency.getInstance("EUR")) + .setOrderId(generateUuid()) + .addBasketItem(getMinTestBasketItemV2()); + } +} diff --git a/src/test/java/com/unzer/payment/business/CustomerV2Test.java b/src/test/java/com/unzer/payment/business/CustomerV2Test.java index cafd7192..59becf9e 100644 --- a/src/test/java/com/unzer/payment/business/CustomerV2Test.java +++ b/src/test/java/com/unzer/payment/business/CustomerV2Test.java @@ -4,17 +4,16 @@ import com.unzer.payment.Customer; import com.unzer.payment.CustomerV2; import com.unzer.payment.PaymentException; +import com.unzer.payment.Unzer; +import com.unzer.payment.integration.resources.BearerAuthBaseTest; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; -class CustomerV2Test extends AbstractPaymentTest { +class CustomerV2Test extends BearerAuthBaseTest { @Test void testCreateMinimumCustomer() { - Customer customer = getUnzer().createCustomer(new CustomerV2("firstname", "lastname")); + Customer customer = getUnzer().createCustomer(new CustomerV2("Max", "Mustermann")); assertNotNull(customer); assertNotNull(customer.getId()); assertEquals(getMinimumCustomer().getFirstname(), customer.getFirstname()); @@ -58,21 +57,23 @@ void testUpdateCustomer() { @Test void testDeleteCustomer() { - Customer customer = getUnzer().createCustomer(initV2Customer()); - String deletedCustomerId = getUnzer().deleteCustomer(customer.getId()); + Unzer unzer = getUnzer(); + Customer customer = unzer.createCustomer(initV2Customer()); + String deletedCustomerId = unzer.deleteCustomer(customer.getId()); assertEquals(customer.getId(), deletedCustomerId); assertThrows(PaymentException.class, () -> { - getUnzer().fetchCustomer(deletedCustomerId); + unzer.fetchCustomer(deletedCustomerId); }, "Fetching deleted customer should cause PaymentException"); } @Test void testCreateCustomerWithException() { + Customer customerRequest = new CustomerV2("User", "Test"); + customerRequest.setId("s-cst-abcdef"); + Unzer unzer = getUnzer(); assertThrows(PaymentException.class, () -> { - Customer customerRequest = new CustomerV2("User", "Test"); - customerRequest.setId("s-cst-abcdef"); - getUnzer().createCustomer(customerRequest); + unzer.createCustomer(customerRequest); }); } } diff --git a/src/test/java/com/unzer/payment/integration/resources/PaypageV2BaseTest.java b/src/test/java/com/unzer/payment/integration/resources/BearerAuthBaseTest.java similarity index 94% rename from src/test/java/com/unzer/payment/integration/resources/PaypageV2BaseTest.java rename to src/test/java/com/unzer/payment/integration/resources/BearerAuthBaseTest.java index f49b56e1..dd45585e 100644 --- a/src/test/java/com/unzer/payment/integration/resources/PaypageV2BaseTest.java +++ b/src/test/java/com/unzer/payment/integration/resources/BearerAuthBaseTest.java @@ -11,7 +11,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @TestInstance(TestInstance.Lifecycle.PER_CLASS) -abstract class PaypageV2BaseTest extends AbstractPaymentTest { +public abstract class BearerAuthBaseTest extends AbstractPaymentTest { protected Unzer unzer; @BeforeAll diff --git a/src/test/java/com/unzer/payment/integration/resources/LinkpayV2Test.java b/src/test/java/com/unzer/payment/integration/resources/LinkpayV2Test.java index f03b423c..52390583 100644 --- a/src/test/java/com/unzer/payment/integration/resources/LinkpayV2Test.java +++ b/src/test/java/com/unzer/payment/integration/resources/LinkpayV2Test.java @@ -14,7 +14,7 @@ /** * Paypage V2 Test for linkpay specific features. */ -class LinkpayV2Test extends PaypageV2BaseTest { +class LinkpayV2Test extends BearerAuthBaseTest { @Test void minimumLinkpayCreation() { diff --git a/src/test/java/com/unzer/payment/integration/resources/PaypageV2Test.java b/src/test/java/com/unzer/payment/integration/resources/PaypageV2Test.java index 7ebe82ef..444a355b 100644 --- a/src/test/java/com/unzer/payment/integration/resources/PaypageV2Test.java +++ b/src/test/java/com/unzer/payment/integration/resources/PaypageV2Test.java @@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.*; -class PaypageV2Test extends PaypageV2BaseTest { +class PaypageV2Test extends BearerAuthBaseTest { @Test void minimumPaypageCreation() {