killbill-uncached
Merge branch 'jgomez-payment-retries-timeline' into jgomez-work-for-release-0.17.x
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 4(+2 -2)
beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationWithWrittenOffTag.java 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..8bf7dc9 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
@@ -247,7 +247,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 +308,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);
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/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoicePaymentJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/InvoicePaymentJson.java
index f37d2e4..8134813 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..b29834f
--- /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 com.wordnik.swagger.annotations.ApiModel;
+import com.wordnik.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 3a85882..e6d4ed8 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 2b2c0a4..2235dda 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 dbd6cbe..e4361cf 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 377dd1c..8f5a12b 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 6811d99..e84f8ec 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 33a10a8..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";
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 3c2b1bb..c11d89e 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 09ae361..ed00977 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 28d2d0b..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;
@@ -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,
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/PaymentProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
index 7a8b101..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;
@@ -438,7 +459,7 @@ public class PaymentProcessor extends ProcessorBase {
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,
@@ -519,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) {
@@ -579,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) {
@@ -612,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;
+ }
+
+ 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;
+ }
- return new DefaultPayment(newPaymentModelDao.getId(),
- newPaymentModelDao.getCreatedDate(),
- newPaymentModelDao.getUpdatedDate(),
- newPaymentModelDao.getAccountId(),
- newPaymentModelDao.getPaymentMethodId(),
- newPaymentModelDao.getPaymentNumber(),
- newPaymentModelDao.getExternalKey(),
- sortedTransactions);
+ 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/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 a57deb8..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
@@ -902,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);
@@ -959,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);
@@ -987,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);
@@ -1451,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");
@@ -1540,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);
}
}
@@ -1558,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);
}
}
@@ -2220,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/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;
}
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..9bd73e1 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,14 +19,17 @@ 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;
@@ -42,12 +45,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 +153,111 @@ 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 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);
}