killbill-memoizeit

Add TransactionType to all payment events Refactor DirectPaymentAutomatonRunner

7/1/2014 3:55:38 PM

Details

diff --git a/api/src/main/java/org/killbill/billing/events/PaymentErrorInternalEvent.java b/api/src/main/java/org/killbill/billing/events/PaymentErrorInternalEvent.java
index 0f98db9..48a9c51 100644
--- a/api/src/main/java/org/killbill/billing/events/PaymentErrorInternalEvent.java
+++ b/api/src/main/java/org/killbill/billing/events/PaymentErrorInternalEvent.java
@@ -17,6 +17,7 @@ package org.killbill.billing.events;
 
 import java.util.UUID;
 
+import org.killbill.billing.payment.api.TransactionType;
 
 public interface PaymentErrorInternalEvent extends BusInternalEvent {
 
@@ -27,4 +28,6 @@ public interface PaymentErrorInternalEvent extends BusInternalEvent {
     public UUID getAccountId();
 
     public UUID getPaymentId();
+
+    public TransactionType getTransactionType();
 }
diff --git a/api/src/main/java/org/killbill/billing/events/PaymentInfoInternalEvent.java b/api/src/main/java/org/killbill/billing/events/PaymentInfoInternalEvent.java
index a1db7cc..49f0ecd 100644
--- a/api/src/main/java/org/killbill/billing/events/PaymentInfoInternalEvent.java
+++ b/api/src/main/java/org/killbill/billing/events/PaymentInfoInternalEvent.java
@@ -21,6 +21,7 @@ import java.util.UUID;
 
 import org.joda.time.DateTime;
 import org.killbill.billing.payment.api.TransactionStatus;
+import org.killbill.billing.payment.api.TransactionType;
 
 public interface PaymentInfoInternalEvent extends BusInternalEvent {
 
@@ -37,4 +38,6 @@ public interface PaymentInfoInternalEvent extends BusInternalEvent {
     public Integer getPaymentNumber();
 
     public TransactionStatus getStatus();
+
+    public TransactionType getTransactionType();
 }
diff --git a/api/src/main/java/org/killbill/billing/events/PaymentPluginErrorInternalEvent.java b/api/src/main/java/org/killbill/billing/events/PaymentPluginErrorInternalEvent.java
index 7314160..f4743ad 100644
--- a/api/src/main/java/org/killbill/billing/events/PaymentPluginErrorInternalEvent.java
+++ b/api/src/main/java/org/killbill/billing/events/PaymentPluginErrorInternalEvent.java
@@ -17,6 +17,7 @@ package org.killbill.billing.events;
 
 import java.util.UUID;
 
+import org.killbill.billing.payment.api.TransactionType;
 
 public interface PaymentPluginErrorInternalEvent extends BusInternalEvent {
 
@@ -27,4 +28,6 @@ public interface PaymentPluginErrorInternalEvent extends BusInternalEvent {
     public UUID getAccountId();
 
     public UUID getPaymentId();
+
+    public TransactionType getTransactionType();
 }
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentErrorEvent.java b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentErrorEvent.java
index fc5c995..7e95787 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentErrorEvent.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentErrorEvent.java
@@ -31,11 +31,13 @@ public class DefaultPaymentErrorEvent extends BusEventBase implements PaymentErr
     private final UUID accountId;
     private final UUID invoiceId;
     private final UUID paymentId;
+    private final TransactionType transactionType;
 
     @JsonCreator
     public DefaultPaymentErrorEvent(@JsonProperty("accountId") final UUID accountId,
                                     @JsonProperty("invoiceId") final UUID invoiceId,
                                     @JsonProperty("paymentId") final UUID paymentId,
+                                    @JsonProperty("transactionType")  final TransactionType transactionType,
                                     @JsonProperty("message") final String message,
                                     @JsonProperty("searchKey1") final Long searchKey1,
                                     @JsonProperty("searchKey2") final Long searchKey2,
@@ -45,24 +47,34 @@ public class DefaultPaymentErrorEvent extends BusEventBase implements PaymentErr
         this.accountId = accountId;
         this.invoiceId = invoiceId;
         this.paymentId = paymentId;
+        this.transactionType = transactionType;
     }
 
+    @Override
     public String getMessage() {
         return message;
     }
 
+    @Override
     public UUID getAccountId() {
         return accountId;
     }
 
+    @Override
     public UUID getInvoiceId() {
         return invoiceId;
     }
 
+    @Override
     public UUID getPaymentId() {
         return paymentId;
     }
 
+    @Override
+    public TransactionType getTransactionType() {
+        return transactionType;
+    }
+
     @JsonIgnore
     @Override
     public BusInternalEventType getBusEventType() {
@@ -83,6 +95,9 @@ public class DefaultPaymentErrorEvent extends BusEventBase implements PaymentErr
         if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
             return false;
         }
+        if (transactionType != null ? !transactionType.equals(that.transactionType) : that.transactionType != null) {
+            return false;
+        }
         if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
             return false;
         }
@@ -100,6 +115,7 @@ public class DefaultPaymentErrorEvent extends BusEventBase implements PaymentErr
     public int hashCode() {
         int result = message != null ? message.hashCode() : 0;
         result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+        result = 31 * result + (transactionType != null ? transactionType.hashCode() : 0);
         result = 31 * result + (invoiceId != null ? invoiceId.hashCode() : 0);
         result = 31 * result + (paymentId != null ? paymentId.hashCode() : 0);
         return result;
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentInfoEvent.java b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentInfoEvent.java
index 726b54a..b42844d 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentInfoEvent.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentInfoEvent.java
@@ -35,6 +35,7 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
     private final BigDecimal amount;
     private final Integer paymentNumber;
     private final TransactionStatus status;
+    private final TransactionType transactionType;
     private final DateTime effectiveDate;
 
     @JsonCreator
@@ -44,6 +45,7 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
                                    @JsonProperty("amount") final BigDecimal amount,
                                    @JsonProperty("paymentNumber") final Integer paymentNumber,
                                    @JsonProperty("status") final TransactionStatus status,
+                                   @JsonProperty("transactionType")  final TransactionType transactionType,
                                    @JsonProperty("extFirstPaymentRefId") final String extFirstPaymentRefId /* TODO for backward compatibility only */,
                                    @JsonProperty("extSecondPaymentRefId") final String extSecondPaymentRefId /* TODO for backward compatibility only */,
                                    @JsonProperty("effectiveDate") final DateTime effectiveDate,
@@ -57,17 +59,19 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
         this.amount = amount;
         this.paymentNumber = paymentNumber;
         this.status = status;
+        this.transactionType = transactionType;
         this.effectiveDate = effectiveDate;
     }
 
     public DefaultPaymentInfoEvent(final UUID accountId, final UUID invoiceId,
                                    final UUID paymentId, final BigDecimal amount, final Integer paymentNumber,
                                    final TransactionStatus status,
+                                   final TransactionType transactionType,
                                    final DateTime effectiveDate,
                                    final Long searchKey1,
                                    final Long searchKey2,
                                    final UUID userToken) {
-        this(accountId, invoiceId, paymentId, amount, paymentNumber, status, null, null,
+        this(accountId, invoiceId, paymentId, amount, paymentNumber, status, transactionType, null, null,
              effectiveDate, searchKey1, searchKey2, userToken);
     }
 
@@ -102,12 +106,16 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
         return paymentId;
     }
 
-    @Override
     public Integer getPaymentNumber() {
         return paymentNumber;
     }
 
     @Override
+    public TransactionType getTransactionType() {
+        return transactionType;
+    }
+
+    @Override
     public TransactionStatus getStatus() {
         return status;
     }
@@ -122,6 +130,7 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
         sb.append(", amount=").append(amount);
         sb.append(", paymentNumber=").append(paymentNumber);
         sb.append(", status=").append(status);
+        sb.append(", transactionType=").append(transactionType);
         sb.append(", effectiveDate=").append(effectiveDate);
         sb.append('}');
         return sb.toString();
@@ -165,6 +174,13 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
         } else if (!accountId.equals(other.accountId)) {
             return false;
         }
+        if (transactionType == null) {
+            if (other.transactionType != null) {
+                return false;
+            }
+        } else if (!transactionType.equals(other.transactionType)) {
+            return false;
+        }
         if (amount == null) {
             if (other.amount != null) {
                 return false;
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentPluginErrorEvent.java b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentPluginErrorEvent.java
index 8bc0220..c22fa02 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentPluginErrorEvent.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentPluginErrorEvent.java
@@ -30,11 +30,13 @@ public class DefaultPaymentPluginErrorEvent extends BusEventBase implements Paym
     private final UUID accountId;
     private final UUID invoiceId;
     private final UUID paymentId;
+    private final TransactionType transactionType;
 
     @JsonCreator
     public DefaultPaymentPluginErrorEvent(@JsonProperty("accountId") final UUID accountId,
                                           @JsonProperty("invoiceId") final UUID invoiceId,
                                           @JsonProperty("paymentId") final UUID paymentId,
+                                          @JsonProperty("transactionType")  final TransactionType transactionType,
                                           @JsonProperty("message") final String message,
                                           @JsonProperty("searchKey1") final Long searchKey1,
                                           @JsonProperty("searchKey2") final Long searchKey2,
@@ -44,24 +46,34 @@ public class DefaultPaymentPluginErrorEvent extends BusEventBase implements Paym
         this.accountId = accountId;
         this.invoiceId = invoiceId;
         this.paymentId = paymentId;
+        this.transactionType = transactionType;
     }
 
+    @Override
     public String getMessage() {
         return message;
     }
 
+    @Override
     public UUID getAccountId() {
         return accountId;
     }
 
+    @Override
     public UUID getInvoiceId() {
         return invoiceId;
     }
 
+    @Override
     public UUID getPaymentId() {
         return paymentId;
     }
 
+    @Override
+    public TransactionType getTransactionType() {
+        return transactionType;
+    }
+
     @JsonIgnore
     @Override
     public BusInternalEventType getBusEventType() {
@@ -82,6 +94,9 @@ public class DefaultPaymentPluginErrorEvent extends BusEventBase implements Paym
         if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) {
             return false;
         }
+        if (transactionType != null ? !transactionType.equals(that.transactionType) : that.transactionType != null) {
+            return false;
+        }
         if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
             return false;
         }
@@ -99,6 +114,7 @@ public class DefaultPaymentPluginErrorEvent extends BusEventBase implements Paym
     public int hashCode() {
         int result = message != null ? message.hashCode() : 0;
         result = 31 * result + (accountId != null ? accountId.hashCode() : 0);
+        result = 31 * result + (transactionType != null ? transactionType.hashCode() : 0);
         result = 31 * result + (invoiceId != null ? invoiceId.hashCode() : 0);
         result = 31 * result + (paymentId != null ? paymentId.hashCode() : 0);
         return result;
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java
index abc986b..26e7a00 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/DirectPaymentProcessor.java
@@ -51,9 +51,9 @@ import org.killbill.billing.payment.api.PluginProperty;
 import org.killbill.billing.payment.api.TransactionStatus;
 import org.killbill.billing.payment.api.TransactionType;
 import org.killbill.billing.payment.core.sm.DirectPaymentAutomatonRunner;
+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.PaymentDao;
 import org.killbill.billing.payment.plugin.api.PaymentPluginApi;
 import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
 import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
@@ -112,133 +112,37 @@ public class DirectPaymentProcessor extends ProcessorBase {
     public DirectPayment createAuthorization(final Account account, @Nullable final UUID paymentMethodId, @Nullable final UUID directPaymentId, final BigDecimal amount, final Currency currency,
                                              final String directPaymentExternalKey, final String directPaymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
                                              final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-
-        validateUniqueTransactionExternalKey(directPaymentTransactionExternalKey, internalCallContext);
-
-        final UUID nonNullDirectPaymentId = directPaymentAutomatonRunner.run(TransactionType.AUTHORIZE,
-                                                                             account,
-                                                                             paymentMethodId,
-                                                                             directPaymentId,
-                                                                             directPaymentExternalKey,
-                                                                             directPaymentTransactionExternalKey,
-                                                                             amount,
-                                                                             currency,
-                                                                             shouldLockAccountAndDispatch,
-                                                                             properties,
-                                                                             callContext,
-                                                                             internalCallContext);
-        // TODO STEPH We should try to post the event from within transaction
-        final DirectPayment directPayment = getPayment(nonNullDirectPaymentId, true, properties, callContext, internalCallContext);
-        postPaymentEvent(account, directPayment, directPaymentTransactionExternalKey, internalCallContext);
-        return directPayment;
+        return performOperation(TransactionType.AUTHORIZE, account, paymentMethodId, directPaymentId, amount, currency, directPaymentExternalKey, directPaymentTransactionExternalKey, shouldLockAccountAndDispatch, properties, callContext, internalCallContext);
     }
 
     public DirectPayment createCapture(final Account account, final UUID directPaymentId, final BigDecimal amount, final Currency currency,
                                        final String directPaymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
                                        final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
 
-        validateUniqueTransactionExternalKey(directPaymentTransactionExternalKey, internalCallContext);
-
-        final UUID nonNullDirectPaymentId = directPaymentAutomatonRunner.run(TransactionType.CAPTURE,
-                                                                             account,
-                                                                             directPaymentId,
-                                                                             directPaymentTransactionExternalKey,
-                                                                             amount,
-                                                                             currency,
-                                                                             shouldLockAccountAndDispatch,
-                                                                             properties,
-                                                                             callContext,
-                                                                             internalCallContext);
-
-        final DirectPayment directPayment = getPayment(nonNullDirectPaymentId, true, properties, callContext, internalCallContext);
-        postPaymentEvent(account, directPayment, directPaymentTransactionExternalKey, internalCallContext);
-        return directPayment;
+        return performOperation(TransactionType.CAPTURE, account, null, directPaymentId, amount, currency, null, directPaymentTransactionExternalKey, shouldLockAccountAndDispatch, properties, callContext, internalCallContext);
     }
 
     public DirectPayment createPurchase(final Account account, @Nullable final UUID paymentMethodId, @Nullable final UUID directPaymentId, final BigDecimal amount, final Currency currency,
                                         final String directPaymentExternalKey, final String directPaymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
                                         final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-
-        validateUniqueTransactionExternalKey(directPaymentTransactionExternalKey, internalCallContext);
-
-        final UUID nonNullDirectPaymentId = directPaymentAutomatonRunner.run(TransactionType.PURCHASE,
-                                                                             account,
-                                                                             paymentMethodId,
-                                                                             directPaymentId,
-                                                                             directPaymentExternalKey,
-                                                                             directPaymentTransactionExternalKey,
-                                                                             amount,
-                                                                             currency,
-                                                                             shouldLockAccountAndDispatch,
-                                                                             properties,
-                                                                             callContext,
-                                                                             internalCallContext);
-
-        final DirectPayment directPayment = getPayment(nonNullDirectPaymentId, true, properties, callContext, internalCallContext);
-        postPaymentEvent(account, directPayment, directPaymentTransactionExternalKey, internalCallContext);
-        return directPayment;
+        return performOperation(TransactionType.PURCHASE, account, paymentMethodId, directPaymentId, amount, currency, directPaymentExternalKey, directPaymentTransactionExternalKey, shouldLockAccountAndDispatch, properties, callContext, internalCallContext);
     }
 
     public DirectPayment createVoid(final Account account, final UUID directPaymentId, final String directPaymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
                                     final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-
-        validateUniqueTransactionExternalKey(directPaymentTransactionExternalKey, internalCallContext);
-
-        final UUID nonNullDirectPaymentId = directPaymentAutomatonRunner.run(TransactionType.VOID,
-                                                                             account,
-                                                                             directPaymentId,
-                                                                             directPaymentTransactionExternalKey,
-                                                                             shouldLockAccountAndDispatch,
-                                                                             properties,
-                                                                             callContext,
-                                                                             internalCallContext);
-        final DirectPayment directPayment = getPayment(nonNullDirectPaymentId, true, properties, callContext, internalCallContext);
-        postPaymentEvent(account, directPayment, directPaymentTransactionExternalKey, internalCallContext);
-        return directPayment;
+        return performOperation(TransactionType.VOID, account, null, directPaymentId, null, null, null, directPaymentTransactionExternalKey, shouldLockAccountAndDispatch, properties, callContext, internalCallContext);
     }
 
     public DirectPayment createRefund(final Account account, final UUID directPaymentId, final BigDecimal amount, final Currency currency,
                                       final String directPaymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
                                       final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-
-        validateUniqueTransactionExternalKey(directPaymentTransactionExternalKey, internalCallContext);
-
-        final UUID nonNullDirectPaymentId = directPaymentAutomatonRunner.run(TransactionType.REFUND,
-                                                                             account,
-                                                                             directPaymentId,
-                                                                             directPaymentTransactionExternalKey,
-                                                                             amount,
-                                                                             currency,
-                                                                             shouldLockAccountAndDispatch,
-                                                                             properties,
-                                                                             callContext,
-                                                                             internalCallContext);
-        final DirectPayment directPayment = getPayment(nonNullDirectPaymentId, true, properties, callContext, internalCallContext);
-        postPaymentEvent(account, directPayment, directPaymentTransactionExternalKey, internalCallContext);
-        return directPayment;
+        return performOperation(TransactionType.REFUND, account, null, directPaymentId, amount, currency, null, directPaymentTransactionExternalKey, shouldLockAccountAndDispatch, properties, callContext, internalCallContext);
     }
 
     public DirectPayment createCredit(final Account account, @Nullable final UUID paymentMethodId, @Nullable final UUID directPaymentId, final BigDecimal amount, final Currency currency,
                                       final String directPaymentExternalKey, final String directPaymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
                                       final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-
-        validateUniqueTransactionExternalKey(directPaymentTransactionExternalKey, internalCallContext);
-
-        final UUID nonNullDirectPaymentId = directPaymentAutomatonRunner.run(TransactionType.CREDIT,
-                                                                             account,
-                                                                             paymentMethodId,
-                                                                             directPaymentId,
-                                                                             directPaymentExternalKey,
-                                                                             directPaymentTransactionExternalKey,
-                                                                             amount,
-                                                                             currency,
-                                                                             shouldLockAccountAndDispatch,
-                                                                             properties,
-                                                                             callContext,
-                                                                             internalCallContext);
-        final DirectPayment directPayment = getPayment(nonNullDirectPaymentId, true, properties, callContext, internalCallContext);
-        postPaymentEvent(account, directPayment, directPaymentTransactionExternalKey, internalCallContext);
-        return directPayment;
+        return performOperation(TransactionType.CREDIT, account, paymentMethodId, directPaymentId, amount, currency, directPaymentExternalKey, directPaymentTransactionExternalKey, shouldLockAccountAndDispatch, properties, callContext, internalCallContext);
     }
 
     public List<DirectPayment> getAccountPayments(final UUID accountId, final InternalTenantContext tenantContext) throws PaymentApiException {
@@ -246,13 +150,13 @@ public class DirectPaymentProcessor extends ProcessorBase {
         final List<PaymentTransactionModelDao> transactionsModelDao = paymentDao.getDirectTransactionsForAccount(accountId, tenantContext);
 
         return Lists.<PaymentModelDao, DirectPayment>transform(paymentsModelDao,
-                                                                     new Function<PaymentModelDao, DirectPayment>() {
-                                                                         @Override
-                                                                         public DirectPayment apply(final PaymentModelDao curPaymentModelDao) {
-                                                                             return toDirectPayment(curPaymentModelDao, transactionsModelDao, null);
-                                                                         }
-                                                                     }
-                                                                    );
+                                                               new Function<PaymentModelDao, DirectPayment>() {
+                                                                   @Override
+                                                                   public DirectPayment apply(final PaymentModelDao curPaymentModelDao) {
+                                                                       return toDirectPayment(curPaymentModelDao, transactionsModelDao, null);
+                                                                   }
+                                                               }
+                                                              );
     }
 
     public void notifyPendingPaymentOfStateChanged(final Account account, UUID transactionId, final boolean isSuccess, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
@@ -284,7 +188,7 @@ public class DirectPaymentProcessor extends ProcessorBase {
         final DateTime utcNow = clock.getUTCNow();
         final PaymentTransactionModelDao chargebackTransaction = new PaymentTransactionModelDao(utcNow, utcNow, chargebackTransactionExternalKey, transactionModelDao.getPaymentId(),
 
-                                                                                                            TransactionType.CHARGEBACK, utcNow, TransactionStatus.SUCCESS, amount, currency, null, null);
+                                                                                                TransactionType.CHARGEBACK, utcNow, TransactionStatus.SUCCESS, amount, currency, null, null);
         final State currentPaymentState = directPaymentAutomatonRunner.fetchNextState("CHARGEBACK_INIT", true);
 
         // TODO STEPH we could create a DAO operation to do both steps at once
@@ -321,7 +225,7 @@ public class DirectPaymentProcessor extends ProcessorBase {
                                               new EntityPaginationBuilder<DirectPayment, PaymentApiException>() {
                                                   @Override
                                                   public Pagination<DirectPayment> build(final Long offset, final Long limit, final String pluginName) throws PaymentApiException {
-                                                      final Pagination<DirectPayment>  result = getPayments(offset, limit, pluginName, properties, tenantContext, internalTenantContext);
+                                                      final Pagination<DirectPayment> result = getPayments(offset, limit, pluginName, properties, tenantContext, internalTenantContext);
                                                       return result;
                                                   }
                                               }
@@ -336,7 +240,7 @@ public class DirectPaymentProcessor extends ProcessorBase {
                                        @Override
                                        public Pagination<PaymentModelDao> build() {
                                            // Find all payments for all accounts
-                                           final Pagination<PaymentModelDao> result  = paymentDao.getDirectPayments(pluginName, offset, limit, internalTenantContext);
+                                           final Pagination<PaymentModelDao> result = paymentDao.getDirectPayments(pluginName, offset, limit, internalTenantContext);
                                            return result;
                                        }
                                    },
@@ -426,6 +330,35 @@ public class DirectPaymentProcessor extends ProcessorBase {
         return toDirectPayment(paymentModelDao, transactionsForAccount, pluginTransactions);
     }
 
+    private DirectPayment performOperation(final TransactionType transactionType, final Account account, final UUID paymentMethodId, final UUID directPaymentId, final BigDecimal amount, final Currency currency,
+                                           final String directPaymentExternalKey, final String directPaymentTransactionExternalKey,
+                                           final boolean shouldLockAccountAndDispatch, final Iterable<PluginProperty> properties, final CallContext callContext,
+                                           final InternalCallContext internalCallContext) throws PaymentApiException {
+
+        DirectPayment directPayment = null;
+        try {
+            validateUniqueTransactionExternalKey(directPaymentTransactionExternalKey, internalCallContext);
+
+            final UUID nonNullDirectPaymentId = directPaymentAutomatonRunner.run(transactionType,
+                                                                                 account,
+                                                                                 paymentMethodId,
+                                                                                 directPaymentId,
+                                                                                 directPaymentExternalKey,
+                                                                                 directPaymentTransactionExternalKey,
+                                                                                 amount,
+                                                                                 currency,
+                                                                                 shouldLockAccountAndDispatch,
+                                                                                 properties,
+                                                                                 callContext,
+                                                                                 internalCallContext);
+            directPayment = getPayment(nonNullDirectPaymentId, true, properties, callContext, internalCallContext);
+            return directPayment;
+        } finally {
+            postPaymentEvent(account, transactionType, directPayment, directPaymentTransactionExternalKey, internalCallContext);
+
+        }
+    }
+
     private void validateUniqueTransactionExternalKey(final String transactionExternalKey, final InternalTenantContext tenantContext) throws PaymentApiException {
         final List<PaymentTransactionModelDao> transactions = paymentDao.getDirectPaymentTransactionsByExternalKey(transactionExternalKey, tenantContext);
         final PaymentTransactionModelDao transactionAlreadyExists = Iterables.tryFind(transactions, new Predicate<PaymentTransactionModelDao>() {
@@ -499,30 +432,31 @@ public class DirectPaymentProcessor extends ProcessorBase {
                                         curPaymentModelDao.getPaymentMethodId(), curPaymentModelDao.getPaymentNumber(), curPaymentModelDao.getExternalKey(), sortedTransactions);
     }
 
-    private void postPaymentEvent(final Account account, final DirectPayment directPayment, final String transactionExternalKey, final InternalCallContext context) {
-        final BusInternalEvent event = buildPaymentEvent(account, directPayment, transactionExternalKey, context);
+    private void postPaymentEvent(final Account account, final TransactionType transactionType, @Nullable final DirectPayment directPayment, final String transactionExternalKey, final InternalCallContext context) {
+        final BusInternalEvent event = buildPaymentEvent(account, transactionType, directPayment, transactionExternalKey, context);
         postPaymentEvent(event, account.getId(), context);
     }
 
-    private BusInternalEvent buildPaymentEvent(final Account account, final DirectPayment directPayment, final String transactionExternalKey, final InternalCallContext context) {
+    private BusInternalEvent buildPaymentEvent(final Account account, final TransactionType transactionType, @Nullable final DirectPayment directPayment, final String transactionExternalKey, final InternalCallContext context) {
 
+        if (directPayment == null) {
+            return new DefaultPaymentErrorEvent(account.getId(),
+                                                null,
+                                                null,
+                                                transactionType,
+                                                "No payment method",
+                                                context.getAccountRecordId(),
+                                                context.getTenantRecordId(),
+                                                context.getUserToken());
 
-        final DirectPaymentTransaction directPaymentTransaction = directPayment.getTransactions().get(directPayment.getTransactions().size() - 1);
-
-        /* STEPH
-        1. Should really use the last transaction for 'that' transactionExternalKey -> meaning if there is none then we did not create a transaction => threw some exception earlier.
-        2. What if there is no such transaction/payment, which event do we post since we don't have any ID ?
+        }
 
-        Iterables.<DirectPaymentTransaction>tryFind(directPayment.getTransactions(),
-                                                                                                              new Predicate<DirectPaymentTransaction>() {
-                                                                                                                  @Override
-                                                                                                                  public boolean apply(final DirectPaymentTransaction input) {
-                                                                                                                      return input.getExternalKey().equals(transactionExternalKey);
-                                                                                                                  }
-                                                                                                              }
-                                                                                                             ).get()
-                                                                                                             */
+        final DirectPaymentTransaction directPaymentTransaction = directPayment.getTransactions().get(directPayment.getTransactions().size() - 1);
+        // If the payment/transaction was created then it should match the transactionExternalKey
+        Preconditions.checkState(directPaymentTransaction.getExternalKey().equals(transactionExternalKey));
+        Preconditions.checkState(directPaymentTransaction.getTransactionType().equals(transactionType));
 
+        final TransactionStatus transactionStatus = directPaymentTransaction.getTransactionStatus();
         switch (directPaymentTransaction.getTransactionStatus()) {
             case SUCCESS:
             case PENDING:
@@ -531,7 +465,8 @@ public class DirectPaymentProcessor extends ProcessorBase {
                                                    directPayment.getId(),
                                                    directPaymentTransaction.getAmount(),
                                                    directPayment.getPaymentNumber(),
-                                                   directPaymentTransaction.getTransactionStatus(),
+                                                   transactionStatus,
+                                                   transactionType,
                                                    directPaymentTransaction.getEffectiveDate(),
                                                    context.getAccountRecordId(),
                                                    context.getTenantRecordId(),
@@ -540,6 +475,7 @@ public class DirectPaymentProcessor extends ProcessorBase {
                 return new DefaultPaymentErrorEvent(account.getId(),
                                                     null,
                                                     directPayment.getId(),
+                                                    transactionType,
                                                     directPaymentTransaction.getPaymentInfoPlugin() == null ? null : directPaymentTransaction.getPaymentInfoPlugin().getGatewayError(),
                                                     context.getAccountRecordId(),
                                                     context.getTenantRecordId(),
@@ -549,6 +485,7 @@ public class DirectPaymentProcessor extends ProcessorBase {
                 return new DefaultPaymentPluginErrorEvent(account.getId(),
                                                           null,
                                                           directPayment.getId(),
+                                                          transactionType,
                                                           directPaymentTransaction.getPaymentInfoPlugin() == null ? null : directPaymentTransaction.getPaymentInfoPlugin().getGatewayError(),
                                                           context.getAccountRecordId(),
                                                           context.getTenantRecordId(),
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
index 234ddca..2eddaf4 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
@@ -267,7 +267,6 @@ public class PaymentMethodProcessor extends ProcessorBase {
                 return paymentMethod;
             }
         }
-
         return null;
     }
 
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/DirectPaymentAutomatonRunner.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/DirectPaymentAutomatonRunner.java
index 876f1d4..0e4b6a5 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/DirectPaymentAutomatonRunner.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/DirectPaymentAutomatonRunner.java
@@ -88,26 +88,10 @@ public class DirectPaymentAutomatonRunner {
         this.clock = clock;
 
         final long paymentPluginTimeoutSec = TimeUnit.SECONDS.convert(paymentConfig.getPaymentPluginTimeout().getPeriod(), paymentConfig.getPaymentPluginTimeout().getUnit());
-        // STEPH HACKED timeout!!!
-        this.paymentPluginDispatcher = new PluginDispatcher<OperationResult>(paymentPluginTimeoutSec * 1000, executor);
+        this.paymentPluginDispatcher = new PluginDispatcher<OperationResult>(paymentPluginTimeoutSec, executor);
 
     }
 
-    public UUID run(final TransactionType transactionType, final Account account,
-                    @Nullable final UUID directPaymentId, final String directPaymentTransactionExternalKey,
-                    final boolean shouldLockAccount, final Iterable<PluginProperty> properties,
-                    final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-        return run(transactionType, account, null, directPaymentId, null, directPaymentTransactionExternalKey, null, null, shouldLockAccount, properties, callContext, internalCallContext);
-    }
-
-    public UUID run(final TransactionType transactionType, final Account account,
-                    @Nullable final UUID directPaymentId, final String directPaymentTransactionExternalKey,
-                    final BigDecimal amount, final Currency currency,
-                    final boolean shouldLockAccount, final Iterable<PluginProperty> properties,
-                    final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-        return run(transactionType, account, null, directPaymentId, null, directPaymentTransactionExternalKey, amount, currency, shouldLockAccount, properties, callContext, internalCallContext);
-    }
-
     public UUID run(final TransactionType transactionType, final Account account, @Nullable final UUID paymentMethodId,
                     @Nullable final UUID directPaymentId, @Nullable final String directPaymentExternalKey, final String directPaymentTransactionExternalKey,
                     @Nullable final BigDecimal amount, @Nullable final Currency currency,
@@ -120,22 +104,22 @@ public class DirectPaymentAutomatonRunner {
                                                                                                   account, paymentMethodId, amount, currency, shouldLockAccount, properties, internalCallContext, callContext);
         final DirectPaymentAutomatonDAOHelper daoHelper = new DirectPaymentAutomatonDAOHelper(directPaymentStateContext, utcNow, paymentDao, pluginRegistry, internalCallContext);
 
-        final UUID nonNullPaymentMethodId;
+        final UUID effectivePaymentMethodId;
         final String currentStateMachineName;
         final String currentStateName;
         if (directPaymentId != null) {
             final PaymentModelDao paymentModelDao = daoHelper.getDirectPayment();
-            nonNullPaymentMethodId = paymentModelDao.getPaymentMethodId();
+            effectivePaymentMethodId = paymentModelDao.getPaymentMethodId();
             currentStateName = paymentModelDao.getStateName();
             currentStateMachineName = getStateMachineName(currentStateName);
 
             // Check for illegal states (should never happen)
             Preconditions.checkState(currentStateMachineName != null, "State machine name cannot be null for direct payment " + directPaymentId);
             Preconditions.checkState(currentStateName != null, "State name cannot be null for direct payment " + directPaymentId);
-            Preconditions.checkState(paymentMethodId == null || nonNullPaymentMethodId.equals(paymentMethodId), "Specified payment method id " + paymentMethodId + " doesn't match the one on the payment " + nonNullPaymentMethodId);
+            Preconditions.checkState(paymentMethodId == null || effectivePaymentMethodId.equals(paymentMethodId), "Specified payment method id " + paymentMethodId + " doesn't match the one on the payment " + effectivePaymentMethodId);
         } else {
             // If the payment method is not specified, retrieve the default one on the account
-            nonNullPaymentMethodId = paymentMethodId != null ? paymentMethodId : daoHelper.getDefaultPaymentMethodId();
+            effectivePaymentMethodId = paymentMethodId != null ? paymentMethodId : daoHelper.getDefaultPaymentMethodId();
 
             switch (transactionType) {
                 case AUTHORIZE:
@@ -155,7 +139,7 @@ public class DirectPaymentAutomatonRunner {
             }
         }
 
-        directPaymentStateContext.setPaymentMethodId(nonNullPaymentMethodId);
+        directPaymentStateContext.setPaymentMethodId(effectivePaymentMethodId);
 
         final String operationStateMachineName;
         final String operationName;
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestEventJson.java b/payment/src/test/java/org/killbill/billing/payment/api/TestEventJson.java
index a8b0471..3abbc18 100644
--- a/payment/src/test/java/org/killbill/billing/payment/api/TestEventJson.java
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestEventJson.java
@@ -33,7 +33,7 @@ public class TestEventJson extends PaymentTestSuiteNoDB {
 
     @Test(groups = "fast")
     public void testPaymentErrorEvent() throws Exception {
-        final PaymentErrorInternalEvent e = new DefaultPaymentErrorEvent(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), "no message", 1L, 2L, UUID.randomUUID());
+        final PaymentErrorInternalEvent e = new DefaultPaymentErrorEvent(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), TransactionType.PURCHASE, "no message", 1L, 2L, UUID.randomUUID());
         final String json = mapper.writeValueAsString(e);
 
         final Class<?> claz = Class.forName(DefaultPaymentErrorEvent.class.getName());
@@ -44,7 +44,7 @@ public class TestEventJson extends PaymentTestSuiteNoDB {
     @Test(groups = "fast")
     public void testPaymentInfoEvent() throws Exception {
         final PaymentInfoInternalEvent e = new DefaultPaymentInfoEvent(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), new BigDecimal(12.9), new Integer(13), TransactionStatus.SUCCESS,
-                                                                       new DateTime(), 1L, 2L, UUID.randomUUID());
+                                                                       TransactionType.PURCHASE, new DateTime(), 1L, 2L, UUID.randomUUID());
         final String json = mapper.writeValueAsString(e);
 
         final Class<?> clazz = Class.forName(DefaultPaymentInfoEvent.class.getName());
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java
index 856aba6..d9d9898 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestOverdue.java
@@ -36,9 +36,7 @@ import static org.testng.Assert.assertEquals;
 
 public class TestOverdue extends TestJaxrsBase {
 
-    // STEPH need to rework the check for default payment method so it happens after we created the payment/transaction and also ensure
-    // payment event event is correctly sent upon exceptions.
-    @Test(groups = "slow", description = "Can retrieve the account overdue status", enabled=false)
+    @Test(groups = "slow", description = "Can retrieve the account overdue status")
     public void testOverdueStatus() throws Exception {
         // Create an account without a payment method
         final Account accountJson = createAccountNoPMBundleAndSubscriptionAndWaitForFirstInvoice();