Skip to content

Commit a7d7d08

Browse files
authored
Merge pull request #86 from unzerdev/UMCS-515/fix/invoice-secured-cancelation-failed
UMCS-515 Invoice secured - reason code for Cancel is mandatory
2 parents b7740d6 + 071411b commit a7d7d08

File tree

6 files changed

+116
-1
lines changed

6 files changed

+116
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This release brings Unzer Paylater Invoice payment type support to Java SDK.
1919
### Fixed
2020

2121
* Fixed: customer salutation is null, because of marshalling/unmarshalling issue.
22+
* Fixed: cancel InvoiceSecured charge failed with error `API.340.100.024: Reason code is mandatory for the payment type INVOICE_SECURED`. Please, use `com.unzer.payment.Cancel.setReasonCode` to set reason code and `com.unzer.payment.Unzer.cancelCharge(java.lang.String, java.lang.String, com.unzer.payment.Cancel)` to cancel InvoiceSecured charge.
2223

2324
### Removed
2425

src/main/java/com/unzer/payment/Cancel.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@
2424
* Business object for Cancellations
2525
*
2626
* @author Unzer E-Com GmbH
27-
*
2827
*/
2928
public class Cancel extends AbstractTransaction<Payment> {
3029

3130
private BigDecimal amountGross;
3231
private BigDecimal amountNet;
3332
private BigDecimal amountVat;
33+
private ReasonCode reasonCode;
3434

3535
public Cancel() {
3636
super();
@@ -73,4 +73,17 @@ public BigDecimal getAmountVat() {
7373
public void setAmountVat(BigDecimal amountVat) {
7474
this.amountVat = amountVat;
7575
}
76+
77+
public ReasonCode getReasonCode() {
78+
return reasonCode;
79+
}
80+
81+
public Cancel setReasonCode(ReasonCode reasonCode) {
82+
this.reasonCode = reasonCode;
83+
return this;
84+
}
85+
86+
public enum ReasonCode {
87+
CANCEL, RETURN, CREDIT
88+
}
7689
}

src/main/java/com/unzer/payment/PaymentError.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package com.unzer.payment;
1717

18+
import java.util.Objects;
19+
1820
public class PaymentError {
1921

2022
private String merchantMessage;
@@ -61,4 +63,23 @@ public String toString() {
6163
return "{merchantMessage:" + merchantMessage + ", customerMessage:" + customerMessage + ", code:" + code + "}";
6264
}
6365

66+
@Override
67+
public boolean equals(Object o) {
68+
if (this == o) return true;
69+
if (o == null || getClass() != o.getClass()) return false;
70+
71+
PaymentError that = (PaymentError) o;
72+
73+
return Objects.equals(merchantMessage, that.merchantMessage) &&
74+
Objects.equals(customerMessage, that.customerMessage) &&
75+
Objects.equals(code, that.code) ;
76+
}
77+
78+
@Override
79+
public int hashCode() {
80+
int result = merchantMessage != null ? merchantMessage.hashCode() : 0;
81+
result = 31 * result + (customerMessage != null ? customerMessage.hashCode() : 0);
82+
result = 31 * result + (code != null ? code.hashCode() : 0);
83+
return result;
84+
}
6485
}

src/main/java/com/unzer/payment/communication/json/JsonCharge.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515
*/
1616
package com.unzer.payment.communication.json;
1717

18+
import com.unzer.payment.Cancel;
19+
1820
public class JsonCharge extends JsonInitPayment implements JsonObject {
1921

2022
private String invoiceId;
23+
private String reasonCode;
2124

2225
public JsonCharge() {
2326
super();
@@ -51,4 +54,7 @@ public void setInvoiceId(String invoiceId) {
5154
this.invoiceId = invoiceId;
5255
}
5356

57+
public void setReasonCode(String reasonCode) {
58+
this.reasonCode = reasonCode;
59+
}
5460
}

src/main/java/com/unzer/payment/communication/mapper/JsonToBusinessClassMapper.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ public JsonObject map(Cancel cancel) {
5757
JsonCharge json = new JsonCharge();
5858
json.setAmount(cancel.getAmount());
5959
json.setPaymentReference(cancel.getPaymentReference());
60+
61+
if (cancel.getReasonCode() != null) {
62+
json.setReasonCode(cancel.getReasonCode().toString());
63+
}
6064
return json;
6165
}
6266

src/test/java/com/unzer/payment/business/paymenttypes/InvoiceSecuredTest.java

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,19 @@
2424
import com.unzer.payment.communication.json.JsonIdObject;
2525
import com.unzer.payment.paymenttypes.InvoiceSecured;
2626
import com.unzer.payment.service.PaymentService;
27+
import org.junit.jupiter.api.DynamicTest;
2728
import org.junit.jupiter.api.Test;
29+
import org.junit.jupiter.api.TestFactory;
2830

2931
import java.math.BigDecimal;
3032
import java.net.MalformedURLException;
3133
import java.net.URL;
3234
import java.text.ParseException;
35+
import java.util.Collection;
3336
import java.util.Currency;
3437
import java.util.Date;
38+
import java.util.stream.Collectors;
39+
import java.util.stream.Stream;
3540

3641
import static com.unzer.payment.business.BasketV1TestData.getMaxTestBasketV1;
3742
import static com.unzer.payment.business.BasketV1TestData.getMinTestBasketV1;
@@ -40,6 +45,7 @@
4045
import static com.unzer.payment.util.Url.unsafeUrl;
4146
import static com.unzer.payment.util.Uuid.generateUuid;
4247
import static org.junit.jupiter.api.Assertions.*;
48+
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
4349

4450
public class InvoiceSecuredTest extends AbstractPaymentTest {
4551

@@ -224,6 +230,70 @@ public void testChargeInvoiceFactoringBasketV2() throws HttpCommunicationExcepti
224230
assertNotNull(charge.getPaymentId());
225231
}
226232

233+
@TestFactory
234+
public Collection<DynamicTest> testCancelInvoiceSecured() {
235+
return Stream.of(Cancel.ReasonCode.RETURN, Cancel.ReasonCode.RETURN, Cancel.ReasonCode.CREDIT)
236+
.map(rc -> dynamicTest(rc.name(), () -> {
237+
Unzer unzer = getUnzer();
238+
InvoiceSecured paymentType = unzer.createPaymentType(new InvoiceSecured());
239+
Basket basket = getMaxTestBasketV2();
240+
String invoiceId = getRandomInvoiceId();
241+
Charge charge = paymentType.charge(
242+
basket.getTotalValueGross(),
243+
Currency.getInstance("EUR"),
244+
unsafeUrl("https://www.meinShop.de"),
245+
getMaximumCustomerSameAddress(generateUuid()),
246+
basket,
247+
invoiceId
248+
);
249+
Cancel cancel = unzer.cancelCharge(
250+
charge.getPaymentId(),
251+
charge.getId(),
252+
(Cancel) new Cancel(unzer)
253+
.setReasonCode(rc)
254+
.setAmount(basket.getTotalValueGross())
255+
);
256+
assertNotNull(cancel);
257+
assertNotNull(cancel.getId());
258+
assertEquals(Cancel.Status.SUCCESS, cancel.getStatus());
259+
})).collect(Collectors.toList());
260+
}
261+
262+
@Test
263+
public void testCancelFailsWithoutReasonCode() throws HttpCommunicationException {
264+
PaymentError expectedError = new PaymentError(
265+
"Reason code is mandatory for the payment type INVOICE_SECURED",
266+
"Reason code is mandatory for the payment type INVOICE_SECURED. Please contact us for more information.",
267+
"API.340.100.024"
268+
);
269+
270+
Unzer unzer = getUnzer();
271+
InvoiceSecured paymentType = unzer.createPaymentType(new InvoiceSecured());
272+
Basket basket = getMaxTestBasketV2();
273+
String invoiceId = getRandomInvoiceId();
274+
Charge charge = paymentType.charge(
275+
basket.getTotalValueGross(),
276+
Currency.getInstance("EUR"),
277+
unsafeUrl("https://www.meinShop.de"),
278+
getMaximumCustomerSameAddress(generateUuid()),
279+
basket,
280+
invoiceId
281+
);
282+
283+
PaymentException exception = assertThrows(PaymentException.class, () -> {
284+
unzer.cancelCharge(
285+
charge.getPaymentId(),
286+
charge.getId(),
287+
(Cancel) new Cancel(unzer)
288+
.setAmount(basket.getTotalValueGross())
289+
);
290+
});
291+
assertEquals(1, exception.getPaymentErrorList().size());
292+
PaymentError actualError = exception.getPaymentErrorList().get(0);
293+
294+
assertEquals(expectedError, actualError);
295+
}
296+
227297

228298
@Deprecated
229299
private InvoiceSecured getInvoiceSecured() {

0 commit comments

Comments
 (0)