killbill-memoizeit
Changes
beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java 4(+2 -2)
beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java 4(+2 -2)
beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationParentInvoice.java 57(+41 -16)
beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithWrittenOffTag.java 2(+1 -1)
payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java 15(+15 -0)
payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryAuthorizeOperationCallback.java 4(+2 -2)
pom.xml 2(+1 -1)
Details
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java
index ebf1e53..9f64e78 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java
@@ -752,7 +752,7 @@ public class TestOverdueIntegration extends TestOverdueBase {
checkODState(OverdueWrapper.CLEAR_STATE_NAME);
// Now, refund the second (first non-zero dollar) invoice
- final Payment payment = paymentApi.getPayment(invoiceUserApi.getInvoicesByAccount(account.getId(), false, callContext).get(1).getPayments().get(0).getPaymentId(), false, PLUGIN_PROPERTIES, callContext);
+ final Payment payment = paymentApi.getPayment(invoiceUserApi.getInvoicesByAccount(account.getId(), false, callContext).get(1).getPayments().get(0).getPaymentId(), false, false, PLUGIN_PROPERTIES, callContext);
refundPaymentAndCheckForCompletion(account, payment, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT, NextEvent.BLOCK);
// We should now be in OD1
checkODState("OD1");
@@ -799,7 +799,7 @@ public class TestOverdueIntegration extends TestOverdueBase {
// Now, create a chargeback for the second (first non-zero dollar) invoice
final InvoicePayment invoicePayment = invoicePaymentApi.getInvoicePayments(invoiceUserApi.getInvoicesByAccount(account.getId(), false, callContext).get(1).getPayments().get(0).getPaymentId(), callContext).get(0);
- Payment payment = paymentApi.getPayment(invoicePayment.getPaymentId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ Payment payment = paymentApi.getPayment(invoicePayment.getPaymentId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
payment = createChargeBackAndCheckForCompletion(account, payment, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT, NextEvent.BLOCK);
// We should now be in OD1
checkODState("OD1");
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoice.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoice.java
index c87e7ed..442d316 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoice.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoice.java
@@ -258,7 +258,7 @@ public class TestIntegrationInvoice extends TestIntegrationBase {
assertTrue(accountBalance3.compareTo(BigDecimal.ZERO) == 0);
- final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
assertEquals(payments.size(), 1);
final Payment payment = payments.get(0);
@@ -320,7 +320,7 @@ public class TestIntegrationInvoice extends TestIntegrationBase {
invoiceUserApi.commitInvoice(draftInvoiceItems.get(0).getInvoiceId(), callContext);
assertListenerStatus();
- final List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), false, null, callContext);
+ final List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), false, false, null, callContext);
assertEquals(accountPayments.size(), 3);
assertEquals(accountPayments.get(2).getPurchasedAmount(), new BigDecimal("10.00"));
}
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
index b82fdd5..ec6768b 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
@@ -528,7 +528,7 @@ public class TestIntegrationInvoiceWithRepairLogic extends TestIntegrationBase {
// ITEM ADJUSTMENT PRIOR TO DOING THE REPAIR
//
final Invoice invoice1 = invoices.get(1);
- final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
final ExpectedPaymentCheck expectedPaymentCheck = new ExpectedPaymentCheck(clock.getUTCNow().toLocalDate(), new BigDecimal("2399.95"), TransactionStatus.SUCCESS, invoice1.getId(), Currency.USD);
final Payment payment1 = payments.get(0);
@@ -598,7 +598,7 @@ public class TestIntegrationInvoiceWithRepairLogic extends TestIntegrationBase {
// ITEM ADJUSTMENT PRIOR TO DOING THE REPAIR
//
final Invoice invoice1 = invoices.get(1);
- final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
final ExpectedPaymentCheck expectedPaymentCheck = new ExpectedPaymentCheck(clock.getUTCNow().toLocalDate(), new BigDecimal("2399.95"), TransactionStatus.SUCCESS, invoice1.getId(), Currency.USD);
final Payment payment1 = payments.get(0);
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationParentInvoice.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationParentInvoice.java
index 6931288..2b9462e 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationParentInvoice.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationParentInvoice.java
@@ -93,14 +93,19 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
assertEquals(parentInvoice.getNumberOfItems(), 2);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.DRAFT);
assertTrue(parentInvoice.isParentInvoice());
- assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.valueOf(279.90)), 0);
+ // balance is 0 because parent invoice status is DRAFT
+ assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
+ // total 279.95
assertEquals(parentInvoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.PARENT_SUMMARY);
+ assertEquals(parentInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(249.95)), 0);
assertEquals(parentInvoice.getInvoiceItems().get(1).getInvoiceItemType(), InvoiceItemType.PARENT_SUMMARY);
+ assertEquals(parentInvoice.getInvoiceItems().get(1).getAmount().compareTo(BigDecimal.valueOf(29.95)), 0);
// Check Child Balance. It should be > 0 here because Parent invoice is unpaid yet.
List<Invoice> child1Invoices = invoiceUserApi.getInvoicesByAccount(child1Account.getId(), false, callContext);
assertEquals(child1Invoices.size(), 2);
- assertTrue(child1Invoices.get(1).getBalance().compareTo(BigDecimal.ZERO) > 0);
+ // child balance is 0 because parent invoice status is DRAFT at this point
+ assertEquals(child1Invoices.get(1).getBalance().compareTo(BigDecimal.ZERO), 0);
// Moving a day the NotificationQ calls the commitInvoice. Payment is expected.
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
@@ -151,7 +156,9 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
assertEquals(parentInvoice.getNumberOfItems(), 1);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.DRAFT);
assertTrue(parentInvoice.isParentInvoice());
- assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.valueOf(29.95)), 0);
+ // balance is 0 because parent invoice status is DRAFT
+ assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
+ assertEquals(parentInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(29.95)), 0);
// upgrade plan
busHandler.pushExpectedEvents(NextEvent.CHANGE, NextEvent.INVOICE);
@@ -160,7 +167,6 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
// check parent invoice. Expected to have the same invoice item with the amount updated
final List<Invoice> childInvoices = invoiceUserApi.getInvoicesByAccount(childAccount.getId(), false, callContext);
- BigDecimal totalAmount = childInvoices.get(1).getBalance().add(childInvoices.get(2).getBalance());
parentInvoices = invoiceUserApi.getInvoicesByAccount(parentAccount.getId(), false, callContext);
assertEquals(parentInvoices.size(), 2);
@@ -168,7 +174,9 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
assertEquals(parentInvoice.getNumberOfItems(), 1);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.DRAFT);
assertTrue(parentInvoice.isParentInvoice());
- assertEquals(parentInvoice.getBalance(), totalAmount);
+ // balance is 0 because parent invoice status is DRAFT
+ assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
+
// Moving a day the NotificationQ calls the commitInvoice. Now payment is expected
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
@@ -221,7 +229,8 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
assertEquals(childInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(29.95)), 0);
assertEquals(childInvoice.getInvoiceItems().get(1).getInvoiceItemType(), InvoiceItemType.CBA_ADJ);
assertEquals(childInvoice.getInvoiceItems().get(1).getAmount().compareTo(BigDecimal.valueOf(-10.00)), 0);
- assertEquals(childInvoice.getBalance().compareTo(BigDecimal.valueOf(19.95)), 0);
+ // child balance is 0 because parent invoice status is DRAFT at this point
+ assertEquals(childInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
// check parent Invoice with child plan amount
List<Invoice> parentInvoices = invoiceUserApi.getInvoicesByAccount(parentAccount.getId(), false, callContext);
@@ -231,7 +240,9 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
assertEquals(parentInvoice.getNumberOfItems(), 1);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.DRAFT);
assertTrue(parentInvoice.isParentInvoice());
- assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.valueOf(19.95)), 0);
+ // balance is 0 because parent invoice status is DRAFT
+ assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
+ assertEquals(parentInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(19.95)), 0);
// Moving a day the NotificationQ calls the commitInvoice.
busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
@@ -247,7 +258,7 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
assertEquals(parentInvoice.getChargedAmount().compareTo(BigDecimal.valueOf(19.95)), 0);
assertEquals(parentInvoice.getCreditedAmount().compareTo(BigDecimal.ZERO), 0);
- final List<Payment> accountPayments = paymentApi.getAccountPayments(parentAccount.getId(), false, null, callContext);
+ final List<Payment> accountPayments = paymentApi.getAccountPayments(parentAccount.getId(), false, false, null, callContext);
assertEquals(accountPayments.size(), 1);
assertEquals(accountPayments.get(0).getPurchasedAmount().setScale(2).compareTo(BigDecimal.valueOf(19.95)), 0);
assertEquals(accountPayments.get(0).getCreditedAmount().compareTo(BigDecimal.ZERO), 0);
@@ -308,7 +319,7 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
assertTrue(parentInvoice.isParentInvoice());
assertEquals(parentInvoice.getChargedAmount().compareTo(BigDecimal.valueOf(29.95)), 0);
- final List<Payment> accountPayments = paymentApi.getAccountPayments(parentAccount.getId(), false, null, callContext);
+ final List<Payment> accountPayments = paymentApi.getAccountPayments(parentAccount.getId(), false, false, null, callContext);
assertEquals(accountPayments.size(), 1);
assertEquals(accountPayments.get(0).getPurchasedAmount().setScale(2).compareTo(BigDecimal.valueOf(29.95)), 0);
assertEquals(accountPayments.get(0).getCreditedAmount().compareTo(BigDecimal.ZERO), 0);
@@ -355,7 +366,10 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
assertEquals(parentInvoice.getNumberOfItems(), 1);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.DRAFT);
assertTrue(parentInvoice.isParentInvoice());
- assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.valueOf(249.95)), 0);
+ // balance is 0 because parent invoice status is DRAFT
+ assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
+ assertEquals(parentInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(249.95)), 0);
+
// issue a $10 adj when invoice is unpaid
busHandler.pushExpectedEvents(NextEvent.INVOICE_ADJUSTMENT);
@@ -371,9 +385,12 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
childInvoice = invoiceUserApi.getInvoice(childInvoice.getId(), callContext);
assertEquals(childInvoice.getNumberOfItems(), 2);
- assertEquals(childInvoice.getBalance().compareTo(BigDecimal.valueOf(239.95)), 0);
+ // child balance is 0 because parent invoice status is DRAFT at this point
+ assertEquals(childInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
assertEquals(childInvoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
+ assertEquals(childInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(249.95)), 0);
assertEquals(childInvoice.getInvoiceItems().get(1).getInvoiceItemType(), InvoiceItemType.ITEM_ADJ);
+ assertEquals(childInvoice.getInvoiceItems().get(1).getAmount().compareTo(BigDecimal.valueOf(-10.00)), 0);
// reload parent invoice
parentInvoice = invoiceUserApi.getInvoice(parentInvoice.getId(), callContext);
@@ -381,7 +398,9 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
assertEquals(parentInvoice.getNumberOfItems(), 1);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.DRAFT);
assertTrue(parentInvoice.isParentInvoice());
- assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.valueOf(239.95)), 0);
+ // balance is 0 because parent invoice status is DRAFT
+ assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
+ assertEquals(parentInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(239.95)), 0);
}
@@ -641,7 +660,9 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
assertEquals(parentInvoice.getNumberOfItems(), 1);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.DRAFT);
assertTrue(parentInvoice.isParentInvoice());
- assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.valueOf(249.95)), 0);
+ // balance is 0 because parent invoice status is DRAFT
+ assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
+ assertEquals(parentInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(249.95)), 0);
// cancel subscription
busHandler.pushExpectedEvents(NextEvent.CANCEL, NextEvent.BLOCK, NextEvent.INVOICE);
@@ -662,7 +683,8 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
// invoice 1
childInvoice = childInvoices.get(1);
assertEquals(childInvoice.getNumberOfItems(), 2);
- assertEquals(childInvoice.getBalance().compareTo(BigDecimal.valueOf(16.66)), 0);
+ // child balance is 0 because parent invoice status is DRAFT at this point
+ assertEquals(childInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
assertEquals(childInvoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.RECURRING);
assertEquals(childInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(249.95)), 0);
assertEquals(childInvoice.getInvoiceItems().get(1).getInvoiceItemType(), InvoiceItemType.CBA_ADJ);
@@ -684,7 +706,8 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
parentInvoice = parentInvoices.get(1);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.DRAFT);
assertTrue(parentInvoice.isParentInvoice());
- assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.valueOf(16.66)), 0);
+ // balance is 0 because parent invoice status is DRAFT
+ assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
assertEquals(parentInvoice.getNumberOfItems(), 1);
assertEquals(parentInvoice.getInvoiceItems().get(0).getInvoiceItemType(), InvoiceItemType.PARENT_SUMMARY);
assertEquals(parentInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(16.66)), 0);
@@ -895,7 +918,9 @@ public class TestIntegrationParentInvoice extends TestIntegrationBase {
assertEquals(parentInvoice.getNumberOfItems(), 1);
assertEquals(parentInvoice.getStatus(), InvoiceStatus.DRAFT);
assertTrue(parentInvoice.isParentInvoice());
- assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.valueOf(8.33)), 0);
+ // balance is 0 because parent invoice status is DRAFT
+ assertEquals(parentInvoice.getBalance().compareTo(BigDecimal.ZERO), 0);
+ assertEquals(parentInvoice.getInvoiceItems().get(0).getAmount().compareTo(BigDecimal.valueOf(8.33)), 0);
}
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithWrittenOffTag.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithWrittenOffTag.java
index 013ad68..3bfcf02 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithWrittenOffTag.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithWrittenOffTag.java
@@ -95,7 +95,7 @@ public class TestIntegrationWithWrittenOffTag extends TestIntegrationBase {
remove_AUTO_PAY_OFF_Tag(account.getId(), ObjectType.ACCOUNT);
assertListenerStatus();
- List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
assertEquals(accountPayments.size(), 0);
}
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestInvoicePayment.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestInvoicePayment.java
index f3e26fe..40a5f31 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestInvoicePayment.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestInvoicePayment.java
@@ -274,7 +274,7 @@ public class TestInvoicePayment extends TestIntegrationBase {
invoiceChecker.checkChargedThroughDate(baseEntitlement.getId(), new LocalDate(2012, 6, 30), callContext);
// Invoice is not paid
- Assert.assertEquals(paymentApi.getAccountPayments(account.getId(), false, ImmutableList.<PluginProperty>of(), callContext).size(), 0);
+ Assert.assertEquals(paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext).size(), 0);
Assert.assertEquals(invoice2.getBalance().compareTo(new BigDecimal("249.95")), 0);
Assert.assertEquals(invoiceUserApi.getAccountBalance(account.getId(), callContext).compareTo(invoice2.getBalance()), 0);
@@ -493,7 +493,7 @@ public class TestInvoicePayment extends TestIntegrationBase {
final BigDecimal accountBalance1 = invoiceUserApi.getAccountBalance(account.getId(), callContext);
assertTrue(accountBalance1.compareTo(new BigDecimal("249.95")) == 0);
- final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
assertEquals(payments.size(), 1);
assertEquals(payments.get(0).getPurchasedAmount().compareTo(BigDecimal.ZERO), 0);
assertEquals(payments.get(0).getTransactions().size(), 1);
@@ -517,7 +517,7 @@ public class TestInvoicePayment extends TestIntegrationBase {
final BigDecimal accountBalance2 = invoiceUserApi.getAccountBalance(account.getId(), callContext);
assertTrue(accountBalance2.compareTo(BigDecimal.ZERO) == 0);
- final List<Payment> payments2 = paymentApi.getAccountPayments(account.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final List<Payment> payments2 = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
assertEquals(payments2.size(), 1);
assertEquals(payments2.get(0).getTransactions().size(), 2);
assertEquals(payments2.get(0).getTransactions().get(1).getAmount().compareTo(new BigDecimal("249.95")), 0);
@@ -595,7 +595,7 @@ public class TestInvoicePayment extends TestIntegrationBase {
Assert.assertTrue(updateInvoice3.getPayments().get(0).isSuccess());
Assert.assertEquals(invoiceUserApi.getAccountBalance(account.getId(), callContext).compareTo(invoice2.getBalance()), 0);
- final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
Assert.assertEquals(payments.size(), 1);
Assert.assertEquals(payments.get(0).getTransactions().size(), 1);
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/util/PaymentChecker.java b/beatrix/src/test/java/org/killbill/billing/beatrix/util/PaymentChecker.java
index efaf1ea..03440c5 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/util/PaymentChecker.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/util/PaymentChecker.java
@@ -59,7 +59,7 @@ public class PaymentChecker {
}
public Payment checkPayment(final UUID accountId, final int paymentOrderingNumber, final CallContext context, final ExpectedPaymentCheck expected) throws PaymentApiException {
- final List<Payment> payments = paymentApi.getAccountPayments(accountId, false, ImmutableList.<PluginProperty>of(), context);
+ final List<Payment> payments = paymentApi.getAccountPayments(accountId, false, false, ImmutableList.<PluginProperty>of(), context);
Assert.assertEquals(payments.size(), paymentOrderingNumber);
final Payment payment = payments.get(paymentOrderingNumber - 1);
final PaymentTransaction transaction = getPurchaseTransaction(payment);
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/util/RefundChecker.java b/beatrix/src/test/java/org/killbill/billing/beatrix/util/RefundChecker.java
index 6eb8afd..9472f6b 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/util/RefundChecker.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/util/RefundChecker.java
@@ -67,7 +67,7 @@ public class RefundChecker {
public PaymentTransaction checkRefund(final UUID paymentId, final CallContext context, ExpectedRefundCheck expected) throws PaymentApiException {
- final Payment payment = paymentApi.getPayment(paymentId, false, ImmutableList.<PluginProperty>of(), context);
+ final Payment payment = paymentApi.getPayment(paymentId, false, false, ImmutableList.<PluginProperty>of(), context);
final PaymentTransaction refund = Iterables.tryFind(payment.getTransactions(), new Predicate<PaymentTransaction>() {
@Override
public boolean apply(final PaymentTransaction input) {
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/model/DefaultInvoice.java b/invoice/src/main/java/org/killbill/billing/invoice/model/DefaultInvoice.java
index a6cdd3e..6db52ff 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/model/DefaultInvoice.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/model/DefaultInvoice.java
@@ -249,7 +249,9 @@ public class DefaultInvoice extends EntityBase implements Invoice, Cloneable {
@Override
public BigDecimal getBalance() {
- return hasZeroParentBalance() ? BigDecimal.ZERO : InvoiceCalculatorUtils.computeInvoiceBalance(currency, invoiceItems, payments, isWrittenOff() || isMigrationInvoice());
+ return getStatus().equals(InvoiceStatus.DRAFT) || hasZeroParentBalance() ?
+ BigDecimal.ZERO :
+ InvoiceCalculatorUtils.computeInvoiceBalance(currency, invoiceItems, payments, isWrittenOff() || isMigrationInvoice());
}
private boolean hasZeroParentBalance() {
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoicePaymentJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoicePaymentJson.java
index 53ae552..7379469 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoicePaymentJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoicePaymentJson.java
@@ -25,6 +25,7 @@ import java.util.UUID;
import javax.annotation.Nullable;
import org.killbill.billing.payment.api.Payment;
+import org.killbill.billing.payment.api.PaymentAttempt;
import org.killbill.billing.util.audit.AccountAuditLogs;
import com.fasterxml.jackson.annotation.JsonCreator;
@@ -51,8 +52,9 @@ public class InvoicePaymentJson extends PaymentJson {
@JsonProperty("currency") final String currency,
@JsonProperty("paymentMethodId") final String paymentMethodId,
@JsonProperty("transactions") final List<? extends PaymentTransactionJson> transactions,
+ @JsonProperty("paymentAttempts") final List<PaymentAttemptJson> paymentAttempts,
@JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs) {
- super(accountId, paymentId, paymentNumber, paymentExternalKey, authAmount, capturedAmount, purchasedAmount, refundedAmount, creditedAmount, currency, paymentMethodId, transactions, auditLogs);
+ super(accountId, paymentId, paymentNumber, paymentExternalKey, authAmount, capturedAmount, purchasedAmount, refundedAmount, creditedAmount, currency, paymentMethodId, transactions, paymentAttempts, auditLogs);
this.targetInvoiceId = targetInvoiceId;
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PaymentAttemptJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PaymentAttemptJson.java
new file mode 100644
index 0000000..f8150da
--- /dev/null
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PaymentAttemptJson.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2016 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.jaxrs.json;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.joda.time.DateTime;
+import org.killbill.billing.payment.api.PaymentAttempt;
+import org.killbill.billing.util.audit.AuditLog;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel(description = "Payment attempt")
+public class PaymentAttemptJson extends JsonBase {
+
+ @ApiModelProperty(dataType = "java.util.UUID")
+ private final String accountId;
+ @ApiModelProperty(dataType = "java.util.UUID")
+ private final String paymentMethodId;
+ private final String paymentExternalKey;
+ @ApiModelProperty(dataType = "java.util.UUID")
+ private final String transactionId;
+ private final String transactionExternalKey;
+ @ApiModelProperty(dataType = "org.killbill.billing.payment.api.TransactionType")
+ private final String transactionType;
+ @ApiModelProperty(dataType = "org.joda.time.DateTime")
+ private final DateTime effectiveDate;
+ private final String stateName;
+ @ApiModelProperty(value = "Transaction amount, required except for void operations")
+ private final BigDecimal amount;
+ @ApiModelProperty(value = "Amount currency (account currency unless specified)", dataType = "org.killbill.billing.catalog.api.Currency")
+ private final String currency;
+ // Plugin specific fields
+ private final String pluginName;
+ private final List<PluginPropertyJson> pluginProperties;
+
+ @JsonCreator
+ public PaymentAttemptJson(@JsonProperty("accountId") final String accountId,
+ @JsonProperty("paymentMethodId") final String paymentMethodId,
+ @JsonProperty("paymentExternalKey") final String paymentExternalKey,
+ @JsonProperty("transactionId") final String transactionId,
+ @JsonProperty("transactionExternalKey") final String transactionExternalKey,
+ @JsonProperty("transactionType") final String transactionType,
+ @JsonProperty("effectiveDate") final DateTime effectiveDate,
+ @JsonProperty("stateName") final String stateName,
+ @JsonProperty("amount") final BigDecimal amount,
+ @JsonProperty("currency") final String currency,
+ @JsonProperty("pluginName") final String pluginName,
+ @JsonProperty("pluginProperties") final List<PluginPropertyJson> pluginProperties,
+ @JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs) {
+ super(auditLogs);
+ this.accountId = accountId;
+ this.paymentMethodId = paymentMethodId;
+ this.paymentExternalKey = paymentExternalKey;
+ this.transactionId = transactionId;
+ this.transactionExternalKey = transactionExternalKey;
+ this.transactionType = transactionType;
+ this.effectiveDate = effectiveDate;
+ this.stateName = stateName;
+ this.amount = amount;
+ this.currency = currency;
+ this.pluginName = pluginName;
+ this.pluginProperties = pluginProperties;
+ }
+
+ public PaymentAttemptJson(final PaymentAttempt paymentAttempt, final String paymentExternalKey, @Nullable final List<AuditLog> attemptsLogs) {
+ this(paymentAttempt.getAccountId().toString(),
+ paymentAttempt.getPaymentMethodId().toString(),
+ paymentExternalKey,
+ paymentAttempt.getTransactionId() != null ? paymentAttempt.getTransactionId().toString() : null,
+ paymentAttempt.getTransactionExternalKey(),
+ paymentAttempt.getTransactionType().toString(),
+ paymentAttempt.getEffectiveDate(),
+ paymentAttempt.getStateName() != null ? paymentAttempt.getStateName() : null,
+ paymentAttempt.getAmount(),
+ paymentAttempt.getCurrency() != null ? paymentAttempt.getCurrency().toString() : null,
+ paymentAttempt.getPluginName(),
+ paymentAttempt.getPluginProperties() == null ? null : toPluginPropertyJson(paymentAttempt.getPluginProperties()),
+ toAuditLogJson(attemptsLogs));
+ }
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ public String getPaymentMethodId() {
+ return paymentMethodId;
+ }
+
+ public String getPaymentExternalKey() {
+ return paymentExternalKey;
+ }
+
+ public String getTransactionId() {
+ return transactionId;
+ }
+
+ public String getTransactionExternalKey() {
+ return transactionExternalKey;
+ }
+
+ public String getTransactionType() {
+ return transactionType;
+ }
+
+ public DateTime getEffectiveDate() {
+ return effectiveDate;
+ }
+
+ public String getStateName() {
+ return stateName;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ public String getCurrency() {
+ return currency;
+ }
+
+ public String getPluginName() {
+ return pluginName;
+ }
+
+ public List<PluginPropertyJson> getPluginProperties() {
+ return pluginProperties;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("PaymentAttemptJson{");
+ sb.append("accountId='").append(accountId).append('\'');
+ sb.append(", paymentMethodId='").append(paymentMethodId).append('\'');
+ sb.append(", paymentExternalKey='").append(paymentExternalKey).append('\'');
+ sb.append(", transactionId='").append(transactionId).append('\'');
+ sb.append(", transactionExternalKey='").append(transactionExternalKey).append('\'');
+ sb.append(", transactionType='").append(transactionType).append('\'');
+ sb.append(", effectiveDate=").append(effectiveDate);
+ sb.append(", stateName='").append(stateName).append('\'');
+ sb.append(", amount=").append(amount);
+ sb.append(", currency='").append(currency).append('\'');
+ sb.append(", pluginName='").append(pluginName).append('\'');
+ sb.append(", pluginProperties=").append(pluginProperties);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final PaymentAttemptJson that = (PaymentAttemptJson) o;
+
+ if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+ return false;
+ }
+ if (paymentMethodId != null ? !paymentMethodId.equals(that.paymentMethodId) : that.paymentMethodId != null) {
+ return false;
+ }
+ if (paymentExternalKey != null ? !paymentExternalKey.equals(that.paymentExternalKey) : that.paymentExternalKey != null) {
+ return false;
+ }
+ if (transactionId != null ? !transactionId.equals(that.transactionId) : that.transactionId != null) {
+ return false;
+ }
+ if (transactionExternalKey != null ? !transactionExternalKey.equals(that.transactionExternalKey) : that.transactionExternalKey != null) {
+ return false;
+ }
+ if (transactionType != null ? !transactionType.equals(that.transactionType) : that.transactionType != null) {
+ return false;
+ }
+ if (effectiveDate != null ? effectiveDate.compareTo(that.effectiveDate) != 0 : that.effectiveDate != null) {
+ return false;
+ }
+ if (stateName != null ? !stateName.equals(that.stateName) : that.stateName != null) {
+ return false;
+ }
+ if (amount != null ? amount.compareTo(that.amount) != 0 : that.amount != null) {
+ return false;
+ }
+ if (currency != null ? !currency.equals(that.currency) : that.currency != null) {
+ return false;
+ }
+ if (pluginName != null ? !pluginName.equals(that.pluginName) : that.pluginName != null) {
+ return false;
+ }
+ if (pluginProperties != null ? !pluginProperties.equals(that.pluginProperties) : that.pluginProperties != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = accountId != null ? accountId.hashCode() : 0;
+ result = 31 * result + (paymentMethodId != null ? paymentMethodId.hashCode() : 0);
+ result = 31 * result + (paymentExternalKey != null ? paymentExternalKey.hashCode() : 0);
+ result = 31 * result + (transactionId != null ? transactionId.hashCode() : 0);
+ result = 31 * result + (transactionExternalKey != null ? transactionExternalKey.hashCode() : 0);
+ result = 31 * result + (transactionType != null ? transactionType.hashCode() : 0);
+ result = 31 * result + (effectiveDate != null ? effectiveDate.hashCode() : 0);
+ result = 31 * result + (stateName != null ? stateName.hashCode() : 0);
+ result = 31 * result + (amount != null ? amount.hashCode() : 0);
+ result = 31 * result + (currency != null ? currency.hashCode() : 0);
+ result = 31 * result + (pluginName != null ? pluginName.hashCode() : 0);
+ result = 31 * result + (pluginProperties != null ? pluginProperties.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PaymentJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PaymentJson.java
index 4e65e56..4a605fa 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PaymentJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PaymentJson.java
@@ -22,6 +22,7 @@ import java.util.List;
import javax.annotation.Nullable;
import org.killbill.billing.payment.api.Payment;
+import org.killbill.billing.payment.api.PaymentAttempt;
import org.killbill.billing.payment.api.PaymentTransaction;
import org.killbill.billing.util.audit.AccountAuditLogs;
import org.killbill.billing.util.audit.AuditLog;
@@ -50,6 +51,7 @@ public class PaymentJson extends JsonBase {
@ApiModelProperty(dataType = "java.util.UUID")
private final String paymentMethodId;
private final List<? extends PaymentTransactionJson> transactions;
+ private final List<PaymentAttemptJson> paymentAttempts;
@JsonCreator
public PaymentJson(@JsonProperty("accountId") final String accountId,
@@ -64,6 +66,7 @@ public class PaymentJson extends JsonBase {
@JsonProperty("currency") final String currency,
@JsonProperty("paymentMethodId") final String paymentMethodId,
@JsonProperty("transactions") final List<? extends PaymentTransactionJson> transactions,
+ @JsonProperty("paymentAttempts") final List<PaymentAttemptJson> paymentAttempts,
@JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs) {
super(auditLogs);
this.accountId = accountId;
@@ -78,6 +81,7 @@ public class PaymentJson extends JsonBase {
this.currency = currency;
this.paymentMethodId = paymentMethodId;
this.transactions = transactions;
+ this.paymentAttempts = paymentAttempts;
}
public PaymentJson(final Payment dp, @Nullable final AccountAuditLogs accountAuditLogs) {
@@ -93,6 +97,7 @@ public class PaymentJson extends JsonBase {
dp.getCurrency() != null ? dp.getCurrency().toString() : null,
dp.getPaymentMethodId() != null ? dp.getPaymentMethodId().toString() : null,
getTransactions(dp.getTransactions(), dp.getExternalKey(), accountAuditLogs),
+ getAttempts(dp.getPaymentAttempts(), dp.getExternalKey(), accountAuditLogs),
toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForPayment(dp.getId())));
}
@@ -108,6 +113,18 @@ public class PaymentJson extends JsonBase {
));
}
+ private static List<PaymentAttemptJson> getAttempts(final Iterable<PaymentAttempt> attempts, final String paymentExternalKey, @Nullable final AccountAuditLogs accountAuditLogs) {
+ return (attempts != null) ? ImmutableList.copyOf(Iterables.transform(attempts,
+ new Function<PaymentAttempt, PaymentAttemptJson>() {
+ @Override
+ public PaymentAttemptJson apply(final PaymentAttempt paymentAttempt) {
+ final List<AuditLog> auditLogsForPaymentAttempt = accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForPaymentAttempt(paymentAttempt.getId());
+ return new PaymentAttemptJson(paymentAttempt, paymentExternalKey, auditLogsForPaymentAttempt);
+ }
+ }
+ )) : null;
+ }
+
public String getAccountId() {
return accountId;
}
@@ -156,6 +173,8 @@ public class PaymentJson extends JsonBase {
return transactions;
}
+ public List<? extends PaymentAttemptJson> getPaymentAttempts() { return paymentAttempts; }
+
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("PaymentJson{");
@@ -171,6 +190,7 @@ public class PaymentJson extends JsonBase {
sb.append(", currency='").append(currency).append('\'');
sb.append(", paymentMethodId='").append(paymentMethodId).append('\'');
sb.append(", transactions=").append(transactions);
+ sb.append(", paymentAttempts=").append(paymentAttempts);
sb.append('}');
return sb.toString();
}
@@ -222,6 +242,9 @@ public class PaymentJson extends JsonBase {
if (transactions != null ? !transactions.equals(that.transactions) : that.transactions != null) {
return false;
}
+ if (paymentAttempts != null ? !paymentAttempts.equals(that.paymentAttempts) : that.paymentAttempts!= null) {
+ return false;
+ }
return true;
}
@@ -240,6 +263,7 @@ public class PaymentJson extends JsonBase {
result = 31 * result + (currency != null ? currency.hashCode() : 0);
result = 31 * result + (paymentMethodId != null ? paymentMethodId.hashCode() : 0);
result = 31 * result + (transactions != null ? transactions.hashCode() : 0);
+ result = 31 * result + (paymentAttempts != null ? paymentAttempts.hashCode() : 0);
return result;
}
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
index 2cd77b4..b97a2e8 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AccountResource.java
@@ -417,7 +417,7 @@ public class AccountResource extends JaxRsResourceBase {
final Callable<List<Payment>> paymentsCallable = new Callable<List<Payment>>() {
@Override
public List<Payment> call() throws Exception {
- return paymentApi.getAccountPayments(accountId, false, ImmutableList.<PluginProperty>of(), tenantContext);
+ return paymentApi.getAccountPayments(accountId, false, false, ImmutableList.<PluginProperty>of(), tenantContext);
}
};
final Callable<AccountAuditLogs> auditsCallable = new Callable<AccountAuditLogs>() {
@@ -635,13 +635,14 @@ public class AccountResource extends JaxRsResourceBase {
public Response getInvoicePayments(@PathParam("accountId") final String accountIdStr,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+ @QueryParam(QUERY_WITH_ATTEMPTS) @DefaultValue("false") final Boolean withAttempts,
@QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException, AccountApiException {
final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final UUID accountId = UUID.fromString(accountIdStr);
final TenantContext tenantContext = context.createContext(request);
final Account account = accountUserApi.getAccountById(accountId, tenantContext);
- final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), withPluginInfo, pluginProperties, tenantContext);
+ final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), withPluginInfo, withAttempts, pluginProperties, tenantContext);
final List<InvoicePayment> invoicePayments = invoicePaymentApi.getInvoicePaymentsByAccount(accountId, tenantContext);
final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(accountId, auditMode.getLevel(), tenantContext);
final List<InvoicePaymentJson> result = new ArrayList<InvoicePaymentJson>(payments.size());
@@ -848,11 +849,12 @@ public class AccountResource extends JaxRsResourceBase {
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+ @QueryParam(QUERY_WITH_ATTEMPTS) @DefaultValue("false") final Boolean withAttempts,
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
final UUID accountId = UUID.fromString(accountIdStr);
final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final TenantContext tenantContext = context.createContext(request);
- final List<Payment> payments = paymentApi.getAccountPayments(accountId, withPluginInfo, pluginProperties, tenantContext);
+ final List<Payment> payments = paymentApi.getAccountPayments(accountId, withPluginInfo, withAttempts, pluginProperties, tenantContext);
final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(accountId, auditMode.getLevel(), tenantContext);
final List<PaymentJson> result = ImmutableList.copyOf(Iterables.transform(payments, new Function<Payment, PaymentJson>() {
@Override
@@ -946,7 +948,7 @@ public class AccountResource extends JaxRsResourceBase {
//
final UUID paymentMethodId;
if (paymentId != null) {
- final Payment initialPayment = paymentApi.getPayment(paymentId, false, pluginProperties, callContext);
+ final Payment initialPayment = paymentApi.getPayment(paymentId, false, false, pluginProperties, callContext);
final PaymentTransaction pendingTransaction = lookupPendingTransaction(initialPayment,
json != null ? json.getTransactionId() : null,
json != null ? json.getTransactionExternalKey() : null,
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
index a1c6674..979d223 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
@@ -88,7 +88,7 @@ public class AdminResource extends JaxRsResourceBase {
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
- final Payment payment = paymentApi.getPayment(UUID.fromString(paymentIdStr), false, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment payment = paymentApi.getPayment(UUID.fromString(paymentIdStr), false, false, ImmutableList.<PluginProperty>of(), callContext);
final UUID paymentTransactionId = UUID.fromString(paymentTransactionIdStr);
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/ComboPaymentResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/ComboPaymentResource.java
index 6c87b6c..947e124 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/ComboPaymentResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/ComboPaymentResource.java
@@ -121,9 +121,9 @@ public abstract class ComboPaymentResource extends JaxRsResourceBase {
Preconditions.checkArgument(paymentIdStr != null || externalKey != null, "Need to set either paymentId or payment externalKey");
if (paymentIdStr != null) {
final UUID paymentId = UUID.fromString(paymentIdStr);
- return paymentApi.getPayment(paymentId, false, pluginProperties, tenantContext);
+ return paymentApi.getPayment(paymentId, false, false, pluginProperties, tenantContext);
} else {
- return paymentApi.getPaymentByExternalKey(externalKey, false, pluginProperties, tenantContext);
+ return paymentApi.getPaymentByExternalKey(externalKey, false, false, pluginProperties, tenantContext);
}
}
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
index c6372a4..1fb9dda 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
@@ -118,7 +118,7 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final UUID paymentIdId = UUID.fromString(paymentIdStr);
final TenantContext tenantContext = context.createContext(request);
- final Payment payment = paymentApi.getPayment(paymentIdId, withPluginInfo, pluginProperties, tenantContext);
+ final Payment payment = paymentApi.getPayment(paymentIdId, withPluginInfo, false, pluginProperties, tenantContext);
final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(payment.getAccountId(), auditMode.getLevel(), tenantContext);
final List<InvoicePayment> invoicePayments = invoicePaymentApi.getInvoicePayments(paymentIdId, tenantContext);
@@ -154,7 +154,7 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
final UUID paymentUuid = UUID.fromString(paymentId);
- final Payment payment = paymentApi.getPayment(paymentUuid, false, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment payment = paymentApi.getPayment(paymentUuid, false, false, ImmutableList.<PluginProperty>of(), callContext);
final Account account = accountUserApi.getAccountById(payment.getAccountId(), callContext);
final Iterable<PluginProperty> pluginProperties;
@@ -201,7 +201,7 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
final UUID paymentUuid = UUID.fromString(paymentId);
- final Payment payment = paymentApi.getPayment(paymentUuid, false, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment payment = paymentApi.getPayment(paymentUuid, false, false, ImmutableList.<PluginProperty>of(), callContext);
final Account account = accountUserApi.getAccountById(payment.getAccountId(), callContext);
final String transactionExternalKey = json.getTransactionExternalKey() != null ? json.getTransactionExternalKey() : UUIDs.randomUUID().toString();
@@ -230,7 +230,7 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
final UUID paymentUuid = UUID.fromString(paymentId);
- final Payment payment = paymentApi.getPayment(paymentUuid, false, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment payment = paymentApi.getPayment(paymentUuid, false, false, ImmutableList.<PluginProperty>of(), callContext);
final Account account = accountUserApi.getAccountById(payment.getAccountId(), callContext);
final Payment result = paymentApi.createChargebackReversalWithPaymentControl(account, payment.getId(), json.getTransactionExternalKey(), createInvoicePaymentControlPluginApiPaymentOptions(false), callContext);
@@ -299,7 +299,7 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final UUID paymentId = UUID.fromString(paymentIdString);
final TenantContext tenantContext = context.createContext(request);
- final Payment payment = paymentApi.getPayment(paymentId, false, pluginProperties, tenantContext);
+ final Payment payment = paymentApi.getPayment(paymentId, false, false, pluginProperties, tenantContext);
return super.getTags(payment.getAccountId(), paymentId, auditMode, includedDeleted, tenantContext);
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
index 9d7e63a..e754aef 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoiceResource.java
@@ -576,6 +576,7 @@ public class InvoiceResource extends JaxRsResourceBase {
public Response getPayments(@PathParam("invoiceId") final String invoiceId,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+ @QueryParam(QUERY_WITH_ATTEMPTS) @DefaultValue("false") final Boolean withAttempts,
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException, InvoiceApiException {
final TenantContext tenantContext = context.createContext(request);
@@ -594,7 +595,7 @@ public class InvoiceResource extends JaxRsResourceBase {
final List<Payment> payments = new ArrayList<Payment>();
for (final UUID paymentId : invoicePaymentIds) {
- final Payment payment = paymentApi.getPayment(paymentId, withPluginInfo, ImmutableList.<PluginProperty>of(), tenantContext);
+ final Payment payment = paymentApi.getPayment(paymentId, withPluginInfo, withAttempts, ImmutableList.<PluginProperty>of(), tenantContext);
payments.add(payment);
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
index db3dc47..3bd3536 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxrsResource.java
@@ -110,6 +110,7 @@ public interface JaxrsResource {
public static final String QUERY_PAYMENT_METHOD_PLUGIN_NAME = "pluginName";
public static final String QUERY_WITH_PLUGIN_INFO = "withPluginInfo";
+ public static final String QUERY_WITH_ATTEMPTS = "withAttempts";
public static final String QUERY_PAYMENT_METHOD_IS_DEFAULT = "isDefault";
public static final String QUERY_PAY_ALL_UNPAID_INVOICES = "payAllUnpaidInvoices";
@@ -127,6 +128,8 @@ public interface JaxrsResource {
public static final String QUERY_DELETE_DEFAULT_PM_WITH_AUTO_PAY_OFF = "deleteDefaultPmWithAutoPayOff";
+ public static final String QUERY_FORCE_DEFAULT_PM_DELETION = "forceDefaultPmDeletion";
+
public static final String QUERY_AUDIT = "audit";
public static final String QUERY_BCD = "bcd";
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
index ee5cf1a..92b5571 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/JaxRsResourceBase.java
@@ -339,8 +339,9 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
}
protected void validatePaymentMethodForAccount(final UUID accountId, final UUID paymentMethodId, final CallContext callContext) throws PaymentApiException {
- verifyNonNull(paymentMethodId, "paymentMethodId should be specified");
-
+ if (paymentMethodId == null) {
+ throw new PaymentApiException(ErrorCode.PAYMENT_NO_DEFAULT_PAYMENT_METHOD, accountId);
+ }
final PaymentMethod paymentMethod = paymentApi.getPaymentMethodById(paymentMethodId, false, false, ImmutableList.<PluginProperty>of(), callContext);
if (!paymentMethod.getAccountId().equals(accountId)) {
throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT_METHOD, paymentMethodId);
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentMethodResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentMethodResource.java
index a3cc105..a5b528b 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentMethodResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentMethodResource.java
@@ -259,6 +259,7 @@ public class PaymentMethodResource extends JaxRsResourceBase {
@ApiResponse(code = 404, message = "Account or payment method not found")})
public Response deletePaymentMethod(@PathParam("paymentMethodId") final String paymentMethodId,
@QueryParam(QUERY_DELETE_DEFAULT_PM_WITH_AUTO_PAY_OFF) @DefaultValue("false") final Boolean deleteDefaultPaymentMethodWithAutoPayOff,
+ @QueryParam(QUERY_FORCE_DEFAULT_PM_DELETION) @DefaultValue("false") final Boolean forceDefaultPaymentMethodDeletion,
@QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@HeaderParam(HDR_CREATED_BY) final String createdBy,
@HeaderParam(HDR_REASON) final String reason,
@@ -270,7 +271,7 @@ public class PaymentMethodResource extends JaxRsResourceBase {
final PaymentMethod paymentMethod = paymentApi.getPaymentMethodById(UUID.fromString(paymentMethodId), false, false, pluginProperties, callContext);
final Account account = accountUserApi.getAccountById(paymentMethod.getAccountId(), callContext);
- paymentApi.deletePaymentMethod(account, UUID.fromString(paymentMethodId), deleteDefaultPaymentMethodWithAutoPayOff, pluginProperties, callContext);
+ paymentApi.deletePaymentMethod(account, UUID.fromString(paymentMethodId), deleteDefaultPaymentMethodWithAutoPayOff, forceDefaultPaymentMethodDeletion, pluginProperties, callContext);
return Response.status(Status.OK).build();
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java
index 30775d3..876e7fe 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java
@@ -106,13 +106,14 @@ public class PaymentResource extends ComboPaymentResource {
@ApiResponse(code = 404, message = "Payment not found")})
public Response getPayment(@PathParam("paymentId") final String paymentIdStr,
@QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+ @QueryParam(QUERY_WITH_ATTEMPTS) @DefaultValue("false") final Boolean withAttempts,
@QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final UUID paymentIdId = UUID.fromString(paymentIdStr);
final TenantContext tenantContext = context.createContext(request);
- final Payment payment = paymentApi.getPayment(paymentIdId, withPluginInfo, pluginProperties, tenantContext);
+ final Payment payment = paymentApi.getPayment(paymentIdId, withPluginInfo, withAttempts, pluginProperties, tenantContext);
final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(payment.getAccountId(), auditMode.getLevel(), tenantContext);
final PaymentJson result = new PaymentJson(payment, accountAuditLogs);
return Response.status(Response.Status.OK).entity(result).build();
@@ -124,6 +125,7 @@ public class PaymentResource extends ComboPaymentResource {
@ApiOperation(value = "Retrieve a payment by external key", response = PaymentJson.class)
@ApiResponses(value = {@ApiResponse(code = 404, message = "Payment not found")})
public Response getPaymentByExternalKey(@QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+ @QueryParam(QUERY_WITH_ATTEMPTS) @DefaultValue("false") final Boolean withAttempts,
@QueryParam(QUERY_EXTERNAL_KEY) final String paymentExternalKey,
@QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@@ -131,7 +133,7 @@ public class PaymentResource extends ComboPaymentResource {
verifyNonNullOrEmpty(paymentExternalKey, "Payment externalKey needs to be specified");
final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final TenantContext tenantContext = context.createContext(request);
- final Payment payment = paymentApi.getPaymentByExternalKey(paymentExternalKey, withPluginInfo, pluginProperties, tenantContext);
+ final Payment payment = paymentApi.getPaymentByExternalKey(paymentExternalKey, withPluginInfo, withAttempts, pluginProperties, tenantContext);
final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(payment.getAccountId(), auditMode.getLevel(), tenantContext);
final PaymentJson result = new PaymentJson(payment, accountAuditLogs);
return Response.status(Response.Status.OK).entity(result).build();
@@ -149,15 +151,16 @@ public class PaymentResource extends ComboPaymentResource {
@QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+ @QueryParam(QUERY_WITH_ATTEMPTS) @DefaultValue("false") final Boolean withAttempts,
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final TenantContext tenantContext = context.createContext(request);
final Pagination<Payment> payments;
if (Strings.isNullOrEmpty(pluginName)) {
- payments = paymentApi.getPayments(offset, limit, withPluginInfo, pluginProperties, tenantContext);
+ payments = paymentApi.getPayments(offset, limit, withPluginInfo, withAttempts, pluginProperties, tenantContext);
} else {
- payments = paymentApi.getPayments(offset, limit, pluginName, withPluginInfo, pluginProperties, tenantContext);
+ payments = paymentApi.getPayments(offset, limit, pluginName, withPluginInfo, withAttempts, pluginProperties, tenantContext);
}
final URI nextPageUri = uriBuilder.nextPage(PaymentResource.class, "getPayments", payments.getNextOffset(), limit, ImmutableMap.<String, String>of(QUERY_PAYMENT_METHOD_PLUGIN_NAME, Strings.nullToEmpty(pluginName),
@@ -193,6 +196,7 @@ public class PaymentResource extends ComboPaymentResource {
@QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+ @QueryParam(QUERY_WITH_ATTEMPTS) @DefaultValue("false") final Boolean withAttempts,
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final TenantContext tenantContext = context.createContext(request);
@@ -200,9 +204,9 @@ public class PaymentResource extends ComboPaymentResource {
// Search the plugin(s)
final Pagination<Payment> payments;
if (Strings.isNullOrEmpty(pluginName)) {
- payments = paymentApi.searchPayments(searchKey, offset, limit, withPluginInfo, pluginProperties, tenantContext);
+ payments = paymentApi.searchPayments(searchKey, offset, limit, withPluginInfo, withAttempts, pluginProperties, tenantContext);
} else {
- payments = paymentApi.searchPayments(searchKey, offset, limit, pluginName, withPluginInfo, pluginProperties, tenantContext);
+ payments = paymentApi.searchPayments(searchKey, offset, limit, pluginName, withPluginInfo, withAttempts, pluginProperties, tenantContext);
}
final URI nextPageUri = uriBuilder.nextPage(PaymentResource.class, "searchPayments", payments.getNextOffset(), limit, ImmutableMap.<String, String>of("searchKey", searchKey,
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java
index 9a1dd1c..823f0fc 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/TransactionResource.java
@@ -95,7 +95,7 @@ public class TransactionResource extends JaxRsResourceBase {
final CallContext callContext = context.createContext(createdBy, reason, comment, request);
final UUID paymentId = UUID.fromString(json.getPaymentId());
- final Payment payment = paymentApi.getPayment(paymentId, false, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment payment = paymentApi.getPayment(paymentId, false, false, ImmutableList.<PluginProperty>of(), callContext);
final Account account = accountUserApi.getAccountById(payment.getAccountId(), callContext);
final boolean success = TransactionStatus.SUCCESS.name().equals(json.getStatus());
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPayment.java b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPayment.java
index 562889a..b16ba6b 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPayment.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPayment.java
@@ -53,18 +53,21 @@ public class DefaultPayment extends EntityBase implements Payment {
private final Currency currency;
private final List<PaymentTransaction> transactions;
+ private final List<PaymentAttempt> paymentAttempts;
public DefaultPayment(final UUID id, @Nullable final DateTime createdDate, @Nullable final DateTime updatedDate, final UUID accountId,
final UUID paymentMethodId,
final Integer paymentNumber,
final String externalKey,
- final List<PaymentTransaction> transactions) {
+ final List<PaymentTransaction> transactions,
+ final List<PaymentAttempt> paymentAttempts) {
super(id, createdDate, updatedDate);
this.accountId = accountId;
this.paymentMethodId = paymentMethodId;
this.paymentNumber = paymentNumber;
this.externalKey = externalKey;
this.transactions = transactions;
+ this.paymentAttempts = paymentAttempts;
final Collection<PaymentTransaction> voidedTransactions = new LinkedList<PaymentTransaction>();
final Collection<PaymentTransaction> nonVoidedTransactions = new LinkedList<PaymentTransaction>();
@@ -350,6 +353,9 @@ public class DefaultPayment extends EntityBase implements Payment {
}
@Override
+ public List<PaymentAttempt> getPaymentAttempts() { return paymentAttempts; }
+
+ @Override
public String toString() {
final StringBuilder sb = new StringBuilder("DefaultPayment{");
sb.append("accountId=").append(accountId);
@@ -362,6 +368,7 @@ public class DefaultPayment extends EntityBase implements Payment {
sb.append(", refundAmount=").append(refundAmount);
sb.append(", currency=").append(currency);
sb.append(", transactions=").append(transactions);
+ sb.append(", paymentAttempts=").append(paymentAttempts);
sb.append('}');
return sb.toString();
}
@@ -410,6 +417,9 @@ public class DefaultPayment extends EntityBase implements Payment {
if (transactions != null ? !transactions.equals(that.transactions) : that.transactions != null) {
return false;
}
+ if (paymentAttempts != null ? !paymentAttempts.equals(that.paymentAttempts) : that.paymentAttempts != null) {
+ return false;
+ }
return true;
}
@@ -427,6 +437,7 @@ public class DefaultPayment extends EntityBase implements Payment {
result = 31 * result + (refundAmount != null ? refundAmount.hashCode() : 0);
result = 31 * result + (currency != null ? currency.hashCode() : 0);
result = 31 * result + (transactions != null ? transactions.hashCode() : 0);
+ result = 31 * result + (paymentAttempts != null ? paymentAttempts.hashCode() : 0);
return result;
}
}
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java
index 22f3a2a..07c4669 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentApi.java
@@ -42,7 +42,6 @@ import org.killbill.billing.util.entity.Pagination;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@@ -297,7 +296,7 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
checkNotNullParameter(properties, "plugin properties");
if (paymentMethodId == null && !paymentOptions.isExternalPayment()) {
- throw new PaymentApiException(ErrorCode.PAYMENT_INVALID_PARAMETER, "paymentMethodId", "should not be null");
+ throw new PaymentApiException(ErrorCode.PAYMENT_NO_DEFAULT_PAYMENT_METHOD, "paymentMethodId", "should not be null");
}
final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
final UUID nonNulPaymentMethodId = (paymentMethodId != null) ?
@@ -783,23 +782,23 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
}
@Override
- public List<Payment> getAccountPayments(final UUID accountId, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext) throws PaymentApiException {
- return paymentProcessor.getAccountPayments(accountId, withPluginInfo, tenantContext, internalCallContextFactory.createInternalTenantContext(accountId, tenantContext));
+ public List<Payment> getAccountPayments(final UUID accountId, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext) throws PaymentApiException {
+ return paymentProcessor.getAccountPayments(accountId, withPluginInfo, withAttempts, tenantContext, internalCallContextFactory.createInternalTenantContext(accountId, tenantContext));
}
@Override
- public Pagination<Payment> getPayments(final Long offset, final Long limit, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext context) {
- return paymentProcessor.getPayments(offset, limit, withPluginInfo, properties, context, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(context));
+ public Pagination<Payment> getPayments(final Long offset, final Long limit, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext context) {
+ return paymentProcessor.getPayments(offset, limit, withPluginInfo, withAttempts, properties, context, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(context));
}
@Override
- public Pagination<Payment> getPayments(final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext) throws PaymentApiException {
- return paymentProcessor.getPayments(offset, limit, pluginName, withPluginInfo, properties, tenantContext, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(tenantContext));
+ public Pagination<Payment> getPayments(final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext) throws PaymentApiException {
+ return paymentProcessor.getPayments(offset, limit, pluginName, withPluginInfo, withAttempts, properties, tenantContext, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(tenantContext));
}
@Override
- public Payment getPayment(final UUID paymentId, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext context) throws PaymentApiException {
- final Payment payment = paymentProcessor.getPayment(paymentId, withPluginInfo, properties, context, internalCallContextFactory.createInternalTenantContext(paymentId, ObjectType.PAYMENT, context));
+ public Payment getPayment(final UUID paymentId, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext context) throws PaymentApiException {
+ final Payment payment = paymentProcessor.getPayment(paymentId, withPluginInfo, withAttempts, properties, context, internalCallContextFactory.createInternalTenantContext(paymentId, ObjectType.PAYMENT, context));
if (payment == null) {
throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT, paymentId);
}
@@ -807,9 +806,9 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
}
@Override
- public Payment getPaymentByExternalKey(final String paymentExternalKey, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext)
+ public Payment getPaymentByExternalKey(final String paymentExternalKey, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext)
throws PaymentApiException {
- final Payment payment = paymentProcessor.getPaymentByExternalKey(paymentExternalKey, withPluginInfo, properties, tenantContext, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(tenantContext));
+ final Payment payment = paymentProcessor.getPaymentByExternalKey(paymentExternalKey, withPluginInfo, withAttempts, properties, tenantContext, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(tenantContext));
if (payment == null) {
throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT, paymentExternalKey);
}
@@ -817,15 +816,14 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
}
@Override
- public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext context) {
- return paymentProcessor.searchPayments(searchKey, offset, limit, withPluginInfo, properties, context, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(context));
+ public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext context) {
+ return paymentProcessor.searchPayments(searchKey, offset, limit, withPluginInfo, withAttempts, properties, context, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(context));
}
@Override
- public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext context) throws PaymentApiException {
- return paymentProcessor.searchPayments(searchKey, offset, limit, pluginName, withPluginInfo, properties, context, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(context));
+ public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext context) throws PaymentApiException {
+ return paymentProcessor.searchPayments(searchKey, offset, limit, pluginName, withPluginInfo, withAttempts, properties, context, internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(context));
}
-
@Override
public UUID addPaymentMethod(final Account account, final String paymentMethodExternalKey, final String pluginName,
final boolean setDefault, final PaymentMethodPlugin paymentMethodInfo,
@@ -874,9 +872,9 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
}
@Override
- public void deletePaymentMethod(final Account account, final UUID paymentMethodId, final boolean deleteDefaultPaymentMethodWithAutoPayOff, final Iterable<PluginProperty> properties, final CallContext context)
+ public void deletePaymentMethod(final Account account, final UUID paymentMethodId, final boolean deleteDefaultPaymentMethodWithAutoPayOff, final boolean forceDefaultPaymentMethodDeletion, final Iterable<PluginProperty> properties, final CallContext context)
throws PaymentApiException {
- paymentMethodProcessor.deletedPaymentMethod(account, paymentMethodId, deleteDefaultPaymentMethodWithAutoPayOff, properties, context, internalCallContextFactory.createInternalCallContext(account.getId(), context));
+ paymentMethodProcessor.deletedPaymentMethod(account, paymentMethodId, deleteDefaultPaymentMethodWithAutoPayOff, forceDefaultPaymentMethodDeletion, properties, context, internalCallContextFactory.createInternalCallContext(account.getId(), context));
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentAttempt.java b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentAttempt.java
new file mode 100644
index 0000000..31384e6
--- /dev/null
+++ b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentAttempt.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2016 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.payment.api;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.killbill.billing.catalog.api.Currency;
+import org.killbill.billing.entity.EntityBase;
+
+public class DefaultPaymentAttempt extends EntityBase implements PaymentAttempt {
+
+ private final UUID accountId;
+ private final UUID paymentMethodId;
+ private final String paymentExternalKey;
+ private final UUID transactionId;
+ private final String transactionExternalKey;
+ private final TransactionType transactionType;
+ private final DateTime effectiveDate;
+ private final String stateName;
+ private final BigDecimal amount;
+ private final Currency currency;
+ private final String pluginName;
+ private final List<PluginProperty> pluginProperties;
+
+ public DefaultPaymentAttempt(final UUID accountId, final UUID paymentMethodId, final UUID id, final DateTime createdDate, final DateTime updatedDate,
+ final DateTime effectiveDate, final String paymentExternalKey, final UUID transactionId, final String transactionExternalKey,
+ final TransactionType transactionType, final String stateName, final BigDecimal amount, final Currency currency,
+ final String pluginName, final List<PluginProperty> pluginProperties) {
+ super(id, createdDate, updatedDate);
+ this.accountId = accountId;
+ this.paymentMethodId = paymentMethodId;
+ this.paymentExternalKey = paymentExternalKey;
+ this.transactionId = transactionId;
+ this.transactionExternalKey = transactionExternalKey;
+ this.transactionType = transactionType;
+ this.effectiveDate = effectiveDate;
+ this.stateName = stateName;
+ this.amount = amount;
+ this.currency = currency;
+ this.pluginName = pluginName;
+ this.pluginProperties = pluginProperties;
+ }
+
+ @Override
+ public UUID getAccountId() {
+ return accountId;
+ }
+
+ @Override
+ public UUID getPaymentMethodId() {
+ return paymentMethodId;
+ }
+
+ @Override
+ public String getPaymentExternalKey() {
+ return paymentExternalKey;
+ }
+
+ @Override
+ public UUID getTransactionId() {
+ return transactionId;
+ }
+
+ @Override
+ public String getTransactionExternalKey() {
+ return transactionExternalKey;
+ }
+
+ @Override
+ public TransactionType getTransactionType() {
+ return transactionType;
+ }
+
+ @Override
+ public DateTime getEffectiveDate() { return effectiveDate; }
+
+ @Override
+ public String getStateName() {
+ return stateName;
+ }
+
+ @Override
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ @Override
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ @Override
+ public String getPluginName() {
+ return pluginName;
+ }
+
+ @Override
+ public List<PluginProperty> getPluginProperties() {
+ return pluginProperties;
+ }
+
+ @Override
+ public String toString() {
+ return "DefaultPaymentAttempt{" +
+ "accountId=" + accountId +
+ ", paymentMethodId=" + paymentMethodId +
+ ", paymentExternalKey='" + paymentExternalKey + '\'' +
+ ", transactionId=" + transactionId +
+ ", transactionExternalKey='" + transactionExternalKey + '\'' +
+ ", transactionType=" + transactionType +
+ ", effectiveDate=" + effectiveDate +
+ ", stateName=" + stateName +
+ ", amount=" + amount +
+ ", currency=" + currency +
+ ", pluginName='" + pluginName + '\'' +
+ ", pluginProperties=" + pluginProperties +
+ '}';
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ final DefaultPaymentAttempt that = (DefaultPaymentAttempt) o;
+
+ if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
+ return false;
+ }
+ if (paymentMethodId != null ? !paymentMethodId.equals(that.paymentMethodId) : that.paymentMethodId != null) {
+ return false;
+ }
+ if (paymentExternalKey != null ? !paymentExternalKey.equals(that.paymentExternalKey) : that.paymentExternalKey != null) {
+ return false;
+ }
+ if (transactionId != null ? !transactionId.equals(that.transactionId) : that.transactionId != null) {
+ return false;
+ }
+ if (transactionExternalKey != null ? !transactionExternalKey.equals(that.transactionExternalKey) : that.transactionExternalKey != null) {
+ return false;
+ }
+ if (transactionType != that.transactionType) {
+ return false;
+ }
+ if (effectiveDate != null ? !effectiveDate.equals(that.effectiveDate) : that.effectiveDate != null) {
+ return false;
+ }
+ if (stateName != null ? !stateName.equals(that.stateName) : that.stateName != null) {
+ return false;
+ }
+ if (amount != null ? !amount.equals(that.amount) : that.amount != null) {
+ return false;
+ }
+ if (currency != that.currency) {
+ return false;
+ }
+ if (pluginName != null ? !pluginName.equals(that.pluginName) : that.pluginName != null) {
+ return false;
+ }
+ return pluginProperties != null ? pluginProperties.equals(that.pluginProperties) : that.pluginProperties == null;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+ result = 31 * result + (paymentMethodId != null ? paymentMethodId.hashCode() : 0);
+ result = 31 * result + (paymentExternalKey != null ? paymentExternalKey.hashCode() : 0);
+ result = 31 * result + (transactionId != null ? transactionId.hashCode() : 0);
+ result = 31 * result + (transactionExternalKey != null ? transactionExternalKey.hashCode() : 0);
+ result = 31 * result + (transactionType != null ? transactionType.hashCode() : 0);
+ result = 31 * result + (effectiveDate != null ? effectiveDate.hashCode() : 0);
+ result = 31 * result + (stateName != null ? stateName.hashCode() : 0);
+ result = 31 * result + (amount != null ? amount.hashCode() : 0);
+ result = 31 * result + (currency != null ? currency.hashCode() : 0);
+ result = 31 * result + (pluginName != null ? pluginName.hashCode() : 0);
+ result = 31 * result + (pluginProperties != null ? pluginProperties.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
index f45ee2d..34e881b 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
@@ -399,6 +399,7 @@ public class PaymentMethodProcessor extends ProcessorBase {
public void deletedPaymentMethod(final Account account, final UUID paymentMethodId,
final boolean deleteDefaultPaymentMethodWithAutoPayOff,
+ final boolean forceDefaultPaymentMethodDeletion,
final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext context)
throws PaymentApiException {
try {
@@ -414,11 +415,10 @@ public class PaymentMethodProcessor extends ProcessorBase {
try {
// Note: account.getPaymentMethodId() may be null
if (paymentMethodId.equals(account.getPaymentMethodId())) {
- if (!deleteDefaultPaymentMethodWithAutoPayOff) {
+ if (!deleteDefaultPaymentMethodWithAutoPayOff && !forceDefaultPaymentMethodDeletion) {
throw new PaymentApiException(ErrorCode.PAYMENT_DEL_DEFAULT_PAYMENT_METHOD, account.getId());
} else {
- final boolean isAccountAutoPayOff = isAccountAutoPayOff(account.getId(), context);
- if (!isAccountAutoPayOff) {
+ if (deleteDefaultPaymentMethodWithAutoPayOff && !isAccountAutoPayOff(account.getId(), context)) {
log.info("Setting AUTO_PAY_OFF on accountId='{}' because of default payment method deletion", account.getId());
setAccountAutoPayOff(account.getId(), context);
}
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
index decfbd4..a2ef19c 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
@@ -19,6 +19,7 @@
package org.killbill.billing.payment.core;
import java.math.BigDecimal;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
@@ -42,9 +43,11 @@ import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.invoice.api.InvoiceInternalApi;
import org.killbill.billing.osgi.api.OSGIServiceRegistration;
import org.killbill.billing.payment.api.DefaultPayment;
+import org.killbill.billing.payment.api.DefaultPaymentAttempt;
import org.killbill.billing.payment.api.DefaultPaymentTransaction;
import org.killbill.billing.payment.api.Payment;
import org.killbill.billing.payment.api.PaymentApiException;
+import org.killbill.billing.payment.api.PaymentAttempt;
import org.killbill.billing.payment.api.PaymentTransaction;
import org.killbill.billing.payment.api.PluginProperty;
import org.killbill.billing.payment.api.TransactionStatus;
@@ -52,13 +55,19 @@ import org.killbill.billing.payment.api.TransactionType;
import org.killbill.billing.payment.core.janitor.IncompletePaymentTransactionTask;
import org.killbill.billing.payment.core.sm.PaymentAutomatonDAOHelper;
import org.killbill.billing.payment.core.sm.PaymentAutomatonRunner;
+import org.killbill.billing.payment.dao.PaymentAttemptModelDao;
import org.killbill.billing.payment.core.sm.PaymentStateContext;
import org.killbill.billing.payment.dao.PaymentDao;
import org.killbill.billing.payment.dao.PaymentModelDao;
import org.killbill.billing.payment.dao.PaymentTransactionModelDao;
+import org.killbill.billing.payment.dao.PluginPropertySerializer;
+import org.killbill.billing.payment.dao.PluginPropertySerializer.PluginPropertySerializerException;
+import org.killbill.billing.payment.glue.DefaultPaymentService;
import org.killbill.billing.payment.plugin.api.PaymentPluginApi;
import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.billing.payment.retry.DefaultRetryService;
+import org.killbill.billing.payment.retry.PaymentRetryNotificationKey;
import org.killbill.billing.tag.TagInternalApi;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
@@ -69,6 +78,11 @@ import org.killbill.billing.util.entity.dao.DefaultPaginationHelper.EntityPagina
import org.killbill.billing.util.entity.dao.DefaultPaginationHelper.SourcePaginationBuilder;
import org.killbill.clock.Clock;
import org.killbill.commons.locker.GlobalLocker;
+import org.killbill.notificationq.api.NotificationEvent;
+import org.killbill.notificationq.api.NotificationEventWithMetadata;
+import org.killbill.notificationq.api.NotificationQueue;
+import org.killbill.notificationq.api.NotificationQueueService;
+import org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificationQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -90,9 +104,13 @@ public class PaymentProcessor extends ProcessorBase {
private final PaymentAutomatonRunner paymentAutomatonRunner;
private final IncompletePaymentTransactionTask incompletePaymentTransactionTask;
+ private final NotificationQueueService notificationQueueService;
private static final Logger log = LoggerFactory.getLogger(PaymentProcessor.class);
+ public static final String SCHEDULED = "SCHEDULED";
+
+
@Inject
public PaymentProcessor(final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry,
final AccountInternalApi accountUserApi,
@@ -103,10 +121,12 @@ public class PaymentProcessor extends ProcessorBase {
final GlobalLocker locker,
final PaymentAutomatonRunner paymentAutomatonRunner,
final IncompletePaymentTransactionTask incompletePaymentTransactionTask,
+ final NotificationQueueService notificationQueueService,
final Clock clock) {
super(pluginRegistry, accountUserApi, paymentDao, tagUserApi, locker, internalCallContextFactory, invoiceApi, clock);
this.paymentAutomatonRunner = paymentAutomatonRunner;
this.incompletePaymentTransactionTask = incompletePaymentTransactionTask;
+ this.notificationQueueService = notificationQueueService;
}
public Payment createAuthorization(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, @Nullable final UUID paymentMethodId, @Nullable final UUID paymentId, final BigDecimal amount, final Currency currency,
@@ -168,7 +188,7 @@ public class PaymentProcessor extends ProcessorBase {
overridePluginResult, PLUGIN_PROPERTIES, callContext, internalCallContext);
}
- public List<Payment> getAccountPayments(final UUID accountId, final boolean withPluginInfo, final TenantContext context, final InternalTenantContext tenantContext) throws PaymentApiException {
+ public List<Payment> getAccountPayments(final UUID accountId, final boolean withPluginInfo, final boolean withAttempts, final TenantContext context, final InternalTenantContext tenantContext) throws PaymentApiException {
final List<PaymentModelDao> paymentsModelDao = paymentDao.getPaymentsForAccount(accountId, tenantContext);
final List<PaymentTransactionModelDao> transactionsModelDao = paymentDao.getTransactionsForAccount(accountId, tenantContext);
@@ -195,7 +215,7 @@ public class PaymentProcessor extends ProcessorBase {
pluginInfo = getPaymentTransactionInfoPluginsIfNeeded(pluginApi, paymentModelDao, context);
}
- return toPayment(paymentModelDao, transactionsModelDao, pluginInfo, tenantContext);
+ return toPayment(paymentModelDao, transactionsModelDao, pluginInfo, withAttempts, tenantContext);
}
});
@@ -203,24 +223,24 @@ public class PaymentProcessor extends ProcessorBase {
return ImmutableList.<Payment>copyOf(transformedPayments);
}
- public Payment getPayment(final UUID paymentId, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
+ public Payment getPayment(final UUID paymentId, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
final PaymentModelDao paymentModelDao = paymentDao.getPayment(paymentId, internalTenantContext);
if (paymentModelDao == null) {
return null;
}
- return toPayment(paymentModelDao, withPluginInfo, properties, tenantContext, internalTenantContext);
+ return toPayment(paymentModelDao, withPluginInfo, withAttempts, properties, tenantContext, internalTenantContext);
}
- public Payment getPaymentByExternalKey(final String paymentExternalKey, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
+ public Payment getPaymentByExternalKey(final String paymentExternalKey, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
final PaymentModelDao paymentModelDao = paymentDao.getPaymentByExternalKey(paymentExternalKey, internalTenantContext);
if (paymentModelDao == null) {
return null;
}
- return toPayment(paymentModelDao, withPluginInfo, properties, tenantContext, internalTenantContext);
+ return toPayment(paymentModelDao, withPluginInfo, withAttempts, properties, tenantContext, internalTenantContext);
}
- public Pagination<Payment> getPayments(final Long offset, final Long limit, final boolean withPluginInfo, final Iterable<PluginProperty> properties,
- final TenantContext tenantContext, final InternalTenantContext internalTenantContext) {
+ public Pagination<Payment> getPayments(final Long offset, final Long limit, final boolean withPluginInfo, final boolean withAttempts,
+ final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) {
return getEntityPaginationFromPlugins(true,
getAvailablePlugins(),
offset,
@@ -228,13 +248,13 @@ public class PaymentProcessor extends ProcessorBase {
new EntityPaginationBuilder<Payment, PaymentApiException>() {
@Override
public Pagination<Payment> build(final Long offset, final Long limit, final String pluginName) throws PaymentApiException {
- return getPayments(offset, limit, pluginName, withPluginInfo, properties, tenantContext, internalTenantContext);
+ return getPayments(offset, limit, pluginName, withPluginInfo, withAttempts, properties, tenantContext, internalTenantContext);
}
}
);
}
- public Pagination<Payment> getPayments(final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
+ public Pagination<Payment> getPayments(final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
final PaymentPluginApi pluginApi = withPluginInfo ? getPaymentPluginApi(pluginName) : null;
return getEntityPagination(limit,
@@ -249,13 +269,13 @@ public class PaymentProcessor extends ProcessorBase {
@Override
public Payment apply(final PaymentModelDao paymentModelDao) {
final List<PaymentTransactionInfoPlugin> pluginInfo = getPaymentTransactionInfoPluginsIfNeeded(pluginApi, paymentModelDao, tenantContext);
- return toPayment(paymentModelDao.getId(), pluginInfo, internalTenantContext);
+ return toPayment(paymentModelDao.getId(), pluginInfo, withAttempts, internalTenantContext);
}
}
);
}
- public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) {
+ public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) {
if (withPluginInfo) {
return getEntityPaginationFromPlugins(false,
getAvailablePlugins(),
@@ -264,7 +284,7 @@ public class PaymentProcessor extends ProcessorBase {
new EntityPaginationBuilder<Payment, PaymentApiException>() {
@Override
public Pagination<Payment> build(final Long offset, final Long limit, final String pluginName) throws PaymentApiException {
- return searchPayments(searchKey, offset, limit, pluginName, withPluginInfo, properties, tenantContext, internalTenantContext);
+ return searchPayments(searchKey, offset, limit, pluginName, withPluginInfo, withAttempts, properties, tenantContext, internalTenantContext);
}
}
);
@@ -280,7 +300,7 @@ public class PaymentProcessor extends ProcessorBase {
new Function<PaymentModelDao, Payment>() {
@Override
public Payment apply(final PaymentModelDao paymentModelDao) {
- return toPayment(paymentModelDao.getId(), null, internalTenantContext);
+ return toPayment(paymentModelDao.getId(), null, withAttempts, internalTenantContext);
}
}
);
@@ -291,7 +311,8 @@ public class PaymentProcessor extends ProcessorBase {
}
}
- public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
+ public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo,
+ final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
final PaymentPluginApi pluginApi = getPaymentPluginApi(pluginName);
return getEntityPagination(limit,
@@ -322,7 +343,7 @@ public class PaymentProcessor extends ProcessorBase {
cachedPaymentTransactions.add(pluginTransaction);
return null;
} else {
- final Payment result = toPayment(pluginTransaction.getKbPaymentId(), withPluginInfo ? ImmutableList.<PaymentTransactionInfoPlugin>copyOf(cachedPaymentTransactions) : ImmutableList.<PaymentTransactionInfoPlugin>of(), internalTenantContext);
+ final Payment result = toPayment(pluginTransaction.getKbPaymentId(), withPluginInfo ? ImmutableList.<PaymentTransactionInfoPlugin>copyOf(cachedPaymentTransactions) : ImmutableList.<PaymentTransactionInfoPlugin>of(), withAttempts, internalTenantContext);
cachedPaymentTransactions.clear();
cachedPaymentTransactions.add(pluginTransaction);
return result;
@@ -436,14 +457,9 @@ public class PaymentProcessor extends ProcessorBase {
currentStateName = paymentModelDao.getLastSuccessStateName();
}
- // Sanity: no paymentMethodId was passed through API and account does not have a default paymentMethodId
- if (paymentStateContext.getPaymentMethodId() == null) {
- throw new PaymentApiException(ErrorCode.PAYMENT_NO_DEFAULT_PAYMENT_METHOD, paymentStateContext.getAccount().getId());
- }
-
final UUID nonNullPaymentId = paymentAutomatonRunner.run(paymentStateContext, daoHelper, currentStateName, transactionType);
- return getPayment(nonNullPaymentId, true, properties, callContext, internalCallContext);
+ return getPayment(nonNullPaymentId, true, false, properties, callContext, internalCallContext);
}
private PaymentTransactionModelDao findTransactionToCompleteAndRunSanityChecks(final PaymentModelDao paymentModelDao,
@@ -524,29 +540,30 @@ public class PaymentProcessor extends ProcessorBase {
}
// Used in bulk get APIs (getPayments / searchPayments)
- private Payment toPayment(final UUID paymentId, @Nullable final Iterable<PaymentTransactionInfoPlugin> pluginTransactions, final InternalTenantContext tenantContext) {
+ private Payment toPayment(final UUID paymentId, @Nullable final Iterable<PaymentTransactionInfoPlugin> pluginTransactions, final boolean withAttempts, final InternalTenantContext tenantContext) {
final PaymentModelDao paymentModelDao = paymentDao.getPayment(paymentId, tenantContext);
if (paymentModelDao == null) {
log.warn("Unable to find payment id " + paymentId);
return null;
}
- return toPayment(paymentModelDao, pluginTransactions, tenantContext);
+ return toPayment(paymentModelDao, pluginTransactions, withAttempts, tenantContext);
}
// Used in single get APIs (getPayment / getPaymentByExternalKey)
- private Payment toPayment(final PaymentModelDao paymentModelDao, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext context, final InternalTenantContext tenantContext) throws PaymentApiException {
+ private Payment toPayment(final PaymentModelDao paymentModelDao, final boolean withPluginInfo, final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext context, final InternalTenantContext tenantContext) throws PaymentApiException {
final PaymentPluginApi plugin = getPaymentProviderPlugin(paymentModelDao.getPaymentMethodId(), tenantContext);
final List<PaymentTransactionInfoPlugin> pluginTransactions = withPluginInfo ? getPaymentTransactionInfoPlugins(plugin, paymentModelDao, properties, context) : null;
- return toPayment(paymentModelDao, pluginTransactions, tenantContext);
+ return toPayment(paymentModelDao, pluginTransactions, withAttempts, tenantContext);
}
- private Payment toPayment(final PaymentModelDao paymentModelDao, @Nullable final Iterable<PaymentTransactionInfoPlugin> pluginTransactions, final InternalTenantContext tenantContext) {
+ private Payment toPayment(final PaymentModelDao paymentModelDao, @Nullable final Iterable<PaymentTransactionInfoPlugin> pluginTransactions,
+ final boolean withAttempts, final InternalTenantContext tenantContext) {
final InternalTenantContext tenantContextWithAccountRecordId = getInternalTenantContextWithAccountRecordId(paymentModelDao.getAccountId(), tenantContext);
final List<PaymentTransactionModelDao> transactionsForPayment = paymentDao.getTransactionsForPayment(paymentModelDao.getId(), tenantContextWithAccountRecordId);
- return toPayment(paymentModelDao, transactionsForPayment, pluginTransactions, tenantContextWithAccountRecordId);
+ return toPayment(paymentModelDao, transactionsForPayment, pluginTransactions, withAttempts, tenantContextWithAccountRecordId);
}
private PaymentModelDao invokeJanitor(final PaymentModelDao curPaymentModelDao, final Collection<PaymentTransactionModelDao> curTransactionsModelDao, @Nullable final Iterable<PaymentTransactionInfoPlugin> pluginTransactions, final InternalTenantContext internalTenantContext) {
@@ -584,9 +601,9 @@ public class PaymentProcessor extends ProcessorBase {
}
// Used in bulk get API (getAccountPayments)
- private Payment toPayment(final PaymentModelDao curPaymentModelDao, final Collection<PaymentTransactionModelDao> curTransactionsModelDao, @Nullable final Iterable<PaymentTransactionInfoPlugin> pluginTransactions, final InternalTenantContext internalTenantContext) {
+ private Payment toPayment(final PaymentModelDao curPaymentModelDao, final Collection<PaymentTransactionModelDao> curTransactionsModelDao, @Nullable final Iterable<PaymentTransactionInfoPlugin> pluginTransactions, final boolean withAttempts, final InternalTenantContext internalTenantContext) {
final Collection<PaymentTransactionModelDao> transactionsModelDao = new LinkedList<PaymentTransactionModelDao>(curTransactionsModelDao);
- final PaymentModelDao newPaymentModelDao = invokeJanitor(curPaymentModelDao, transactionsModelDao, pluginTransactions, internalTenantContext);
+ invokeJanitor(curPaymentModelDao, transactionsModelDao, pluginTransactions, internalTenantContext);
final Collection<PaymentTransaction> transactions = new LinkedList<PaymentTransaction>();
for (final PaymentTransactionModelDao newPaymentTransactionModelDao : transactionsModelDao) {
@@ -617,15 +634,103 @@ public class PaymentProcessor extends ProcessorBase {
}
});
final List<PaymentTransaction> sortedTransactions = perPaymentTransactionOrdering.immutableSortedCopy(transactions);
+ return new DefaultPayment(curPaymentModelDao.getId(),
+ curPaymentModelDao.getCreatedDate(),
+ curPaymentModelDao.getUpdatedDate(),
+ curPaymentModelDao.getAccountId(),
+ curPaymentModelDao.getPaymentMethodId(),
+ curPaymentModelDao.getPaymentNumber(),
+ curPaymentModelDao.getExternalKey(),
+ sortedTransactions,
+ (withAttempts && !sortedTransactions.isEmpty()) ?
+ getPaymentAttempts(paymentDao.getPaymentAttempts(curPaymentModelDao.getExternalKey(), internalTenantContext),
+ internalTenantContext) : null
+ );
+ }
+
+ private List<PaymentAttempt> getPaymentAttempts(final List<PaymentAttemptModelDao> pastPaymentAttempts,
+ final InternalTenantContext internalTenantContext) {
+
+ List<PaymentAttempt> paymentAttempts = new ArrayList<PaymentAttempt>();
+
+ // Add Past Payment Attempts
+ for (PaymentAttemptModelDao pastPaymentAttempt : pastPaymentAttempts) {
+ DefaultPaymentAttempt paymentAttempt = new DefaultPaymentAttempt(
+ pastPaymentAttempt.getAccountId(),
+ pastPaymentAttempt.getPaymentMethodId(),
+ pastPaymentAttempt.getId(),
+ pastPaymentAttempt.getCreatedDate(),
+ pastPaymentAttempt.getUpdatedDate(),
+ pastPaymentAttempt.getCreatedDate(),
+ pastPaymentAttempt.getPaymentExternalKey(),
+ pastPaymentAttempt.getTransactionId(),
+ pastPaymentAttempt.getTransactionExternalKey(),
+ pastPaymentAttempt.getTransactionType(),
+ pastPaymentAttempt.getStateName(),
+ pastPaymentAttempt.getAmount(),
+ pastPaymentAttempt.getCurrency(),
+ pastPaymentAttempt.getPluginName(),
+ buildPluginProperties(pastPaymentAttempt));
+ paymentAttempts.add(paymentAttempt);
+ }
+
+ // Get Future Payment Attempts from Notification Queue and add them to the list
+ try {
+ final NotificationQueue retryQueue = notificationQueueService.getNotificationQueue(DefaultPaymentService.SERVICE_NAME, DefaultRetryService.QUEUE_NAME);
+ final List<NotificationEventWithMetadata<NotificationEvent>> notificationEventWithMetadatas =
+ retryQueue.getFutureNotificationForSearchKeys(internalTenantContext.getAccountRecordId(), internalTenantContext.getTenantRecordId());
+
+ for (final NotificationEventWithMetadata<NotificationEvent> notificationEvent : notificationEventWithMetadatas) {
+ // Last Attempt
+ PaymentAttemptModelDao lastPaymentAttempt = getLastPaymentAttempt(pastPaymentAttempts,
+ ((PaymentRetryNotificationKey) notificationEvent.getEvent()).getAttemptId());
+
+ if (lastPaymentAttempt != null) {
+ DefaultPaymentAttempt futurePaymentAttempt = new DefaultPaymentAttempt(
+ lastPaymentAttempt.getAccountId(), // accountId
+ lastPaymentAttempt.getPaymentMethodId(), // paymentMethodId
+ ((PaymentRetryNotificationKey) notificationEvent.getEvent()).getAttemptId(), // id
+ null, // createdDate
+ null, // updatedDate
+ notificationEvent.getEffectiveDate(), // effectiveDate
+ lastPaymentAttempt.getPaymentExternalKey(), // paymentExternalKey
+ null, // transactionId
+ lastPaymentAttempt.getTransactionExternalKey(), // transactionExternalKey
+ lastPaymentAttempt.getTransactionType(), // transactionType
+ SCHEDULED, // stateName
+ lastPaymentAttempt.getAmount(), // amount
+ lastPaymentAttempt.getCurrency(), // currency
+ ((PaymentRetryNotificationKey) notificationEvent.getEvent()).getPaymentControlPluginNames().get(0), // pluginName,
+ buildPluginProperties(lastPaymentAttempt)); // pluginProperties
+ paymentAttempts.add(futurePaymentAttempt);
+ }
+ }
+ } catch (NoSuchNotificationQueue noSuchNotificationQueue) {
+ log.error("ERROR Loading Notification Queue - " + noSuchNotificationQueue.getMessage());
+ }
+ return paymentAttempts;
+ }
- return new DefaultPayment(newPaymentModelDao.getId(),
- newPaymentModelDao.getCreatedDate(),
- newPaymentModelDao.getUpdatedDate(),
- newPaymentModelDao.getAccountId(),
- newPaymentModelDao.getPaymentMethodId(),
- newPaymentModelDao.getPaymentNumber(),
- newPaymentModelDao.getExternalKey(),
- sortedTransactions);
+ private PaymentAttemptModelDao getLastPaymentAttempt(final List<PaymentAttemptModelDao> pastPaymentAttempts, final UUID attemptId) {
+ if (!pastPaymentAttempts.isEmpty()) {
+ for (int i = pastPaymentAttempts.size() - 1; i == 0; i--) {
+ if (pastPaymentAttempts.get(i).getId().equals(attemptId)) {
+ return pastPaymentAttempts.get(i);
+ }
+ }
+ }
+ return null;
+ }
+
+ private List<PluginProperty> buildPluginProperties(final PaymentAttemptModelDao pastPaymentAttempt) {
+ if (pastPaymentAttempt.getPluginProperties() != null) {
+ try {
+ return Lists.newArrayList(PluginPropertySerializer.deserialize(pastPaymentAttempt.getPluginProperties()));
+ } catch (PluginPropertySerializerException e) {
+ log.error("ERROR Deserializing Plugin Properties - " + e.getMessage());
+ }
+ }
+ return null;
}
private PaymentTransactionInfoPlugin findPaymentTransactionInfoPlugin(final PaymentTransactionModelDao paymentTransactionModelDao, @Nullable final Iterable<PaymentTransactionInfoPlugin> pluginTransactions) {
diff --git a/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java b/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java
index 9ba3edc..912d736 100644
--- a/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java
@@ -306,6 +306,21 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
final BigDecimal requestedAmount = validateAndComputePaymentAmount(invoice, paymentControlPluginContext.getAmount(), paymentControlPluginContext.isApiPayment());
final boolean isAborted = requestedAmount.compareTo(BigDecimal.ZERO) == 0;
+
+ if (!isAborted && paymentControlPluginContext.getPaymentMethodId() == null) {
+ log.warn("Payment for invoiceId='{}' was not triggered, accountId='{}' doesn't have a default payment method", getInvoiceId(pluginProperties), paymentControlPluginContext.getAccountId());
+ invoiceApi.recordPaymentAttemptCompletion(invoiceId,
+ paymentControlPluginContext.getAmount(),
+ paymentControlPluginContext.getCurrency(),
+ paymentControlPluginContext.getProcessedCurrency(),
+ paymentControlPluginContext.getPaymentId(),
+ paymentControlPluginContext.getTransactionExternalKey(),
+ paymentControlPluginContext.getCreatedDate(),
+ false,
+ internalContext);
+ return new DefaultPriorPaymentControlResult(true);
+ }
+
if (!isAborted && insert_AUTO_PAY_OFF_ifRequired(paymentControlPluginContext, requestedAmount)) {
return new DefaultPriorPaymentControlResult(true);
}
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestDefaultPayment.java b/payment/src/test/java/org/killbill/billing/payment/api/TestDefaultPayment.java
index 6bf1743..85e0a0a 100644
--- a/payment/src/test/java/org/killbill/billing/payment/api/TestDefaultPayment.java
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestDefaultPayment.java
@@ -220,6 +220,7 @@ public class TestDefaultPayment extends PaymentTestSuiteNoDB {
UUID.randomUUID(),
1,
UUID.randomUUID().toString(),
- transactions);
+ transactions,
+ null);
}
}
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestExternalPaymentPlugin.java b/payment/src/test/java/org/killbill/billing/payment/api/TestExternalPaymentPlugin.java
index 2e6f46e..589ec38 100644
--- a/payment/src/test/java/org/killbill/billing/payment/api/TestExternalPaymentPlugin.java
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestExternalPaymentPlugin.java
@@ -60,8 +60,8 @@ public class TestExternalPaymentPlugin extends PaymentTestSuiteWithEmbeddedDB {
final Payment payment = paymentApi.createPurchase(account, account.getPaymentMethodId(), null, requestedAmount, Currency.AED, paymentExternalKey, transactionExternalKey,
ImmutableList.<PluginProperty>of(), callContext);
- final Payment paymentPluginInfoFalse = paymentApi.getPayment(payment.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
- final Payment paymentPluginInfoTrue = paymentApi.getPayment(payment.getId(), true, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment paymentPluginInfoFalse = paymentApi.getPayment(payment.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment paymentPluginInfoTrue = paymentApi.getPayment(payment.getId(), true, false, ImmutableList.<PluginProperty>of(), callContext);
Assert.assertEquals(paymentPluginInfoFalse.getAccountId(), paymentPluginInfoTrue.getAccountId());
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
index 1b24f8b..16a43e7 100644
--- a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
@@ -147,12 +147,43 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
checkPaymentMethodPagination(paymentMethodId, baseNbRecords + 1, false);
- paymentApi.deletePaymentMethod(account, paymentMethodId, true, ImmutableList.<PluginProperty>of(), callContext);
+ paymentApi.deletePaymentMethod(account, paymentMethodId, true, false, ImmutableList.<PluginProperty>of(), callContext);
checkPaymentMethodPagination(paymentMethodId, baseNbRecords, true);
}
@Test(groups = "slow")
+ public void testAddRemovePaymentMethodWithForcedDeletion() throws Exception {
+ final Long baseNbRecords = paymentApi.getPaymentMethods(0L, 1000L, false, ImmutableList.<PluginProperty>of(), callContext).getMaxNbRecords();
+ Assert.assertEquals(baseNbRecords, (Long) 1L);
+
+ final Account account = testHelper.createTestAccount(UUID.randomUUID().toString(), true);
+ final UUID paymentMethodId = account.getPaymentMethodId();
+
+ checkPaymentMethodPagination(paymentMethodId, baseNbRecords + 1, false);
+
+ paymentApi.deletePaymentMethod(account, paymentMethodId, false, true, ImmutableList.<PluginProperty>of(), callContext);
+
+ checkPaymentMethodPagination(paymentMethodId, baseNbRecords, true);
+ }
+
+ @Test(groups = "slow")
+ public void testAddRemovePaymentMethodWithoutForcedDeletion() throws Exception {
+ final Long baseNbRecords = paymentApi.getPaymentMethods(0L, 1000L, false, ImmutableList.<PluginProperty>of(), callContext).getMaxNbRecords();
+ Assert.assertEquals(baseNbRecords, (Long) 1L);
+
+ final Account account = testHelper.createTestAccount(UUID.randomUUID().toString(), true);
+ final UUID paymentMethodId = account.getPaymentMethodId();
+
+ try {
+ paymentApi.deletePaymentMethod(account, paymentMethodId, false, false, ImmutableList.<PluginProperty>of(), callContext);
+ } catch (final PaymentApiException e) {
+ Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INTERNAL_ERROR.getCode());
+ }
+ checkPaymentMethodPagination(paymentMethodId, baseNbRecords + 1, false);
+ }
+
+ @Test(groups = "slow")
public void testCreateSuccessPurchase() throws PaymentApiException {
final BigDecimal requestedAmount = BigDecimal.TEN;
@@ -871,7 +902,7 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
}
- final List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
assertEquals(accountPayments.size(), 1);
final Payment payment = accountPayments.get(0);
assertEquals(payment.getExternalKey(), paymentExternalKey);
@@ -928,7 +959,7 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
}
- final List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
assertEquals(accountPayments.size(), 1);
final Payment payment = accountPayments.get(0);
assertEquals(payment.getExternalKey(), paymentExternalKey);
@@ -956,7 +987,7 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
createPropertiesForInvoice(invoice), INVOICE_PAYMENT, callContext);
- final List<Payment> accountPayments2 = paymentApi.getAccountPayments(account.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final List<Payment> accountPayments2 = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
assertEquals(accountPayments2.size(), 1);
final Payment payment2 = accountPayments2.get(0);
assertEquals(payment2.getTransactions().size(), 2);
@@ -1420,7 +1451,7 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
assertEquals(e.getCode(), ErrorCode.PAYMENT_NO_SUCH_SUCCESS_PAYMENT.getCode());
}
- assertEquals(paymentApi.getPayment(payment.getId(), false, ImmutableList.<PluginProperty>of(), callContext).getTransactions().size(), 1);
+ assertEquals(paymentApi.getPayment(payment.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext).getTransactions().size(), 1);
assertEquals(paymentDao.getPayment(payment.getId(), internalCallContext).getStateName(), "PURCHASE_SUCCESS");
assertEquals(paymentDao.getPayment(payment.getId(), internalCallContext).getLastSuccessStateName(), "PURCHASE_SUCCESS");
@@ -1509,7 +1540,7 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
} catch (final PaymentApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_NO_SUCH_PAYMENT.getCode());
- final Payment latestPayment = paymentApi.getPayment(initialPayment.getId(), true, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment latestPayment = paymentApi.getPayment(initialPayment.getId(), true, false, ImmutableList.<PluginProperty>of(), callContext);
assertEquals(latestPayment, initialPayment);
}
}
@@ -1527,7 +1558,7 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
} catch (final PaymentApiException e) {
Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INVALID_PARAMETER.getCode());
- final Payment latestPayment = paymentApi.getPayment(initialPayment.getId(), true, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment latestPayment = paymentApi.getPayment(initialPayment.getId(), true, false, ImmutableList.<PluginProperty>of(), callContext);
assertEquals(latestPayment, initialPayment);
}
}
@@ -2189,7 +2220,7 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
private void verifyPaymentViaGetPath(final Payment payment) throws PaymentApiException {
// We can't use Assert.assertEquals because the updateDate may have been updated by the Janitor
- final Payment refreshedPayment = paymentApi.getPayment(payment.getId(), true, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment refreshedPayment = paymentApi.getPayment(payment.getId(), true, false, ImmutableList.<PluginProperty>of(), callContext);
Assert.assertEquals(refreshedPayment.getAccountId(), payment.getAccountId());
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApiNoDB.java b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApiNoDB.java
index cad7b12..bf1e53c 100644
--- a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApiNoDB.java
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApiNoDB.java
@@ -177,18 +177,18 @@ public class TestPaymentApiNoDB extends PaymentTestSuiteNoDB {
boolean failed = false;
try {
- paymentApi.deletePaymentMethod(account, account.getPaymentMethodId(), false, PLUGIN_PROPERTIES, callContext);
+ paymentApi.deletePaymentMethod(account, account.getPaymentMethodId(), false, false, PLUGIN_PROPERTIES, callContext);
} catch (final PaymentApiException e) {
failed = true;
}
assertTrue(failed);
- paymentApi.deletePaymentMethod(account, initDefaultMethod.getId(), true, PLUGIN_PROPERTIES, callContext);
+ paymentApi.deletePaymentMethod(account, initDefaultMethod.getId(), true, false, PLUGIN_PROPERTIES, callContext);
methods = paymentApi.getAccountPaymentMethods(account.getId(), false, PLUGIN_PROPERTIES, callContext);
assertEquals(methods.size(), 1);
// NOW retry with default payment method with special flag
- paymentApi.deletePaymentMethod(account, account.getPaymentMethodId(), true, PLUGIN_PROPERTIES, callContext);
+ paymentApi.deletePaymentMethod(account, account.getPaymentMethodId(), true, false, PLUGIN_PROPERTIES, callContext);
methods = paymentApi.getAccountPaymentMethods(account.getId(), false, PLUGIN_PROPERTIES, callContext);
assertEquals(methods.size(), 0);
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryAuthorizeOperationCallback.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryAuthorizeOperationCallback.java
index a09ddfa..d6e79c8 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryAuthorizeOperationCallback.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryAuthorizeOperationCallback.java
@@ -22,8 +22,8 @@ import org.killbill.automaton.OperationResult;
import org.killbill.billing.payment.api.DefaultPayment;
import org.killbill.billing.payment.api.DefaultPaymentTransaction;
import org.killbill.billing.payment.api.Payment;
-import org.killbill.billing.payment.api.PaymentTransaction;
import org.killbill.billing.payment.api.PaymentApiException;
+import org.killbill.billing.payment.api.PaymentTransaction;
import org.killbill.billing.payment.api.TransactionStatus;
import org.killbill.billing.payment.core.PaymentProcessor;
import org.killbill.billing.payment.core.sm.control.AuthorizeControlOperation;
@@ -106,7 +106,7 @@ public class MockRetryAuthorizeOperationCallback extends AuthorizeControlOperati
null);
return new DefaultPayment(paymentModelDao.getId(), paymentModelDao.getCreatedDate(), paymentModelDao.getUpdatedDate(), paymentModelDao.getAccountId(),
- paymentModelDao.getPaymentMethodId(), paymentModelDao.getPaymentNumber(), paymentModelDao.getExternalKey(), Collections.singletonList(convertedTransaction));
+ paymentModelDao.getPaymentMethodId(), paymentModelDao.getPaymentNumber(), paymentModelDao.getExternalKey(), Collections.singletonList(convertedTransaction), null);
}
public MockRetryAuthorizeOperationCallback setException(final Exception exception) {
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/TestPaymentProcessor.java b/payment/src/test/java/org/killbill/billing/payment/core/TestPaymentProcessor.java
index 25aee73..41fa7ea 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/TestPaymentProcessor.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/TestPaymentProcessor.java
@@ -87,7 +87,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
mockPaymentProviderPlugin.overridePaymentPluginStatus(paymentId, authorization.getTransactions().get(0).getId(), PaymentPluginStatus.PROCESSED);
- final List<Payment> payments = paymentProcessor.getAccountPayments(account.getId(), true, callContext, internalCallContext);
+ final List<Payment> payments = paymentProcessor.getAccountPayments(account.getId(), true, false, callContext, internalCallContext);
Assert.assertEquals(payments.size(), 1);
verifyPayment(payments.get(0), paymentExternalKey, TEN, ZERO, ZERO, 1);
verifyPaymentTransaction(payments.get(0).getTransactions().get(0), authorizationKey, TransactionType.AUTHORIZE, TEN, paymentId);
diff --git a/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java b/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java
index 8051f80..c248d23 100644
--- a/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java
+++ b/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java
@@ -301,7 +301,7 @@ public class TestJanitor extends PaymentTestSuiteWithEmbeddedDB {
assertNotificationsCompleted(internalCallContext, 5);
testListener.assertListenerStatus();
- final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
assertEquals(updatedPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS);
}
@@ -341,7 +341,7 @@ public class TestJanitor extends PaymentTestSuiteWithEmbeddedDB {
Assert.assertEquals(paymentTransactionHistoryAfterJanitor.size(), 4);
Assert.assertEquals(paymentTransactionHistoryAfterJanitor.get(3).getTransactionStatus(), TransactionStatus.PAYMENT_FAILURE);
- final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
// Janitor should have moved us to PAYMENT_FAILURE
assertEquals(updatedPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.PAYMENT_FAILURE);
}
@@ -362,7 +362,7 @@ public class TestJanitor extends PaymentTestSuiteWithEmbeddedDB {
} catch (PaymentApiException ignore) {
testListener.assertListenerStatus();
}
- final Payment payment = paymentApi.getPaymentByExternalKey(paymentExternalKey, false, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment payment = paymentApi.getPaymentByExternalKey(paymentExternalKey, false, false, ImmutableList.<PluginProperty>of(), callContext);
// Artificially move the transaction status to UNKNOWN
final String paymentStateName = paymentSMHelper.getErroredStateForTransaction(TransactionType.AUTHORIZE).toString();
@@ -411,7 +411,7 @@ public class TestJanitor extends PaymentTestSuiteWithEmbeddedDB {
assertNotificationsCompleted(internalCallContext, 5);
testListener.assertListenerStatus();
- final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
Assert.assertEquals(updatedPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS);
}
@@ -458,7 +458,7 @@ public class TestJanitor extends PaymentTestSuiteWithEmbeddedDB {
Thread.sleep(1000);
assertNotificationsCompleted(internalCallContext, 5);
- final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, ImmutableList.<PluginProperty>of(), callContext);
+ final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
Assert.assertEquals(updatedPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.PENDING);
}
diff --git a/payment/src/test/java/org/killbill/billing/payment/TestRetryService.java b/payment/src/test/java/org/killbill/billing/payment/TestRetryService.java
index 521911c..676c940 100644
--- a/payment/src/test/java/org/killbill/billing/payment/TestRetryService.java
+++ b/payment/src/test/java/org/killbill/billing/payment/TestRetryService.java
@@ -83,7 +83,7 @@ public class TestRetryService extends PaymentTestSuiteNoDB {
}
private Payment getPaymentForExternalKey(final String externalKey) throws PaymentApiException {
- final Payment payment = paymentProcessor.getPaymentByExternalKey(externalKey, false, ImmutableList.<PluginProperty>of(), callContext, internalCallContext);
+ final Payment payment = paymentProcessor.getPaymentByExternalKey(externalKey, false, false, ImmutableList.<PluginProperty>of(), callContext, internalCallContext);
return payment;
}
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 1a2e4aa..5298d25 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
<parent>
<artifactId>killbill-oss-parent</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.114</version>
+ <version>0.116-SNAPSHOT</version>
</parent>
<artifactId>killbill</artifactId>
<version>0.17.2-SNAPSHOT</version>
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccount.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccount.java
index 4044278..f1a2074 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccount.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestAccount.java
@@ -186,7 +186,7 @@ public class TestAccount extends TestJaxrsBase {
//
// DELETE NON DEFAULT PM
//
- killBillClient.deletePaymentMethod(paymentMethodCC.getPaymentMethodId(), false, createdBy, reason, comment);
+ killBillClient.deletePaymentMethod(paymentMethodCC.getPaymentMethodId(), false, false, createdBy, reason, comment);
//
// FETCH ALL PAYMENT METHODS
@@ -198,7 +198,7 @@ public class TestAccount extends TestJaxrsBase {
// DELETE DEFAULT PAYMENT METHOD (without special flag first)
//
try {
- killBillClient.deletePaymentMethod(paymentMethodPP.getPaymentMethodId(), false, createdBy, reason, comment);
+ killBillClient.deletePaymentMethod(paymentMethodPP.getPaymentMethodId(), false, false, createdBy, reason, comment);
fail();
} catch (final KillBillClientException e) {
}
@@ -206,7 +206,7 @@ public class TestAccount extends TestJaxrsBase {
//
// RETRY TO DELETE DEFAULT PAYMENT METHOD (with special flag this time)
//
- killBillClient.deletePaymentMethod(paymentMethodPP.getPaymentMethodId(), true, createdBy, reason, comment);
+ killBillClient.deletePaymentMethod(paymentMethodPP.getPaymentMethodId(), true, false, createdBy, reason, comment);
// CHECK ACCOUNT IS NOW AUTO_PAY_OFF
final List<Tag> tagsJson = killBillClient.getAccountTags(accountJson.getAccountId());
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestChargeback.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestChargeback.java
index a8eb3bd..405c415 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestChargeback.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestChargeback.java
@@ -94,7 +94,7 @@ public class TestChargeback extends TestJaxrsBase {
assertEquals(killBillClient.getPaymentMethod(payment.getPaymentMethodId()).getAccountId(), payment.getAccountId());
// Delete the payment method
- killBillClient.deletePaymentMethod(payment.getPaymentMethodId(), true, createdBy, reason, comment);
+ killBillClient.deletePaymentMethod(payment.getPaymentMethodId(), true, false, createdBy, reason, comment);
// Check the payment method was deleted
assertNull(killBillClient.getAccount(payment.getAccountId()).getPaymentMethodId());
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
index 5c21ce8..cdf5c3d 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
@@ -19,20 +19,24 @@ package org.killbill.billing.jaxrs;
import java.math.BigDecimal;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Nullable;
import org.killbill.billing.client.KillBillClientException;
+import org.killbill.billing.client.RequestOptions;
import org.killbill.billing.client.model.Account;
import org.killbill.billing.client.model.ComboPaymentTransaction;
+import org.killbill.billing.client.model.InvoicePayments;
import org.killbill.billing.client.model.Payment;
import org.killbill.billing.client.model.PaymentMethod;
import org.killbill.billing.client.model.PaymentMethodPluginDetail;
import org.killbill.billing.client.model.PaymentTransaction;
import org.killbill.billing.client.model.Payments;
import org.killbill.billing.client.model.PluginProperty;
+import org.killbill.billing.client.model.Tags;
import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
import org.killbill.billing.osgi.api.OSGIServiceDescriptor;
import org.killbill.billing.osgi.api.OSGIServiceRegistration;
@@ -42,12 +46,14 @@ import org.killbill.billing.payment.plugin.api.PaymentPluginApi;
import org.killbill.billing.payment.plugin.api.PaymentPluginStatus;
import org.killbill.billing.payment.provider.MockPaymentControlProviderPlugin;
import org.killbill.billing.payment.provider.MockPaymentProviderPlugin;
+import org.killbill.billing.util.api.AuditLevel;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Inject;
@@ -148,6 +154,129 @@ public class TestPayment extends TestJaxrsBase {
}
@Test(groups = "slow")
+ public void testWithFailedPaymentAndScheduledAttemptsGetInvoicePayment() throws Exception {
+ mockPaymentProviderPlugin.makeNextPaymentFailWithError();
+ final Account account = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
+ // Getting Invoice #2 (first after Trial period)
+ UUID failedInvoiceId = killBillClient.getInvoicesForAccount(account.getAccountId(), false, false, RequestOptions.empty()).get(1).getInvoiceId();
+
+ HashMultimap<String, String> queryParams = HashMultimap.create();
+ queryParams.put("withAttempts", "true");
+ RequestOptions inputOptions = RequestOptions.builder()
+ .withCreatedBy(createdBy)
+ .withReason(reason)
+ .withComment(comment)
+ .withQueryParams(queryParams).build();
+
+ InvoicePayments invoicePayments = killBillClient.getInvoicePayment(failedInvoiceId, inputOptions);
+
+ Assert.assertEquals(invoicePayments.get(0).getTargetInvoiceId(), failedInvoiceId);
+ Assert.assertNotNull(invoicePayments.get(0).getPaymentAttempts());
+ Assert.assertEquals(invoicePayments.get(0).getPaymentAttempts().get(0).getStateName(), "RETRIED");
+ Assert.assertEquals(invoicePayments.get(0).getPaymentAttempts().get(1).getStateName(), "SCHEDULED");
+ }
+
+ @Test(groups = "slow")
+ public void testWithFailedPaymentAndScheduledAttemptsGetPaymentsForAccount() throws Exception {
+ mockPaymentProviderPlugin.makeNextPaymentFailWithError();
+ final Account account = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
+
+ HashMultimap<String, String> queryParams = HashMultimap.create();
+ queryParams.put("withAttempts", "true");
+ RequestOptions inputOptions = RequestOptions.builder()
+ .withCreatedBy(createdBy)
+ .withReason(reason)
+ .withComment(comment)
+ .withQueryParams(queryParams).build();
+
+ Payments payments = killBillClient.getPaymentsForAccount(account.getAccountId(), inputOptions);
+
+ Assert.assertNotNull(payments.get(0).getPaymentAttempts());
+ Assert.assertEquals(payments.get(0).getPaymentAttempts().get(0).getStateName(), "RETRIED");
+ Assert.assertEquals(payments.get(0).getPaymentAttempts().get(1).getStateName(), "SCHEDULED");
+ }
+
+ @Test(groups = "slow")
+ public void testWithFailedPaymentAndScheduledAttemptsGetPayments() throws Exception {
+ mockPaymentProviderPlugin.makeNextPaymentFailWithError();
+ createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
+
+ HashMultimap<String, String> queryParams = HashMultimap.create();
+ queryParams.put("withAttempts", "true");
+ RequestOptions inputOptions = RequestOptions.builder()
+ .withCreatedBy(createdBy)
+ .withReason(reason)
+ .withComment(comment)
+ .withQueryParams(queryParams).build();
+
+ Payments payments = killBillClient.getPayments(0L, 100L, null, new HashMap<String, String>(), AuditLevel.NONE, inputOptions);
+
+ Assert.assertNotNull(payments.get(0).getPaymentAttempts());
+ Assert.assertEquals(payments.get(0).getPaymentAttempts().get(0).getStateName(), "RETRIED");
+ Assert.assertEquals(payments.get(0).getPaymentAttempts().get(1).getStateName(), "SCHEDULED");
+ }
+
+ @Test(groups = "slow")
+ public void testWithFailedPaymentAndScheduledAttemptsSearchPayments() throws Exception {
+ mockPaymentProviderPlugin.makeNextPaymentFailWithError();
+ createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
+
+ HashMultimap<String, String> queryParams = HashMultimap.create();
+ queryParams.put("withAttempts", "true");
+ RequestOptions inputOptions = RequestOptions.builder()
+ .withCreatedBy(createdBy)
+ .withReason(reason)
+ .withComment(comment)
+ .withQueryParams(queryParams).build();
+
+ Payments payments = killBillClient.searchPayments("1", 0L, 100L, AuditLevel.NONE, inputOptions);
+
+ Assert.assertNotNull(payments.get(0).getPaymentAttempts());
+ Assert.assertEquals(payments.get(0).getPaymentAttempts().get(0).getStateName(), "RETRIED");
+ Assert.assertEquals(payments.get(0).getPaymentAttempts().get(1).getStateName(), "SCHEDULED");
+ }
+
+ @Test(groups = "slow")
+ public void testWithFailedPaymentAndScheduledAttemptsGetPaymentById() throws Exception {
+ mockPaymentProviderPlugin.makeNextPaymentFailWithError();
+ createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
+
+ HashMultimap<String, String> queryParams = HashMultimap.create();
+ queryParams.put("withAttempts", "true");
+ RequestOptions inputOptions = RequestOptions.builder()
+ .withCreatedBy(createdBy)
+ .withReason(reason)
+ .withComment(comment)
+ .withQueryParams(queryParams).build();
+
+ Payments payments = killBillClient.searchPayments("", 0L, 100L, AuditLevel.NONE, inputOptions);
+ Assert.assertNotNull(payments.get(0));
+ Payment payment = killBillClient.getPayment(payments.get(0).getPaymentId(), inputOptions);
+
+ Assert.assertNotNull(payment.getPaymentAttempts());
+ Assert.assertEquals(payment.getPaymentAttempts().get(0).getStateName(), "RETRIED");
+ Assert.assertEquals(payment.getPaymentAttempts().get(1).getStateName(), "SCHEDULED");
+ }
+
+ @Test(groups = "slow")
+ public void testDeletePaymentMethodWithAutoPayOff() throws Exception {
+ final Account account = createAccountWithDefaultPaymentMethod();
+ final UUID paymentMethodId = account.getPaymentMethodId();
+
+ RequestOptions inputOptions = RequestOptions.builder()
+ .withCreatedBy(createdBy)
+ .withReason(reason)
+ .withComment(comment).build();
+
+ killBillClient.deletePaymentMethod(paymentMethodId, true, false, inputOptions);
+
+ Tags accountTags = killBillClient.getAccountTags(account.getAccountId(), inputOptions);
+
+ Assert.assertNotNull(accountTags);
+ Assert.assertEquals(accountTags.get(0).getTagDefinitionName(), "AUTO_PAY_OFF");
+ }
+
+ @Test(groups = "slow")
public void testCreateRetrievePayment() throws Exception {
final Account account = createAccountWithDefaultPaymentMethod();
final String externalPaymentKey = UUID.randomUUID().toString();
diff --git a/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java b/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java
index 1871609..87c8433 100644
--- a/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java
+++ b/util/src/main/java/org/killbill/billing/util/audit/DefaultAccountAuditLogs.java
@@ -96,6 +96,11 @@ public class DefaultAccountAuditLogs implements AccountAuditLogs {
}
@Override
+ public List<AuditLog> getAuditLogsForPaymentAttempt(final UUID paymentAttemptId) {
+ return getAuditLogs(ObjectType.PAYMENT_ATTEMPT).getAuditLogs(paymentAttemptId);
+ }
+
+ @Override
public List<AuditLog> getAuditLogsForPaymentMethod(final UUID paymentMethodId) {
return getAuditLogs(ObjectType.PAYMENT_METHOD).getAuditLogs(paymentMethodId);
}