Details
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 90d44b6..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
@@ -52,7 +52,7 @@ 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<PaymentAttempt> paymentAttempts,
+ @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, 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..dc64083
--- /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().toString(),
+ 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 66b3e32..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
@@ -51,7 +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<PaymentAttempt> paymentAttempts;
+ private final List<PaymentAttemptJson> paymentAttempts;
@JsonCreator
public PaymentJson(@JsonProperty("accountId") final String accountId,
@@ -66,7 +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<PaymentAttempt> paymentAttempts,
+ @JsonProperty("paymentAttempts") final List<PaymentAttemptJson> paymentAttempts,
@JsonProperty("auditLogs") @Nullable final List<AuditLogJson> auditLogs) {
super(auditLogs);
this.accountId = accountId;
@@ -97,7 +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),
- dp.getPaymentAttempts(),
+ getAttempts(dp.getPaymentAttempts(), dp.getExternalKey(), accountAuditLogs),
toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForPayment(dp.getId())));
}
@@ -113,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;
}
@@ -161,7 +173,7 @@ public class PaymentJson extends JsonBase {
return transactions;
}
- public List<PaymentAttempt> getPaymentAttempts() { return paymentAttempts; }
+ public List<? extends PaymentAttemptJson> getPaymentAttempts() { return paymentAttempts; }
@Override
public String toString() {
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
index 97ec78f..31384e6 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentAttempt.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentAttempt.java
@@ -89,6 +89,14 @@ public class DefaultPaymentAttempt extends EntityBase implements PaymentAttempt
}
@Override
+ public DateTime getEffectiveDate() { return effectiveDate; }
+
+ @Override
+ public String getStateName() {
+ return stateName;
+ }
+
+ @Override
public BigDecimal getAmount() {
return amount;
}
@@ -109,11 +117,6 @@ public class DefaultPaymentAttempt extends EntityBase implements PaymentAttempt
}
@Override
- public String getStateName() {
- return stateName;
- }
-
- @Override
public String toString() {
return "DefaultPaymentAttempt{" +
"accountId=" + accountId +
@@ -122,6 +125,7 @@ public class DefaultPaymentAttempt extends EntityBase implements PaymentAttempt
", transactionId=" + transactionId +
", transactionExternalKey='" + transactionExternalKey + '\'' +
", transactionType=" + transactionType +
+ ", effectiveDate=" + effectiveDate +
", stateName=" + stateName +
", amount=" + amount +
", currency=" + currency +
@@ -190,6 +194,7 @@ public class DefaultPaymentAttempt extends EntityBase implements PaymentAttempt
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);
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 debeea1..b8e469a 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
@@ -59,6 +59,8 @@ 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;
@@ -622,9 +624,6 @@ public class PaymentProcessor extends ProcessorBase {
List<PaymentAttempt> paymentAttempts = new ArrayList<PaymentAttempt>();
- // Last Attempt from model dao
- PaymentAttemptModelDao lastPaymentAttemptModelDao = pastPaymentAttempts.get(pastPaymentAttempts.size() - 1);
-
// Add Past Payment Attempts
for (PaymentAttemptModelDao pastPaymentAttempt : pastPaymentAttempts) {
DefaultPaymentAttempt paymentAttempt = new DefaultPaymentAttempt(
@@ -642,7 +641,7 @@ public class PaymentProcessor extends ProcessorBase {
pastPaymentAttempt.getAmount(),
pastPaymentAttempt.getCurrency(),
pastPaymentAttempt.getPluginName(),
- null); // TODO: transform from byte[] to List<PluginProperty>
+ buildPluginProperties(pastPaymentAttempt));
paymentAttempts.add(paymentAttempt);
}
@@ -652,24 +651,30 @@ public class PaymentProcessor extends ProcessorBase {
final List<NotificationEventWithMetadata<NotificationEvent>> notificationEventWithMetadatas =
retryQueue.getFutureNotificationForSearchKeys(internalTenantContext.getAccountRecordId(), internalTenantContext.getTenantRecordId());
- for (NotificationEventWithMetadata<NotificationEvent> notificationEvent : notificationEventWithMetadatas) {
- DefaultPaymentAttempt futurePaymentAttempt = new DefaultPaymentAttempt(
- lastPaymentAttemptModelDao.getAccountId(), // accountId
- lastPaymentAttemptModelDao.getPaymentMethodId(), // paymentMethodId
- ((PaymentRetryNotificationKey) notificationEvent.getEvent()).getAttemptId(), // id
- null, // createdDate
- null, // updatedDate
- notificationEvent.getEffectiveDate(), // effectiveDate
- lastPaymentAttemptModelDao.getPaymentExternalKey(), // paymentExternalKey
- null, // transactionId
- lastPaymentAttemptModelDao.getTransactionExternalKey(), // transactionExternalKey
- lastPaymentAttemptModelDao.getTransactionType(), // transactionType
- SCHEDULED, // stateName
- lastPaymentAttemptModelDao.getAmount(), // amount
- lastPaymentAttemptModelDao.getCurrency(), // currency
- ((PaymentRetryNotificationKey) notificationEvent.getEvent()).getPaymentControlPluginNames().get(0), // pluginName,
- null); // TODO: transform from byte[] to List<PluginProperty> // pluginProperties
- paymentAttempts.add(futurePaymentAttempt);
+ 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());
@@ -677,6 +682,28 @@ public class PaymentProcessor extends ProcessorBase {
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;
+ }
+
+ 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) {
if (pluginTransactions == null) {
return null;
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);
}