killbill-memoizeit

Move payment bus events from within DAO transaction Keep sending

7/10/2014 10:36:29 PM

Changes

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 48a9c51..3b5889f 100644
--- a/api/src/main/java/org/killbill/billing/events/PaymentErrorInternalEvent.java
+++ b/api/src/main/java/org/killbill/billing/events/PaymentErrorInternalEvent.java
@@ -23,8 +23,6 @@ public interface PaymentErrorInternalEvent extends BusInternalEvent {
 
     public String getMessage();
 
-    public UUID getInvoiceId();
-
     public UUID getAccountId();
 
     public UUID getPaymentId();
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 49f0ecd..f1265b9 100644
--- a/api/src/main/java/org/killbill/billing/events/PaymentInfoInternalEvent.java
+++ b/api/src/main/java/org/killbill/billing/events/PaymentInfoInternalEvent.java
@@ -20,6 +20,7 @@ import java.math.BigDecimal;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
+import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.payment.api.TransactionStatus;
 import org.killbill.billing.payment.api.TransactionType;
 
@@ -29,13 +30,11 @@ public interface PaymentInfoInternalEvent extends BusInternalEvent {
 
     public UUID getAccountId();
 
-    public UUID getInvoiceId();
-
     public BigDecimal getAmount();
 
-    public DateTime getEffectiveDate();
+    public Currency getCurrency();
 
-    public Integer getPaymentNumber();
+    public DateTime getEffectiveDate();
 
     public TransactionStatus getStatus();
 
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 f4743ad..a0198cc 100644
--- a/api/src/main/java/org/killbill/billing/events/PaymentPluginErrorInternalEvent.java
+++ b/api/src/main/java/org/killbill/billing/events/PaymentPluginErrorInternalEvent.java
@@ -23,8 +23,6 @@ public interface PaymentPluginErrorInternalEvent extends BusInternalEvent {
 
     public String getMessage();
 
-    public UUID getInvoiceId();
-
     public UUID getAccountId();
 
     public UUID getPaymentId();
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 5f035f4..f7c366d 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
@@ -54,9 +54,9 @@ public class InvoicePaymentJson extends PaymentJson {
         this.targetInvoiceId = targetInvoiceId;
     }
 
-    public InvoicePaymentJson(final Payment dp, @Nullable final UUID invoiceId, @Nullable final AccountAuditLogs accountAuditLogs) {
-        super(dp, accountAuditLogs);
-        // STEPH we should build InvoicePaymentTransactionJson instead of PaymentTransactionJson here.
+    public InvoicePaymentJson(final Payment payment, @Nullable final UUID invoiceId, @Nullable final AccountAuditLogs accountAuditLogs) {
+        super(payment, accountAuditLogs);
+        //  TODO should build InvoicePaymentTransactionJson instead of PaymentTransactionJson here.
         this.targetInvoiceId = invoiceId != null ? invoiceId.toString() : null;
     }
 
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/mappers/PaymentApiExceptionMapper.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/mappers/PaymentApiExceptionMapper.java
index c4edfd2..9fb84ad 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/mappers/PaymentApiExceptionMapper.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/mappers/PaymentApiExceptionMapper.java
@@ -42,6 +42,8 @@ public class PaymentApiExceptionMapper extends ExceptionMapperBase implements Ex
             return buildBadRequestResponse(exception, uriInfo);
         } else if (exception.getCode() == ErrorCode.PAYMENT_CREATE_PAYMENT.getCode()) {
             return buildInternalErrorResponse(exception, uriInfo);
+        } else if (exception.getCode() == ErrorCode.PAYMENT_REFUND_AMOUNT_NEGATIVE_OR_NULL.getCode()) {
+            return buildInternalErrorResponse(exception, uriInfo);
         } else if (exception.getCode() == ErrorCode.PAYMENT_DEL_DEFAULT_PAYMENT_METHOD.getCode()) {
             return buildBadRequestResponse(exception, uriInfo);
         } else if (exception.getCode() == ErrorCode.PAYMENT_DEL_PAYMENT_METHOD.getCode()) {
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 008d171..0c900cc 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
@@ -71,7 +71,7 @@ public class DefaultPaymentApi implements PaymentApi {
         checkNotNullParameter(properties, "plugin properties");
         checkPositiveAmount(amount);
 
-        logAPICall(TransactionType.AUTHORIZE.toString(), account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey);
+        logAPICall(TransactionType.AUTHORIZE, account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey);
 
         final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
         return paymentProcessor.createAuthorization(IS_API_PAYMENT, null, account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey,
@@ -88,7 +88,7 @@ public class DefaultPaymentApi implements PaymentApi {
         checkNotNullParameter(properties, "plugin properties");
         checkPositiveAmount(amount);
 
-        logAPICall(TransactionType.CAPTURE.toString(), account, null, paymentId, amount, currency, null, paymentTransactionExternalKey);
+        logAPICall(TransactionType.CAPTURE, account, null, paymentId, amount, currency, null, paymentTransactionExternalKey);
 
         final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
         return paymentProcessor.createCapture(IS_API_PAYMENT, null, account, paymentId, amount, currency, paymentTransactionExternalKey,
@@ -106,7 +106,7 @@ public class DefaultPaymentApi implements PaymentApi {
         checkNotNullParameter(properties, "plugin properties");
         checkPositiveAmount(amount);
 
-        logAPICall(TransactionType.PURCHASE.toString(), account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey);
+        logAPICall(TransactionType.PURCHASE, account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey);
 
         final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
         return paymentProcessor.createPurchase(IS_API_PAYMENT, null, account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey,
@@ -125,7 +125,7 @@ public class DefaultPaymentApi implements PaymentApi {
         checkNotNullParameter(properties, "plugin properties");
         checkPositiveAmount(amount);
 
-        logAPICall(TransactionType.PURCHASE.toString(), account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey);
+        logAPICall(TransactionType.PURCHASE, account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey);
 
         if (paymentMethodId == null && !paymentOptions.isExternalPayment()) {
             throw new PaymentApiException(ErrorCode.PAYMENT_INVALID_PARAMETER, "paymentMethodId", "should not be null");
@@ -150,7 +150,7 @@ public class DefaultPaymentApi implements PaymentApi {
         checkNotNullParameter(paymentId, "paymentId");
         checkNotNullParameter(properties, "plugin properties");
 
-        logAPICall(TransactionType.VOID.toString(), account, null, paymentId, null, null, null, paymentTransactionExternalKey);
+        logAPICall(TransactionType.VOID, account, null, paymentId, null, null, null, paymentTransactionExternalKey);
 
         final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
         return paymentProcessor.createVoid(IS_API_PAYMENT, null, account, paymentId, paymentTransactionExternalKey,
@@ -169,7 +169,7 @@ public class DefaultPaymentApi implements PaymentApi {
         checkNotNullParameter(properties, "plugin properties");
         checkPositiveAmount(amount);
 
-        logAPICall(TransactionType.REFUND.toString(), account, null, paymentId, amount, currency, null, paymentTransactionExternalKey);
+        logAPICall(TransactionType.REFUND, account, null, paymentId, amount, currency, null, paymentTransactionExternalKey);
 
         final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
         return paymentProcessor.createRefund(IS_API_PAYMENT, null, account, paymentId, amount, currency, paymentTransactionExternalKey,
@@ -189,7 +189,7 @@ public class DefaultPaymentApi implements PaymentApi {
             checkPositiveAmount(amount);
         }
 
-        logAPICall(TransactionType.REFUND.toString(), account, null, paymentId, amount, currency, null, paymentTransactionExternalKey);
+        logAPICall(TransactionType.REFUND, account, null, paymentId, amount, currency, null, paymentTransactionExternalKey);
 
         final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
         return pluginControlledPaymentProcessor.createRefund(IS_API_PAYMENT, account, paymentId, amount, currency, paymentTransactionExternalKey,
@@ -210,7 +210,7 @@ public class DefaultPaymentApi implements PaymentApi {
         checkNotNullParameter(properties, "plugin properties");
         checkPositiveAmount(amount);
 
-        logAPICall(TransactionType.CREDIT.toString(), account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey);
+        logAPICall(TransactionType.CREDIT, account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey);
 
         final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
         return paymentProcessor.createCredit(IS_API_PAYMENT, null, account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey,
@@ -224,7 +224,7 @@ public class DefaultPaymentApi implements PaymentApi {
         checkNotNullParameter(account, "account");
         checkNotNullParameter(paymentTransactionId, "paymentTransactionId");
 
-        logAPICall("PENDING_STATE_CHANGED", account, null, paymentTransactionId /* STEPH TBD if this is paymentId or transactionId */, null, null, null, null);
+        logAPICall(TransactionType.NOTIFY_STATE_CHANGE, account, null, paymentTransactionId /* STEPH TBD if this is paymentId or transactionId */, null, null, null, null);
 
         final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
         paymentProcessor.notifyPendingPaymentOfStateChanged(account, paymentTransactionId, isSuccess, callContext, internalCallContext);
@@ -244,7 +244,7 @@ public class DefaultPaymentApi implements PaymentApi {
         checkNotNullParameter(paymentId, "paymentId");
         checkPositiveAmount(amount);
 
-        logAPICall(TransactionType.CHARGEBACK.toString(), account, null, paymentId, amount, currency, null, paymentTransactionExternalKey);
+        logAPICall(TransactionType.CHARGEBACK, account, null, paymentId, amount, currency, null, paymentTransactionExternalKey);
 
         final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
         return paymentProcessor.createChargeback(IS_API_PAYMENT, null, account, paymentId, paymentTransactionExternalKey, amount, currency, true,
@@ -389,7 +389,7 @@ public class DefaultPaymentApi implements PaymentApi {
         return paymentMethods;
     }
 
-    private void logAPICall(final String transactionType, final Account account, final UUID paymentMethodId, @Nullable final UUID paymentId, @Nullable final BigDecimal amount, @Nullable final Currency currency, @Nullable final String paymentExternalKey, @Nullable final String paymentTransactionExternalKey) {
+    private void logAPICall(final TransactionType transactionType, final Account account, final UUID paymentMethodId, @Nullable final UUID paymentId, @Nullable final BigDecimal amount, @Nullable final Currency currency, @Nullable final String paymentExternalKey, @Nullable final String paymentTransactionExternalKey) {
         if (log.isInfoEnabled()) {
             final StringBuilder logLine = new StringBuilder();
             logLine.append("PaymentApi : ")
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 7e95787..82afcb7 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
@@ -29,13 +29,11 @@ public class DefaultPaymentErrorEvent extends BusEventBase implements PaymentErr
 
     private final String message;
     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,
@@ -45,7 +43,6 @@ public class DefaultPaymentErrorEvent extends BusEventBase implements PaymentErr
         super(searchKey1, searchKey2, userToken);
         this.message = message;
         this.accountId = accountId;
-        this.invoiceId = invoiceId;
         this.paymentId = paymentId;
         this.transactionType = transactionType;
     }
@@ -61,11 +58,6 @@ public class DefaultPaymentErrorEvent extends BusEventBase implements PaymentErr
     }
 
     @Override
-    public UUID getInvoiceId() {
-        return invoiceId;
-    }
-
-    @Override
     public UUID getPaymentId() {
         return paymentId;
     }
@@ -98,9 +90,6 @@ public class DefaultPaymentErrorEvent extends BusEventBase implements PaymentErr
         if (transactionType != null ? !transactionType.equals(that.transactionType) : that.transactionType != null) {
             return false;
         }
-        if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
-            return false;
-        }
         if (message != null ? !message.equals(that.message) : that.message != null) {
             return false;
         }
@@ -116,7 +105,6 @@ public class DefaultPaymentErrorEvent extends BusEventBase implements PaymentErr
         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 b42844d..d3d73b2 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
@@ -20,6 +20,7 @@ import java.math.BigDecimal;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
+import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.events.BusEventBase;
 import org.killbill.billing.events.PaymentInfoInternalEvent;
 
@@ -30,20 +31,18 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfoInternalEvent {
 
     private final UUID accountId;
-    private final UUID invoiceId;
     private final UUID paymentId;
     private final BigDecimal amount;
-    private final Integer paymentNumber;
+    private final Currency currency;
     private final TransactionStatus status;
     private final TransactionType transactionType;
     private final DateTime effectiveDate;
 
     @JsonCreator
     public DefaultPaymentInfoEvent(@JsonProperty("accountId") final UUID accountId,
-                                   @JsonProperty("invoiceId") final UUID invoiceId,
                                    @JsonProperty("paymentId") final UUID paymentId,
                                    @JsonProperty("amount") final BigDecimal amount,
-                                   @JsonProperty("paymentNumber") final Integer paymentNumber,
+                                   @JsonProperty("currency") final Currency currency,
                                    @JsonProperty("status") final TransactionStatus status,
                                    @JsonProperty("transactionType")  final TransactionType transactionType,
                                    @JsonProperty("extFirstPaymentRefId") final String extFirstPaymentRefId /* TODO for backward compatibility only */,
@@ -54,24 +53,25 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
                                    @JsonProperty("userToken") final UUID userToken) {
         super(searchKey1, searchKey2, userToken);
         this.accountId = accountId;
-        this.invoiceId = invoiceId;
         this.paymentId = paymentId;
         this.amount = amount;
-        this.paymentNumber = paymentNumber;
+        this.currency = currency;
         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,
+    public DefaultPaymentInfoEvent(final UUID accountId,
+                                   final UUID paymentId,
+                                   final BigDecimal amount,
+                                   final Currency currency,
                                    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, transactionType, null, null,
+        this(accountId, paymentId, amount, currency, status, transactionType, null, null,
              effectiveDate, searchKey1, searchKey2, userToken);
     }
 
@@ -86,10 +86,6 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
         return accountId;
     }
 
-    @Override
-    public UUID getInvoiceId() {
-        return invoiceId;
-    }
 
     @Override
     public BigDecimal getAmount() {
@@ -97,6 +93,11 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
     }
 
     @Override
+    public Currency getCurrency() {
+        return currency;
+    }
+
+    @Override
     public DateTime getEffectiveDate() {
         return effectiveDate;
     }
@@ -106,10 +107,6 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
         return paymentId;
     }
 
-    public Integer getPaymentNumber() {
-        return paymentNumber;
-    }
-
     @Override
     public TransactionType getTransactionType() {
         return transactionType;
@@ -125,10 +122,9 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
         final StringBuilder sb = new StringBuilder();
         sb.append("DefaultPaymentInfoEvent");
         sb.append("{accountId=").append(accountId);
-        sb.append(", invoiceId=").append(invoiceId);
         sb.append(", paymentId=").append(paymentId);
         sb.append(", amount=").append(amount);
-        sb.append(", paymentNumber=").append(paymentNumber);
+        sb.append(", currency=").append(currency);
         sb.append(", status=").append(status);
         sb.append(", transactionType=").append(transactionType);
         sb.append(", effectiveDate=").append(effectiveDate);
@@ -146,11 +142,9 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
         result = prime * result
                  + ((effectiveDate == null) ? 0 : effectiveDate.hashCode());
         result = prime * result
-                 + ((invoiceId == null) ? 0 : invoiceId.hashCode());
-        result = prime * result
                  + ((paymentId == null) ? 0 : paymentId.hashCode());
         result = prime * result
-                 + ((paymentNumber == null) ? 0 : paymentNumber.hashCode());
+                 + ((currency == null) ? 0 : currency.hashCode());
         result = prime * result + ((status == null) ? 0 : status.hashCode());
         return result;
     }
@@ -195,13 +189,6 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
         } else if (effectiveDate.compareTo(other.effectiveDate) != 0) {
             return false;
         }
-        if (invoiceId == null) {
-            if (other.invoiceId != null) {
-                return false;
-            }
-        } else if (!invoiceId.equals(other.invoiceId)) {
-            return false;
-        }
         if (paymentId == null) {
             if (other.paymentId != null) {
                 return false;
@@ -209,11 +196,11 @@ public class DefaultPaymentInfoEvent extends BusEventBase implements PaymentInfo
         } else if (!paymentId.equals(other.paymentId)) {
             return false;
         }
-        if (paymentNumber == null) {
-            if (other.paymentNumber != null) {
+        if (currency == null) {
+            if (other.currency != null) {
                 return false;
             }
-        } else if (!paymentNumber.equals(other.paymentNumber)) {
+        } else if (!currency.equals(other.currency)) {
             return false;
         }
         if (status != other.status) {
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 c22fa02..5ef1ac2 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
@@ -28,13 +28,11 @@ public class DefaultPaymentPluginErrorEvent extends BusEventBase implements Paym
 
     private final String message;
     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,
@@ -44,7 +42,6 @@ public class DefaultPaymentPluginErrorEvent extends BusEventBase implements Paym
         super(searchKey1, searchKey2, userToken);
         this.message = message;
         this.accountId = accountId;
-        this.invoiceId = invoiceId;
         this.paymentId = paymentId;
         this.transactionType = transactionType;
     }
@@ -60,11 +57,6 @@ public class DefaultPaymentPluginErrorEvent extends BusEventBase implements Paym
     }
 
     @Override
-    public UUID getInvoiceId() {
-        return invoiceId;
-    }
-
-    @Override
     public UUID getPaymentId() {
         return paymentId;
     }
@@ -97,9 +89,6 @@ public class DefaultPaymentPluginErrorEvent extends BusEventBase implements Paym
         if (transactionType != null ? !transactionType.equals(that.transactionType) : that.transactionType != null) {
             return false;
         }
-        if (invoiceId != null ? !invoiceId.equals(that.invoiceId) : that.invoiceId != null) {
-            return false;
-        }
         if (message != null ? !message.equals(that.message) : that.message != null) {
             return false;
         }
@@ -115,7 +104,6 @@ public class DefaultPaymentPluginErrorEvent extends BusEventBase implements Paym
         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/PaymentGatewayProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentGatewayProcessor.java
index 9fdf44a..b4f3698 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PaymentGatewayProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentGatewayProcessor.java
@@ -71,12 +71,11 @@ public class PaymentGatewayProcessor extends ProcessorBase {
                                    final TagInternalApi tagUserApi,
                                    final PaymentDao paymentDao,
                                    final NonEntityDao nonEntityDao,
-                                   final PersistentBus eventBus,
                                    final GlobalLocker locker,
                                    final PaymentConfig paymentConfig,
                                    @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor,
-                                  final Clock clock) {
-        super(pluginRegistry, accountUserApi, eventBus, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi, clock);
+                                   final Clock clock) {
+        super(pluginRegistry, accountUserApi, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi, clock);
         final long paymentPluginTimeoutSec = TimeUnit.SECONDS.convert(paymentConfig.getPaymentPluginTimeout().getPeriod(), paymentConfig.getPaymentPluginTimeout().getUnit());
         this.paymentPluginFormDispatcher = new PluginDispatcher<HostedPaymentPageFormDescriptor>(paymentPluginTimeoutSec, executor);
         this.paymentPluginNotificationDispatcher = new PluginDispatcher<GatewayNotification>(paymentPluginTimeoutSec, executor);
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 ca7dca0..484b60c 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
@@ -79,14 +79,13 @@ public class PaymentMethodProcessor extends ProcessorBase {
     public PaymentMethodProcessor(final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry,
                                   final AccountInternalApi accountInternalApi,
                                   final InvoiceInternalApi invoiceApi,
-                                  final PersistentBus eventBus,
                                   final PaymentDao paymentDao,
                                   final NonEntityDao nonEntityDao,
                                   final TagInternalApi tagUserApi,
                                   final GlobalLocker locker,
                                   @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor,
                                   final Clock clock) {
-        super(pluginRegistry, accountInternalApi, eventBus, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi, clock);
+        super(pluginRegistry, accountInternalApi, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi, clock);
     }
 
     public UUID addPaymentMethod(final String paymentMethodExternalKey, final String paymentPluginServiceName, final Account account,
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 100b72f..011800a 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
@@ -35,13 +35,9 @@ import org.killbill.billing.account.api.AccountInternalApi;
 import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.api.Currency;
-import org.killbill.billing.events.BusInternalEvent;
 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.DefaultPaymentErrorEvent;
-import org.killbill.billing.payment.api.DefaultPaymentInfoEvent;
-import org.killbill.billing.payment.api.DefaultPaymentPluginErrorEvent;
 import org.killbill.billing.payment.api.DefaultPaymentTransaction;
 import org.killbill.billing.payment.api.Payment;
 import org.killbill.billing.payment.api.PaymentApiException;
@@ -99,14 +95,13 @@ public class PaymentProcessor extends ProcessorBase {
                             final TagInternalApi tagUserApi,
                             final PaymentDao paymentDao,
                             final NonEntityDao nonEntityDao,
-                            final PersistentBus eventBus,
                             final InternalCallContextFactory internalCallContextFactory,
                             final GlobalLocker locker,
                             @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor,
                             final PaymentAutomatonRunner paymentAutomatonRunner,
                             final PaymentStateMachineHelper paymentSMHelper,
                             final Clock clock) {
-        super(pluginRegistry, accountUserApi, eventBus, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi, clock);
+        super(pluginRegistry, accountUserApi, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi, clock);
         this.paymentSMHelper = paymentSMHelper;
         this.internalCallContextFactory = internalCallContextFactory;
         this.paymentAutomatonRunner = paymentAutomatonRunner;
@@ -182,7 +177,8 @@ public class PaymentProcessor extends ProcessorBase {
         final State currentPaymentState;
         final String stateName = paymentModelDao.getStateName();
         final String lastSuccessPaymentStateStrOrNull = paymentSMHelper.isSuccessState(stateName) ? stateName : null;
-        paymentDao.updatePaymentAndTransactionOnCompletion(transactionModelDao.getPaymentId(), stateName, lastSuccessPaymentStateStrOrNull, transactionModelDao.getId(), newStatus,
+        paymentDao.updatePaymentAndTransactionOnCompletion(account.getId(), transactionModelDao.getPaymentId(), TransactionType.NOTIFY_STATE_CHANGE,
+                                                           stateName, lastSuccessPaymentStateStrOrNull, transactionModelDao.getId(), newStatus,
                                                            transactionModelDao.getProcessedAmount(), transactionModelDao.getProcessedCurrency(),
                                                            transactionModelDao.getGatewayErrorCode(), transactionModelDao.getGatewayErrorMsg(), internalCallContext);
     }
@@ -323,28 +319,24 @@ public class PaymentProcessor extends ProcessorBase {
                                      final InternalCallContext internalCallContext) throws PaymentApiException {
 
         Payment payment = null;
-        try {
-            validateUniqueTransactionExternalKey(paymentTransactionExternalKey, internalCallContext);
-
-            final UUID nonNullPaymentId = paymentAutomatonRunner.run(transactionType,
-                                                                     account,
-                                                                     attemptId,
-                                                                     paymentMethodId,
-                                                                     paymentId,
-                                                                     paymentExternalKey,
-                                                                     paymentTransactionExternalKey,
-                                                                     amount,
-                                                                     currency,
-                                                                     shouldLockAccountAndDispatch,
-                                                                     properties,
-                                                                     callContext,
-                                                                     internalCallContext);
-            payment = getPayment(nonNullPaymentId, true, properties, callContext, internalCallContext);
-            return payment;
-        } finally {
-            postPaymentEvent(isApiPayment, account, transactionType, payment, paymentTransactionExternalKey, internalCallContext);
-
-        }
+        validateUniqueTransactionExternalKey(paymentTransactionExternalKey, internalCallContext);
+
+        final UUID nonNullPaymentId = paymentAutomatonRunner.run(isApiPayment,
+                                                                 transactionType,
+                                                                 account,
+                                                                 attemptId,
+                                                                 paymentMethodId,
+                                                                 paymentId,
+                                                                 paymentExternalKey,
+                                                                 paymentTransactionExternalKey,
+                                                                 amount,
+                                                                 currency,
+                                                                 shouldLockAccountAndDispatch,
+                                                                 properties,
+                                                                 callContext,
+                                                                 internalCallContext);
+        payment = getPayment(nonNullPaymentId, true, properties, callContext, internalCallContext);
+        return payment;
     }
 
     private Payment getPayment(final PaymentModelDao paymentModelDao, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext context, final InternalTenantContext tenantContext) throws PaymentApiException {
@@ -406,72 +398,4 @@ public class PaymentProcessor extends ProcessorBase {
         return new DefaultPayment(curPaymentModelDao.getId(), curPaymentModelDao.getCreatedDate(), curPaymentModelDao.getUpdatedDate(), curPaymentModelDao.getAccountId(),
                                   curPaymentModelDao.getPaymentMethodId(), curPaymentModelDao.getPaymentNumber(), curPaymentModelDao.getExternalKey(), sortedTransactions);
     }
-
-    private void postPaymentEvent(final boolean isApiPayment, final Account account, final TransactionType transactionType, @Nullable final Payment payment, final String transactionExternalKey, final InternalCallContext context) {
-        final BusInternalEvent event = buildPaymentEvent(isApiPayment, account, transactionType, payment, transactionExternalKey, context);
-        if (event != null) {
-            postPaymentEvent(event, account.getId(), context);
-        }
-    }
-
-    private BusInternalEvent buildPaymentEvent(final boolean isApiPayment, final Account account, final TransactionType transactionType, @Nullable final Payment payment, final String transactionExternalKey, final InternalCallContext context) {
-
-        // If an exception was thrown we don't have the payment detail but we still want to send a partially formed event for calls originating outside of API calls (e.g bus, ..)
-        if (payment == null) {
-            if (isApiPayment) {
-                return null;
-            } else {
-                return new DefaultPaymentErrorEvent(account.getId(),
-                                                    null,
-                                                    null,
-                                                    transactionType,
-                                                    "Early abortion of payment transaction",
-                                                    context.getAccountRecordId(),
-                                                    context.getTenantRecordId(),
-                                                    context.getUserToken());
-            }
-        }
-
-        final PaymentTransaction paymentTransaction = payment.getTransactions().get(payment.getTransactions().size() - 1);
-        // If the payment/transaction was created then it should match the transactionExternalKey
-        Preconditions.checkState(paymentTransaction.getExternalKey().equals(transactionExternalKey));
-        Preconditions.checkState(paymentTransaction.getTransactionType().equals(transactionType));
-
-        final TransactionStatus transactionStatus = paymentTransaction.getTransactionStatus();
-        switch (paymentTransaction.getTransactionStatus()) {
-            case SUCCESS:
-            case PENDING:
-                return new DefaultPaymentInfoEvent(account.getId(),
-                                                   null,
-                                                   payment.getId(),
-                                                   paymentTransaction.getAmount(),
-                                                   payment.getPaymentNumber(),
-                                                   transactionStatus,
-                                                   transactionType,
-                                                   paymentTransaction.getEffectiveDate(),
-                                                   context.getAccountRecordId(),
-                                                   context.getTenantRecordId(),
-                                                   context.getUserToken());
-            case PAYMENT_FAILURE:
-                return new DefaultPaymentErrorEvent(account.getId(),
-                                                    null,
-                                                    payment.getId(),
-                                                    transactionType,
-                                                    paymentTransaction.getPaymentInfoPlugin() == null ? null : paymentTransaction.getPaymentInfoPlugin().getGatewayError(),
-                                                    context.getAccountRecordId(),
-                                                    context.getTenantRecordId(),
-                                                    context.getUserToken());
-            case PLUGIN_FAILURE:
-            default:
-                return new DefaultPaymentPluginErrorEvent(account.getId(),
-                                                          null,
-                                                          payment.getId(),
-                                                          transactionType,
-                                                          paymentTransaction.getPaymentInfoPlugin() == null ? null : paymentTransaction.getPaymentInfoPlugin().getGatewayError(),
-                                                          context.getAccountRecordId(),
-                                                          context.getTenantRecordId(),
-                                                          context.getUserToken());
-        }
-    }
-
 }
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PluginControlledPaymentProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PluginControlledPaymentProcessor.java
index 1041584..513caac 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PluginControlledPaymentProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PluginControlledPaymentProcessor.java
@@ -69,13 +69,12 @@ public class PluginControlledPaymentProcessor extends ProcessorBase {
                                             final TagInternalApi tagUserApi,
                                             final PaymentDao paymentDao,
                                             final NonEntityDao nonEntityDao,
-                                            final PersistentBus eventBus,
                                             final GlobalLocker locker,
                                             @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor,
                                             final PluginControlledPaymentAutomatonRunner pluginControlledPaymentAutomatonRunner,
                                             final RetryStateMachineHelper retrySMHelper,
                                             final Clock clock) {
-        super(pluginRegistry, accountInternalApi, eventBus, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi, clock);
+        super(pluginRegistry, accountInternalApi, paymentDao, nonEntityDao, tagUserApi, locker, executor, invoiceApi, clock);
         this.retrySMHelper = retrySMHelper;
         this.pluginControlledPaymentAutomatonRunner = pluginControlledPaymentAutomatonRunner;
     }
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java b/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java
index b396c2f..59a8ca6 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/ProcessorBase.java
@@ -72,7 +72,6 @@ public abstract class ProcessorBase {
 
     protected final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry;
     protected final AccountInternalApi accountInternalApi;
-    protected final PersistentBus eventBus;
     protected final GlobalLocker locker;
     protected final ExecutorService executor;
     protected final PaymentDao paymentDao;
@@ -85,7 +84,6 @@ public abstract class ProcessorBase {
 
     public ProcessorBase(final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry,
                          final AccountInternalApi accountInternalApi,
-                         final PersistentBus eventBus,
                          final PaymentDao paymentDao,
                          final NonEntityDao nonEntityDao,
                          final TagInternalApi tagInternalApi,
@@ -95,7 +93,6 @@ public abstract class ProcessorBase {
                          final Clock clock) {
         this.pluginRegistry = pluginRegistry;
         this.accountInternalApi = accountInternalApi;
-        this.eventBus = eventBus;
         this.paymentDao = paymentDao;
         this.nonEntityDao = nonEntityDao;
         this.locker = locker;
@@ -160,16 +157,6 @@ public abstract class ProcessorBase {
         return paymentMethodId;
     }
 
-    protected void postPaymentEvent(final BusInternalEvent ev, final UUID accountId, final InternalCallContext context) {
-        if (ev == null) {
-            return;
-        }
-        try {
-            eventBus.post(ev);
-        } catch (EventBusException e) {
-            log.error("Failed to post Payment event event for account {} ", accountId, e);
-        }
-    }
 
     protected TenantContext buildTenantContext(final InternalTenantContext context) {
         return context.toTenantContext(nonEntityDao.retrieveIdFromObject(context.getTenantRecordId(), ObjectType.TENANT));
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonDAOHelper.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonDAOHelper.java
index 1a964c8..5e5cf0c 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonDAOHelper.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonDAOHelper.java
@@ -25,22 +25,35 @@ import javax.annotation.Nullable;
 
 import org.joda.time.DateTime;
 import org.killbill.billing.ErrorCode;
+import org.killbill.billing.account.api.Account;
 import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.catalog.api.Currency;
+import org.killbill.billing.events.BusInternalEvent;
 import org.killbill.billing.osgi.api.OSGIServiceRegistration;
+import org.killbill.billing.payment.api.DefaultPaymentErrorEvent;
+import org.killbill.billing.payment.api.DefaultPaymentInfoEvent;
+import org.killbill.billing.payment.api.DefaultPaymentPluginErrorEvent;
 import org.killbill.billing.payment.api.PaymentApiException;
 import org.killbill.billing.payment.api.TransactionStatus;
+import org.killbill.billing.payment.api.TransactionType;
 import org.killbill.billing.payment.dao.PaymentDao;
 import org.killbill.billing.payment.dao.PaymentMethodModelDao;
 import org.killbill.billing.payment.dao.PaymentModelDao;
 import org.killbill.billing.payment.dao.PaymentTransactionModelDao;
 import org.killbill.billing.payment.plugin.api.PaymentPluginApi;
 import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.bus.api.PersistentBus;
+import org.killbill.bus.api.PersistentBus.EventBusException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 public class PaymentAutomatonDAOHelper {
 
+    private static final Logger log = LoggerFactory.getLogger(PaymentAutomatonDAOHelper.class);
+
     protected final PaymentStateContext paymentStateContext;
     protected final DateTime utcNow;
     protected final InternalCallContext internalCallContext;
@@ -49,18 +62,21 @@ public class PaymentAutomatonDAOHelper {
     protected final PaymentDao paymentDao;
 
     private final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry;
+    private final PersistentBus eventBus;
 
     // Used to build new payments and transactions
     public PaymentAutomatonDAOHelper(final PaymentStateContext paymentStateContext,
                                      final DateTime utcNow, final PaymentDao paymentDao,
                                      final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry,
                                      final InternalCallContext internalCallContext,
+                                     final PersistentBus eventBus,
                                      final PaymentStateMachineHelper paymentSMHelper) throws PaymentApiException {
         this.paymentStateContext = paymentStateContext;
         this.utcNow = utcNow;
         this.paymentDao = paymentDao;
         this.pluginRegistry = pluginRegistry;
         this.internalCallContext = internalCallContext;
+        this.eventBus = eventBus;
         this.paymentSMHelper = paymentSMHelper;
     }
 
@@ -101,16 +117,18 @@ public class PaymentAutomatonDAOHelper {
         final String gatewayErrorMsg = paymentInfoPlugin == null ? null : paymentInfoPlugin.getGatewayError();
 
         final String lastSuccessPaymentState = paymentSMHelper.isSuccessState(currentPaymentStateName) ? currentPaymentStateName : null;
-        paymentDao.updatePaymentAndTransactionOnCompletion(paymentStateContext.getPaymentId(),
-                                                                 currentPaymentStateName,
-                                                                 lastSuccessPaymentState,
-                                                                 paymentStateContext.getPaymentTransactionModelDao().getId(),
-                                                                 paymentStatus,
-                                                                 processedAmount,
-                                                                 processedCurrency,
-                                                                 gatewayErrorCode,
-                                                                 gatewayErrorMsg,
-                                                                 internalCallContext);
+        paymentDao.updatePaymentAndTransactionOnCompletion(paymentStateContext.getAccount().getId(),
+                                                           paymentStateContext.getPaymentId(),
+                                                           paymentStateContext.getTransactionType(),
+                                                           currentPaymentStateName,
+                                                           lastSuccessPaymentState,
+                                                           paymentStateContext.getPaymentTransactionModelDao().getId(),
+                                                           paymentStatus,
+                                                           processedAmount,
+                                                           processedCurrency,
+                                                           gatewayErrorCode,
+                                                           gatewayErrorMsg,
+                                                           internalCallContext);
 
         // Update the context
         paymentStateContext.setPaymentTransactionModelDao(paymentDao.getPaymentTransaction(paymentStateContext.getPaymentTransactionModelDao().getId(), internalCallContext));
@@ -143,6 +161,10 @@ public class PaymentAutomatonDAOHelper {
         return paymentModelDao;
     }
 
+    public PersistentBus getEventBus() {
+        return eventBus;
+    }
+
     private PaymentModelDao buildNewPaymentModelDao() {
         final DateTime createdDate = utcNow;
         final DateTime updatedDate = utcNow;
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonRunner.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonRunner.java
index c31ee0c..3b8068a 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonRunner.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentAutomatonRunner.java
@@ -52,6 +52,7 @@ import org.killbill.billing.payment.glue.PaymentModule;
 import org.killbill.billing.payment.plugin.api.PaymentPluginApi;
 import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.billing.util.config.PaymentConfig;
+import org.killbill.bus.api.PersistentBus;
 import org.killbill.clock.Clock;
 import org.killbill.commons.locker.GlobalLocker;
 
@@ -72,6 +73,7 @@ public class PaymentAutomatonRunner {
     protected final PluginDispatcher<OperationResult> paymentPluginDispatcher;
     protected final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry;
     protected final Clock clock;
+    private final PersistentBus eventBus;
 
     @Inject
     public PaymentAutomatonRunner(@javax.inject.Named(PaymentModule.STATE_MACHINE_PAYMENT) final StateMachineConfig stateMachineConfig,
@@ -81,19 +83,21 @@ public class PaymentAutomatonRunner {
                                   final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry,
                                   final Clock clock,
                                   @Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor,
+                                  final PersistentBus eventBus,
                                   final PaymentStateMachineHelper paymentSMHelper) {
         this.paymentSMHelper = paymentSMHelper;
         this.paymentDao = paymentDao;
         this.locker = locker;
         this.pluginRegistry = pluginRegistry;
         this.clock = clock;
+        this.eventBus = eventBus;
 
         final long paymentPluginTimeoutSec = TimeUnit.SECONDS.convert(paymentConfig.getPaymentPluginTimeout().getPeriod(), paymentConfig.getPaymentPluginTimeout().getUnit());
         this.paymentPluginDispatcher = new PluginDispatcher<OperationResult>(paymentPluginTimeoutSec, executor);
 
     }
 
-    public UUID run(final TransactionType transactionType, final Account account, @Nullable final UUID attemptId, @Nullable final UUID paymentMethodId,
+    public UUID run(final boolean isApiPayment, final TransactionType transactionType, final Account account, @Nullable final UUID attemptId, @Nullable final UUID paymentMethodId,
                     @Nullable final UUID paymentId, @Nullable final String paymentExternalKey, final String paymentTransactionExternalKey,
                     @Nullable final BigDecimal amount, @Nullable final Currency currency,
                     final boolean shouldLockAccount, final Iterable<PluginProperty> properties,
@@ -101,12 +105,11 @@ public class PaymentAutomatonRunner {
 
         final DateTime utcNow = clock.getUTCNow();
 
-        final PaymentStateContext paymentStateContext = new PaymentStateContext(paymentId, attemptId, paymentExternalKey, paymentTransactionExternalKey, transactionType,
+        final PaymentStateContext paymentStateContext = new PaymentStateContext(isApiPayment, paymentId, attemptId, paymentExternalKey, paymentTransactionExternalKey, transactionType,
                                                                                                   account, paymentMethodId, amount, currency, shouldLockAccount, properties, internalCallContext, callContext);
-        final PaymentAutomatonDAOHelper daoHelper = new PaymentAutomatonDAOHelper(paymentStateContext, utcNow, paymentDao, pluginRegistry, internalCallContext, paymentSMHelper);
+        final PaymentAutomatonDAOHelper daoHelper = new PaymentAutomatonDAOHelper(paymentStateContext, utcNow, paymentDao, pluginRegistry, internalCallContext, eventBus, paymentSMHelper);
 
         final UUID effectivePaymentMethodId;
-        final String currentStateMachineName;
         final String currentStateName;
         if (paymentId != null) {
             final PaymentModelDao paymentModelDao = daoHelper.getPayment();
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentEnteringStateCallback.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentEnteringStateCallback.java
index a37ad65..430b132 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentEnteringStateCallback.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentEnteringStateCallback.java
@@ -24,9 +24,16 @@ import org.killbill.automaton.OperationResult;
 import org.killbill.automaton.State;
 import org.killbill.automaton.State.EnteringStateCallback;
 import org.killbill.automaton.State.LeavingStateCallback;
+import org.killbill.billing.account.api.Account;
+import org.killbill.billing.callcontext.InternalCallContext;
+import org.killbill.billing.events.BusInternalEvent;
+import org.killbill.billing.payment.api.DefaultPaymentErrorEvent;
 import org.killbill.billing.payment.api.PaymentApiException;
 import org.killbill.billing.payment.api.TransactionStatus;
+import org.killbill.billing.payment.api.TransactionType;
+import org.killbill.billing.payment.dao.PaymentTransactionModelDao;
 import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.bus.api.PersistentBus.EventBusException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,6 +58,23 @@ public abstract class PaymentEnteringStateCallback implements EnteringStateCallb
             final PaymentTransactionInfoPlugin paymentInfoPlugin = paymentStateContext.getPaymentInfoPlugin();
             final TransactionStatus paymentStatus = paymentPluginStatusToPaymentStatus(paymentInfoPlugin, operationResult);
             daoHelper.processPaymentInfoPlugin(paymentStatus, paymentInfoPlugin, newState.getName());
+        } else if (paymentStateContext.isApiPayment()) {
+            //
+            // If there is transaction to update (because payment transaction did not occur), we still want to send a bus event when the call originates from api
+            // to notify listeners that some transaction occurred for that specific account.
+            //
+            final BusInternalEvent event = new DefaultPaymentErrorEvent(paymentStateContext.getAccount().getId(),
+                                                                        null,
+                                                                        paymentStateContext.getTransactionType(),
+                                                                        "Early abortion of payment transaction",
+                                                                        paymentStateContext.getInternalCallContext().getAccountRecordId(),
+                                                                        paymentStateContext.getInternalCallContext().getTenantRecordId(),
+                                                                        paymentStateContext.getInternalCallContext().getUserToken());
+            try {
+                daoHelper.getEventBus().post(event);
+            } catch (EventBusException e) {
+                logger.error("Failed to post Payment event event for account {} ", paymentStateContext.getAccount().getId(), e);
+            }
         }
     }
 
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentStateContext.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentStateContext.java
index 7755985..a6b0cc2 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentStateContext.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/PaymentStateContext.java
@@ -58,22 +58,24 @@ public class PaymentStateContext {
     protected final Iterable<PluginProperty> properties;
     protected final InternalCallContext internalCallContext;
     protected final CallContext callContext;
+    protected final boolean isApiPayment;
 
     // Use to create new transactions only
-    public PaymentStateContext(@Nullable final UUID paymentId, @Nullable final String paymentTransactionExternalKey, final TransactionType transactionType,
+    public PaymentStateContext(final boolean isApiPayment, @Nullable final UUID paymentId, @Nullable final String paymentTransactionExternalKey, final TransactionType transactionType,
                                final Account account, @Nullable final UUID paymentMethodId, final BigDecimal amount, final Currency currency,
                                final boolean shouldLockAccountAndDispatch, final Iterable<PluginProperty> properties,
                                final InternalCallContext internalCallContext, final CallContext callContext) {
-        this(paymentId, null, null, paymentTransactionExternalKey, transactionType, account, paymentMethodId,
+        this(isApiPayment, paymentId, null, null, paymentTransactionExternalKey, transactionType, account, paymentMethodId,
              amount, currency, shouldLockAccountAndDispatch, properties, internalCallContext, callContext);
     }
 
     // Used to create new payment and transactions
-    public PaymentStateContext(@Nullable final UUID paymentId, @Nullable final UUID attemptId, @Nullable final String paymentExternalKey,
+    public PaymentStateContext(final boolean isApiPayment, @Nullable final UUID paymentId, @Nullable final UUID attemptId, @Nullable final String paymentExternalKey,
                                @Nullable final String paymentTransactionExternalKey, final TransactionType transactionType,
                                final Account account, @Nullable final UUID paymentMethodId, final BigDecimal amount, final Currency currency,
                                final boolean shouldLockAccountAndDispatch, final Iterable<PluginProperty> properties,
                                final InternalCallContext internalCallContext, final CallContext callContext) {
+        this.isApiPayment = isApiPayment;
         this.paymentId = paymentId;
         this.attemptId= attemptId;
         this.paymentExternalKey = paymentExternalKey;
@@ -90,6 +92,10 @@ public class PaymentStateContext {
         this.onLeavingStateExistingTransactions = ImmutableList.of();
     }
 
+    public boolean isApiPayment() {
+        return isApiPayment;
+    }
+
     public void setPaymentMethodId(final UUID paymentMethodId) {
         this.paymentMethodId = paymentMethodId;
     }
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/PluginControlledPaymentAutomatonRunner.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/PluginControlledPaymentAutomatonRunner.java
index 5e2dbab..d980903 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/PluginControlledPaymentAutomatonRunner.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/PluginControlledPaymentAutomatonRunner.java
@@ -48,6 +48,7 @@ import org.killbill.billing.payment.retry.BaseRetryService.RetryServiceScheduler
 import org.killbill.billing.retry.plugin.api.PaymentControlPluginApi;
 import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.billing.util.config.PaymentConfig;
+import org.killbill.bus.api.PersistentBus;
 import org.killbill.clock.Clock;
 import org.killbill.commons.locker.GlobalLocker;
 
@@ -69,8 +70,8 @@ public class PluginControlledPaymentAutomatonRunner extends PaymentAutomatonRunn
     @Inject
     public PluginControlledPaymentAutomatonRunner(@Named(PaymentModule.STATE_MACHINE_PAYMENT) final StateMachineConfig stateMachineConfig, final PaymentDao paymentDao, final GlobalLocker locker, final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry,
                                                   final OSGIServiceRegistration<PaymentControlPluginApi> retryPluginRegistry, final Clock clock, final PaymentProcessor paymentProcessor, @Named(RETRYABLE_NAMED) final RetryServiceScheduler retryServiceScheduler,
-                                                  final PaymentConfig paymentConfig, @com.google.inject.name.Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor, PaymentStateMachineHelper paymentSMHelper, RetryStateMachineHelper retrySMHelper) {
-        super(stateMachineConfig, paymentConfig, paymentDao, locker, pluginRegistry, clock, executor, paymentSMHelper);
+                                                  final PaymentConfig paymentConfig, @com.google.inject.name.Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor, PaymentStateMachineHelper paymentSMHelper, RetryStateMachineHelper retrySMHelper, final PersistentBus eventBus) {
+        super(stateMachineConfig, paymentConfig, paymentDao, locker, pluginRegistry, clock, executor, eventBus, paymentSMHelper);
         this.paymentProcessor = paymentProcessor;
         this.paymentControlPluginRegistry = retryPluginRegistry;
         this.retryServiceScheduler = retryServiceScheduler;
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryablePaymentStateContext.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryablePaymentStateContext.java
index d4e8b7c..41b769a 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryablePaymentStateContext.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/RetryablePaymentStateContext.java
@@ -37,7 +37,6 @@ import com.google.common.collect.Iterables;
 
 public class RetryablePaymentStateContext extends PaymentStateContext {
 
-    private boolean isApiPayment;
     private DateTime retryDate;
     private String pluginName;
     private Payment result;
@@ -46,9 +45,8 @@ public class RetryablePaymentStateContext extends PaymentStateContext {
                                         @Nullable final String paymentTransactionExternalKey, final TransactionType transactionType,
                                         final Account account, @Nullable final UUID paymentMethodId, final BigDecimal amount, final Currency currency,
                                         final Iterable<PluginProperty> properties, final InternalCallContext internalCallContext, final CallContext callContext) {
-        super(paymentId, null, paymentExternalKey, paymentTransactionExternalKey, transactionType, account, paymentMethodId, amount, currency, true, properties, internalCallContext, callContext);
+        super(isApiPayment, paymentId, null, paymentExternalKey, paymentTransactionExternalKey, transactionType, account, paymentMethodId, amount, currency, true, properties, internalCallContext, callContext);
         this.pluginName = pluginName;
-        this.isApiPayment = isApiPayment;
     }
 
     public DateTime getRetryDate() {
@@ -75,10 +73,6 @@ public class RetryablePaymentStateContext extends PaymentStateContext {
         this.result = result;
     }
 
-    public boolean isApiPayment() {
-        return isApiPayment;
-    }
-
     public void setAmount(final BigDecimal adjustedAmount) {
         this.amount = adjustedAmount;
     }
diff --git a/payment/src/main/java/org/killbill/billing/payment/dao/DefaultPaymentDao.java b/payment/src/main/java/org/killbill/billing/payment/dao/DefaultPaymentDao.java
index 0a6be18..afb88fa 100644
--- a/payment/src/main/java/org/killbill/billing/payment/dao/DefaultPaymentDao.java
+++ b/payment/src/main/java/org/killbill/billing/payment/dao/DefaultPaymentDao.java
@@ -32,6 +32,10 @@ import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.entity.EntityPersistenceException;
+import org.killbill.billing.events.BusInternalEvent;
+import org.killbill.billing.payment.api.DefaultPaymentErrorEvent;
+import org.killbill.billing.payment.api.DefaultPaymentInfoEvent;
+import org.killbill.billing.payment.api.DefaultPaymentPluginErrorEvent;
 import org.killbill.billing.payment.api.Payment;
 import org.killbill.billing.payment.api.PaymentMethod;
 import org.killbill.billing.payment.api.TransactionStatus;
@@ -45,8 +49,12 @@ import org.killbill.billing.util.entity.dao.EntitySqlDao;
 import org.killbill.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
 import org.killbill.billing.util.entity.dao.EntitySqlDaoTransactionalJdbiWrapper;
 import org.killbill.billing.util.entity.dao.EntitySqlDaoWrapperFactory;
+import org.killbill.bus.api.PersistentBus;
+import org.killbill.bus.api.PersistentBus.EventBusException;
 import org.killbill.clock.Clock;
 import org.skife.jdbi.v2.IDBI;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
@@ -55,13 +63,19 @@ import com.google.common.collect.Collections2;
 
 public class DefaultPaymentDao implements PaymentDao {
 
+    private final static Logger log = LoggerFactory.getLogger(DefaultPaymentDao.class);
+
     private final EntitySqlDaoTransactionalJdbiWrapper transactionalSqlDao;
     private final DefaultPaginationSqlDaoHelper paginationHelper;
+    private final PersistentBus eventBus;
+    private final Clock clock;
 
     @Inject
-    public DefaultPaymentDao(final IDBI dbi, final Clock clock, final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao) {
+    public DefaultPaymentDao(final IDBI dbi, final Clock clock, final CacheControllerDispatcher cacheControllerDispatcher, final NonEntityDao nonEntityDao, final PersistentBus eventBus) {
         this.transactionalSqlDao = new EntitySqlDaoTransactionalJdbiWrapper(dbi, clock, cacheControllerDispatcher, nonEntityDao);
         this.paginationHelper = new DefaultPaginationSqlDaoHelper(transactionalSqlDao);
+        this.eventBus = eventBus;
+        this.clock = clock;
     }
 
     @Override
@@ -139,7 +153,7 @@ public class DefaultPaymentDao implements PaymentDao {
 
     @Override
     public int failOldPendingTransactions(final TransactionStatus newTransactionStatus, final DateTime createdBeforeDate, final InternalCallContext context) {
-         return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Integer>() {
+        return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Integer>() {
             @Override
             public Integer inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
                 final TransactionSqlDao transactional = entitySqlDaoWrapperFactory.become(TransactionSqlDao.class);
@@ -158,7 +172,6 @@ public class DefaultPaymentDao implements PaymentDao {
         });
     }
 
-
     @Override
     public List<PaymentTransactionModelDao> getPaymentTransactionsByExternalKey(final String transactionExternalKey, final InternalTenantContext context) {
         return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<PaymentTransactionModelDao>>() {
@@ -232,31 +245,33 @@ public class DefaultPaymentDao implements PaymentDao {
     }
 
     @Override
-    public void updatePaymentAndTransactionOnCompletion(final UUID paymentId, final String currentPaymentStateName,
-                                                              @Nullable final String lastPaymentSuccessStateName,
-                                                              final UUID transactionId, final TransactionStatus paymentStatus,
-                                                              final BigDecimal processedAmount, final Currency processedCurrency,
-                                                              final String gatewayErrorCode, final String gatewayErrorMsg,
-                                                              final InternalCallContext context) {
+    public void updatePaymentAndTransactionOnCompletion(final UUID accountId, final UUID paymentId, final TransactionType transactionType,
+                                                        final String currentPaymentStateName, @Nullable final String lastPaymentSuccessStateName,
+                                                        final UUID transactionId, final TransactionStatus transactionStatus,
+                                                        final BigDecimal processedAmount, final Currency processedCurrency,
+                                                        final String gatewayErrorCode, final String gatewayErrorMsg,
+                                                        final InternalCallContext context) {
         transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<Void>() {
 
             @Override
             public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
                 entitySqlDaoWrapperFactory.become(TransactionSqlDao.class).updateTransactionStatus(transactionId.toString(),
-                                                                                                         processedAmount, processedCurrency == null ? null : processedCurrency.toString(),
-                                                                                                         paymentStatus == null ? null : paymentStatus.toString(),
-                                                                                                         gatewayErrorCode, gatewayErrorMsg, context);
+                                                                                                   processedAmount, processedCurrency == null ? null : processedCurrency.toString(),
+                                                                                                   transactionStatus == null ? null : transactionStatus.toString(),
+                                                                                                   gatewayErrorCode, gatewayErrorMsg, context);
                 if (lastPaymentSuccessStateName != null) {
                     entitySqlDaoWrapperFactory.become(PaymentSqlDao.class).updateLastSuccessPaymentStateName(paymentId.toString(), currentPaymentStateName, lastPaymentSuccessStateName, context);
                 } else {
                     entitySqlDaoWrapperFactory.become(PaymentSqlDao.class).updatePaymentStateName(paymentId.toString(), currentPaymentStateName, context);
                 }
+                postPaymentEventFromTransaction(accountId, transactionStatus, transactionType, paymentId, processedAmount, processedCurrency, clock.getUTCNow(), gatewayErrorCode, entitySqlDaoWrapperFactory, context);
                 return null;
             }
         });
 
     }
 
+
     @Override
     public PaymentModelDao getPayment(final UUID paymentId, final InternalTenantContext context) {
         return transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<PaymentModelDao>() {
@@ -476,4 +491,59 @@ public class DefaultPaymentDao implements PaymentDao {
             }
         });
     }
+
+    private void postPaymentEventFromTransaction(final UUID accountId,
+                                                 final TransactionStatus transactionStatus,
+                                                 final TransactionType transactionType,
+                                                 final UUID paymentId,
+                                                 final BigDecimal processedAmount,
+                                                 final Currency processedCurrency,
+                                                 final DateTime effectiveDate,
+                                                 final String gatewayErrorCode,
+                                                 final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory,
+                                                 final InternalCallContext context) {
+
+        final BusInternalEvent event;
+        switch (transactionStatus) {
+            case SUCCESS:
+            case PENDING:
+                event = new DefaultPaymentInfoEvent(accountId,
+                                                    paymentId,
+                                                    processedAmount,
+                                                    processedCurrency,
+                                                    transactionStatus,
+                                                    transactionType,
+                                                    effectiveDate,
+                                                    context.getAccountRecordId(),
+                                                    context.getTenantRecordId(),
+                                                    context.getUserToken());
+                break;
+
+            case PAYMENT_FAILURE:
+                event = new DefaultPaymentErrorEvent(accountId,
+                                                     paymentId,
+                                                     transactionType,
+                                                     gatewayErrorCode,
+                                                     context.getAccountRecordId(),
+                                                     context.getTenantRecordId(),
+                                                     context.getUserToken());
+                break;
+
+            case PLUGIN_FAILURE:
+            default:
+                event = new DefaultPaymentPluginErrorEvent(accountId,
+                                                           paymentId,
+                                                           transactionType,
+                                                           gatewayErrorCode,
+                                                           context.getAccountRecordId(),
+                                                           context.getTenantRecordId(),
+                                                           context.getUserToken());
+                break;
+        }
+        try {
+            eventBus.postFromTransaction(event, entitySqlDaoWrapperFactory.getSqlDao());
+        } catch (EventBusException e) {
+            log.error("Failed to post Payment event event for account {} ", accountId, e);
+        }
+    }
 }
diff --git a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentDao.java b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentDao.java
index 640601e..efdea6c 100644
--- a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentDao.java
+++ b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentDao.java
@@ -25,6 +25,7 @@ import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.payment.api.TransactionStatus;
+import org.killbill.billing.payment.api.TransactionType;
 import org.killbill.billing.util.entity.Pagination;
 
 public interface PaymentDao {
@@ -51,12 +52,10 @@ public interface PaymentDao {
 
     public PaymentTransactionModelDao updatePaymentWithNewTransaction(UUID paymentId, PaymentTransactionModelDao paymentTransaction, InternalCallContext context);
 
-    public void updatePaymentAndTransactionOnCompletion(UUID paymentId, String currentPaymentStateName,
-                                                              String lastPaymentSuccessStateName,
-                                                              UUID transactionId, TransactionStatus paymentStatus,
-                                                              BigDecimal processedAmount, Currency processedCurrency,
-                                                              String gatewayErrorCode, String gatewayErrorMsg,
-                                                              InternalCallContext context);
+    public void updatePaymentAndTransactionOnCompletion(UUID accountId, UUID paymentId, final TransactionType transactionType, String currentPaymentStateName, String lastPaymentSuccessStateName, UUID transactionId,
+                                                              TransactionStatus paymentStatus, BigDecimal processedAmount, Currency processedCurrency,
+                                                              String gatewayErrorCode, String gatewayErrorMsg, InternalCallContext context);
+
 
     public PaymentModelDao getPayment(UUID paymentId, InternalTenantContext context);
 
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 3abbc18..809199f 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
@@ -20,6 +20,7 @@ import java.math.BigDecimal;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
+import org.killbill.billing.catalog.api.Currency;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -33,7 +34,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(), TransactionType.PURCHASE, "no message", 1L, 2L, UUID.randomUUID());
+        final PaymentErrorInternalEvent e = new DefaultPaymentErrorEvent(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());
@@ -43,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,
+        final PaymentInfoInternalEvent e = new DefaultPaymentInfoEvent(UUID.randomUUID(), UUID.randomUUID(), new BigDecimal(12.9), Currency.EUR, TransactionStatus.SUCCESS,
                                                                        TransactionType.PURCHASE, new DateTime(), 1L, 2L, UUID.randomUUID());
         final String json = mapper.writeValueAsString(e);
 
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryablePaymentAutomatonRunner.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryablePaymentAutomatonRunner.java
index 65283c8..992e210 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryablePaymentAutomatonRunner.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/MockRetryablePaymentAutomatonRunner.java
@@ -44,6 +44,7 @@ import org.killbill.billing.retry.plugin.api.PaymentControlPluginApi;
 import org.killbill.billing.tag.TagInternalApi;
 import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.billing.util.config.PaymentConfig;
+import org.killbill.bus.api.PersistentBus;
 import org.killbill.clock.Clock;
 import org.killbill.commons.locker.GlobalLocker;
 
@@ -58,8 +59,8 @@ public class MockRetryablePaymentAutomatonRunner extends PluginControlledPayment
     @Inject
     public MockRetryablePaymentAutomatonRunner(@Named(PaymentModule.STATE_MACHINE_PAYMENT) final StateMachineConfig stateMachineConfig, @Named(PaymentModule.STATE_MACHINE_RETRY) final StateMachineConfig retryStateMachine, final PaymentDao paymentDao, final GlobalLocker locker, final OSGIServiceRegistration<PaymentPluginApi> pluginRegistry, final OSGIServiceRegistration<PaymentControlPluginApi> retryPluginRegistry, final Clock clock, final TagInternalApi tagApi, final PaymentProcessor paymentProcessor,
                                                @Named(RETRYABLE_NAMED) final RetryServiceScheduler retryServiceScheduler, final PaymentConfig paymentConfig, @com.google.inject.name.Named(PLUGIN_EXECUTOR_NAMED) final ExecutorService executor,
-                                               final PaymentStateMachineHelper paymentSMHelper, final RetryStateMachineHelper retrySMHelper) {
-        super(stateMachineConfig, paymentDao, locker, pluginRegistry, retryPluginRegistry, clock, paymentProcessor, retryServiceScheduler, paymentConfig, executor, paymentSMHelper, retrySMHelper);
+                                               final PaymentStateMachineHelper paymentSMHelper, final RetryStateMachineHelper retrySMHelper, final PersistentBus eventBus) {
+        super(stateMachineConfig, paymentDao, locker, pluginRegistry, retryPluginRegistry, clock, paymentProcessor, retryServiceScheduler, paymentConfig, executor, paymentSMHelper, retrySMHelper, eventBus);
     }
 
     @Override
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentAutomatonDAOHelper.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentAutomatonDAOHelper.java
index e019377..140780d 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentAutomatonDAOHelper.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentAutomatonDAOHelper.java
@@ -31,8 +31,8 @@ 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.dao.PaymentModelDao;
-import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
 import org.killbill.billing.payment.plugin.api.PaymentPluginStatus;
+import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
 import org.mockito.Mockito;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -119,26 +119,26 @@ public class TestPaymentAutomatonDAOHelper extends PaymentTestSuiteWithEmbeddedD
     }
 
     private PaymentAutomatonDAOHelper createDAOHelper(@Nullable final UUID paymentId, final String paymentExternalKey,
-                                                            final String paymentTransactionExternalKey,
-                                                            final BigDecimal amount, final Currency currency) throws Exception {
+                                                      final String paymentTransactionExternalKey,
+                                                      final BigDecimal amount, final Currency currency) throws Exception {
         final Account account = Mockito.mock(Account.class);
         Mockito.when(account.getId()).thenReturn(UUID.randomUUID());
         // No default payment method
 
-        paymentStateContext = new PaymentStateContext(paymentId,
-                                                                  null,
-                                                                  paymentExternalKey,
-                                                                  paymentTransactionExternalKey,
-                                                                  TransactionType.CAPTURE,
-                                                                  account,
-                                                                  UUID.randomUUID(),
-                                                                  amount,
-                                                                  currency,
-                                                                  false,
-                                                                  ImmutableList.<PluginProperty>of(),
-                                                                  internalCallContext,
-                                                                  callContext);
-
-        return new PaymentAutomatonDAOHelper(paymentStateContext, clock.getUTCNow(), paymentDao, registry, internalCallContext, paymentSMHelper);
+        paymentStateContext = new PaymentStateContext(true, paymentId,
+                                                      null,
+                                                      paymentExternalKey,
+                                                      paymentTransactionExternalKey,
+                                                      TransactionType.CAPTURE,
+                                                      account,
+                                                      UUID.randomUUID(),
+                                                      amount,
+                                                      currency,
+                                                      false,
+                                                      ImmutableList.<PluginProperty>of(),
+                                                      internalCallContext,
+                                                      callContext);
+
+        return new PaymentAutomatonDAOHelper(paymentStateContext, clock.getUTCNow(), paymentDao, registry, internalCallContext, eventBus, paymentSMHelper);
     }
 }
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentEnteringStateCallback.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentEnteringStateCallback.java
index e0869d5..7cc35b5 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentEnteringStateCallback.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentEnteringStateCallback.java
@@ -21,7 +21,6 @@ import java.math.BigDecimal;
 import java.util.UUID;
 
 import org.killbill.automaton.Operation.OperationCallback;
-import org.killbill.automaton.OperationException;
 import org.killbill.automaton.OperationResult;
 import org.killbill.automaton.State;
 import org.killbill.automaton.State.LeavingStateCallback;
@@ -57,18 +56,19 @@ public class TestPaymentEnteringStateCallback extends PaymentTestSuiteWithEmbedd
     public void setUp() throws Exception {
         final Account account = Mockito.mock(Account.class);
         Mockito.when(account.getId()).thenReturn(UUID.randomUUID());
-        paymentStateContext = new PaymentStateContext(null,
-                                                                  UUID.randomUUID().toString(),
-                                                                  TransactionType.CAPTURE,
-                                                                  account,
-                                                                  UUID.randomUUID(),
-                                                                  new BigDecimal("192.3920111"),
-                                                                  Currency.BRL,
-                                                                  false,
-                                                                  ImmutableList.<PluginProperty>of(),
-                                                                  internalCallContext,
-                                                                  callContext);
-        daoHelper = new PaymentAutomatonDAOHelper(paymentStateContext, clock.getUTCNow(), paymentDao, registry, internalCallContext, paymentSMHelper);
+        paymentStateContext = new PaymentStateContext(true,
+                                                      null,
+                                                      UUID.randomUUID().toString(),
+                                                      TransactionType.CAPTURE,
+                                                      account,
+                                                      UUID.randomUUID(),
+                                                      new BigDecimal("192.3920111"),
+                                                      Currency.BRL,
+                                                      false,
+                                                      ImmutableList.<PluginProperty>of(),
+                                                      internalCallContext,
+                                                      callContext);
+        daoHelper = new PaymentAutomatonDAOHelper(paymentStateContext, clock.getUTCNow(), paymentDao, registry, internalCallContext, eventBus, paymentSMHelper);
         callback = new PaymentEnteringStateTestCallback(daoHelper, paymentStateContext);
 
         Mockito.when(state.getName()).thenReturn("NEW_STATE");
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentLeavingStateCallback.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentLeavingStateCallback.java
index a1cca0d..17e50c9 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentLeavingStateCallback.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentLeavingStateCallback.java
@@ -95,19 +95,20 @@ public class TestPaymentLeavingStateCallback extends PaymentTestSuiteWithEmbedde
     private void setUp(@Nullable final UUID paymentId) throws Exception {
         final Account account = Mockito.mock(Account.class);
         Mockito.when(account.getId()).thenReturn(UUID.randomUUID());
-        paymentStateContext = new PaymentStateContext(paymentId,
-                                                                  null,
-                                                                  UUID.randomUUID().toString(),
-                                                                  UUID.randomUUID().toString(),
-                                                                  TransactionType.CAPTURE,
-                                                                  account,
-                                                                  UUID.randomUUID(),
-                                                                  new BigDecimal("192.3920111"),
-                                                                  Currency.BRL,
-                                                                  false,
-                                                                  ImmutableList.<PluginProperty>of(),
-                                                                  internalCallContext,
-                                                                  callContext);
+        paymentStateContext = new PaymentStateContext(true,
+                                                      paymentId,
+                                                      null,
+                                                      UUID.randomUUID().toString(),
+                                                      UUID.randomUUID().toString(),
+                                                      TransactionType.CAPTURE,
+                                                      account,
+                                                      UUID.randomUUID(),
+                                                      new BigDecimal("192.3920111"),
+                                                      Currency.BRL,
+                                                      false,
+                                                      ImmutableList.<PluginProperty>of(),
+                                                      internalCallContext,
+                                                      callContext);
 
         if (paymentId != null) {
             // Create the first payment manually
@@ -134,7 +135,7 @@ public class TestPaymentLeavingStateCallback extends PaymentTestSuiteWithEmbedde
             paymentDao.insertPaymentWithFirstTransaction(newPaymentModelDao, newPaymentTransactionModelDao, internalCallContext);
         }
 
-        final PaymentAutomatonDAOHelper daoHelper = new PaymentAutomatonDAOHelper(paymentStateContext, clock.getUTCNow(), paymentDao, registry, internalCallContext, paymentSMHelper);
+        final PaymentAutomatonDAOHelper daoHelper = new PaymentAutomatonDAOHelper(paymentStateContext, clock.getUTCNow(), paymentDao, registry, internalCallContext, eventBus, paymentSMHelper);
         callback = new PaymentLeavingStateTestCallback(daoHelper);
 
         Mockito.when(state.getName()).thenReturn("NEW_STATE");
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentOperation.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentOperation.java
index 8139b65..a21aefd 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentOperation.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentOperation.java
@@ -34,9 +34,9 @@ import org.killbill.billing.payment.api.TransactionType;
 import org.killbill.billing.payment.dao.PaymentDao;
 import org.killbill.billing.payment.dao.PaymentMethodModelDao;
 import org.killbill.billing.payment.dispatcher.PluginDispatcher;
-import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
 import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
 import org.killbill.billing.payment.plugin.api.PaymentPluginStatus;
+import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
 import org.killbill.billing.payment.provider.MockPaymentProviderPlugin;
 import org.killbill.commons.locker.GlobalLocker;
 import org.killbill.commons.locker.memory.MemoryGlobalLocker;
@@ -103,26 +103,27 @@ public class TestPaymentOperation extends PaymentTestSuiteNoDB {
     private void setUp(final PaymentPluginStatus paymentPluginStatus) throws Exception {
         final GlobalLocker locker = new MemoryGlobalLocker();
         final PluginDispatcher<OperationResult> paymentPluginDispatcher = new PluginDispatcher<OperationResult>(1, Executors.newCachedThreadPool());
-        paymentStateContext = new PaymentStateContext(UUID.randomUUID(),
-                                                                  null,
-                                                                  UUID.randomUUID().toString(),
-                                                                  UUID.randomUUID().toString(),
-                                                                  TransactionType.CAPTURE,
-                                                                  Mockito.mock(Account.class),
-                                                                  UUID.randomUUID(),
-                                                                  new BigDecimal("192.3920111"),
-                                                                  Currency.BRL,
-                                                                  false,
-                                                                  ImmutableList.<PluginProperty>of(),
-                                                                  internalCallContext,
-                                                                  callContext);
+        paymentStateContext = new PaymentStateContext(true,
+                                                      UUID.randomUUID(),
+                                                      null,
+                                                      UUID.randomUUID().toString(),
+                                                      UUID.randomUUID().toString(),
+                                                      TransactionType.CAPTURE,
+                                                      Mockito.mock(Account.class),
+                                                      UUID.randomUUID(),
+                                                      new BigDecimal("192.3920111"),
+                                                      Currency.BRL,
+                                                      false,
+                                                      ImmutableList.<PluginProperty>of(),
+                                                      internalCallContext,
+                                                      callContext);
 
         final PaymentMethodModelDao paymentMethodModelDao = new PaymentMethodModelDao(paymentStateContext.getPaymentMethodId(), UUID.randomUUID().toString(), clock.getUTCNow(), clock.getUTCNow(),
                                                                                       paymentStateContext.getAccount().getId(), MockPaymentProviderPlugin.PLUGIN_NAME, true);
         final PaymentDao paymentDao = Mockito.mock(PaymentDao.class);
         Mockito.when(paymentDao.getPaymentMethodIncludedDeleted(paymentStateContext.getPaymentMethodId(), internalCallContext)).thenReturn(paymentMethodModelDao);
 
-        final PaymentAutomatonDAOHelper daoHelper = new PaymentAutomatonDAOHelper(paymentStateContext, clock.getUTCNow(), paymentDao, registry, internalCallContext, paymentSMHelper);
+        final PaymentAutomatonDAOHelper daoHelper = new PaymentAutomatonDAOHelper(paymentStateContext, clock.getUTCNow(), paymentDao, registry, internalCallContext, eventBus, paymentSMHelper);
         paymentOperation = new PaymentOperationTest(paymentPluginStatus, daoHelper, locker, paymentPluginDispatcher, paymentStateContext);
     }
 
@@ -131,8 +132,8 @@ public class TestPaymentOperation extends PaymentTestSuiteNoDB {
         private final PaymentTransactionInfoPlugin paymentInfoPlugin;
 
         public PaymentOperationTest(@Nullable final PaymentPluginStatus paymentPluginStatus,
-                                          final PaymentAutomatonDAOHelper daoHelper, final GlobalLocker locker,
-                                          final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateContext paymentStateContext) throws PaymentApiException {
+                                    final PaymentAutomatonDAOHelper daoHelper, final GlobalLocker locker,
+                                    final PluginDispatcher<OperationResult> paymentPluginDispatcher, final PaymentStateContext paymentStateContext) throws PaymentApiException {
             super(daoHelper, locker, paymentPluginDispatcher, paymentStateContext);
             this.paymentInfoPlugin = (paymentPluginStatus == null ? null : getPaymentInfoPlugin(paymentPluginStatus));
         }
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPluginOperation.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPluginOperation.java
index 8af57a6..4362013 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPluginOperation.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPluginOperation.java
@@ -69,7 +69,7 @@ public class TestPluginOperation extends PaymentTestSuiteNoDB {
     // STEPH the test now fails because the logic has been changed; we don't check in the dispatchWithAccountLockAndTimeout
     // method to see whether account should be locked or not. Instead we either (dispatch AND lock) OR
     // ! (dispatch AND lock)
-    @Test(groups = "fast", enabled=false)
+    @Test(groups = "fast", enabled = false)
     public void testWithoutAccountLock() throws Exception {
         testLocking(false);
     }
@@ -201,19 +201,19 @@ public class TestPluginOperation extends PaymentTestSuiteNoDB {
     private PaymentOperation getPluginOperation(final boolean shouldLockAccount, final int timeoutSeconds) throws PaymentApiException {
         final PluginDispatcher<OperationResult> paymentPluginDispatcher = new PluginDispatcher<OperationResult>(timeoutSeconds, Executors.newCachedThreadPool());
 
-        final PaymentStateContext paymentStateContext = new PaymentStateContext(UUID.randomUUID(),
-                                                                                                  null,
-                                                                                                  UUID.randomUUID().toString(),
-                                                                                                  UUID.randomUUID().toString(),
-                                                                                                  TransactionType.CAPTURE,
-                                                                                                  account,
-                                                                                                  UUID.randomUUID(),
-                                                                                                  new BigDecimal("192.3920111"),
-                                                                                                  Currency.BRL,
-                                                                                                  shouldLockAccount,
-                                                                                                  ImmutableList.<PluginProperty>of(),
-                                                                                                  internalCallContext,
-                                                                                                  callContext);
+        final PaymentStateContext paymentStateContext = new PaymentStateContext(true, UUID.randomUUID(),
+                                                                                null,
+                                                                                UUID.randomUUID().toString(),
+                                                                                UUID.randomUUID().toString(),
+                                                                                TransactionType.CAPTURE,
+                                                                                account,
+                                                                                UUID.randomUUID(),
+                                                                                new BigDecimal("192.3920111"),
+                                                                                Currency.BRL,
+                                                                                shouldLockAccount,
+                                                                                ImmutableList.<PluginProperty>of(),
+                                                                                internalCallContext,
+                                                                                callContext);
 
         final PaymentAutomatonDAOHelper daoHelper = Mockito.mock(PaymentAutomatonDAOHelper.class);
         Mockito.when(daoHelper.getPaymentProviderPlugin()).thenReturn(null);
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryablePayment.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryablePayment.java
index 6eb3f89..43c2e13 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryablePayment.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestRetryablePayment.java
@@ -163,7 +163,8 @@ public class TestRetryablePayment extends PaymentTestSuiteNoDB {
                 paymentConfig,
                 executor,
                 paymentSMHelper,
-                retrySMHelper);
+                retrySMHelper,
+                eventBus);
 
         paymentStateContext =
                 new RetryablePaymentStateContext(MockPaymentControlProviderPlugin.PLUGIN_NAME,
@@ -195,7 +196,6 @@ public class TestRetryablePayment extends PaymentTestSuiteNoDB {
                                                          tagApi,
                                                          paymentDao,
                                                          nonEntityDao,
-                                                         eventBus,
                                                          locker,
                                                          executor,
                                                          runner,
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 1af2d44..3b128ec 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
@@ -88,7 +88,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
                                                                                               SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(authorizationPost3DS, paymentExternalKey, TEN, ZERO, ZERO, 2);
         verifyPaymentTransaction(authorizationPost3DS.getTransactions().get(1), authorizationPost3DSKey, TransactionType.AUTHORIZE, TEN, paymentId);
-        paymentBusListener.verify(2, account.getId(), paymentId, TEN);
+        paymentBusListener.verify(2, account.getId(), paymentId, TEN.add(TEN) /* STEPH the processedAmount is 20; probably something wrong in the MockPlugin */);
 
         // CAPTURE
         final String capture1Key = UUID.randomUUID().toString();
@@ -104,7 +104,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
                                                                                    SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(partialCapture2, paymentExternalKey, TEN, TEN, ZERO, 4);
         verifyPaymentTransaction(partialCapture2.getTransactions().get(3), capture2Key, TransactionType.CAPTURE, FIVE, paymentId);
-        paymentBusListener.verify(4, account.getId(), paymentId, FIVE);
+        paymentBusListener.verify(4, account.getId(), paymentId, FIVE.add(FIVE) /* STEPH the processedAmount is 20; probably something wrong in the MockPlugin */);
 
         // REFUND
         final String refund1Key = UUID.randomUUID().toString();
@@ -120,7 +120,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
                                                                                  SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(partialRefund2, paymentExternalKey, TEN, TEN, TEN, 6);
         verifyPaymentTransaction(partialRefund2.getTransactions().get(5), refund2Key, TransactionType.REFUND, FIVE, paymentId);
-        paymentBusListener.verify(6, account.getId(), paymentId, FIVE);
+        paymentBusListener.verify(6, account.getId(), paymentId, FIVE.add(FIVE) /* STEPH the processedAmount is 20; probably something wrong in the MockPlugin */);
     }
 
     @Test(groups = "slow")
@@ -238,9 +238,8 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         private void verify(final PaymentInfoInternalEvent event, final UUID accountId, final UUID paymentId, @Nullable final BigDecimal amount) {
             Assert.assertEquals(event.getPaymentId(), paymentId);
             Assert.assertEquals(event.getAccountId(), accountId);
-            Assert.assertNull(event.getInvoiceId());
             if (amount == null) {
-                Assert.assertNull(event.getAmount());
+                Assert.assertEquals(event.getAmount().compareTo(BigDecimal.ZERO), 0);
             } else {
                 Assert.assertEquals(event.getAmount().compareTo(amount), 0);
             }
diff --git a/payment/src/test/java/org/killbill/billing/payment/dao/MockPaymentDao.java b/payment/src/test/java/org/killbill/billing/payment/dao/MockPaymentDao.java
index 932beeb..f36e9bb 100644
--- a/payment/src/test/java/org/killbill/billing/payment/dao/MockPaymentDao.java
+++ b/payment/src/test/java/org/killbill/billing/payment/dao/MockPaymentDao.java
@@ -30,6 +30,7 @@ import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.payment.api.TransactionStatus;
+import org.killbill.billing.payment.api.TransactionType;
 import org.killbill.billing.util.entity.Pagination;
 
 import com.google.common.base.Predicate;
@@ -168,7 +169,10 @@ public class MockPaymentDao implements PaymentDao {
     }
 
     @Override
-    public void updatePaymentAndTransactionOnCompletion(final UUID paymentId, final String currentPaymentStateName, final String lastSuccessPaymentStateName, final UUID transactionId, final TransactionStatus paymentStatus, final BigDecimal processedAmount, final Currency processedCurrency, final String gatewayErrorCode, final String gatewayErrorMsg, final InternalCallContext context) {
+    public void updatePaymentAndTransactionOnCompletion(final UUID accountId, final UUID paymentId, final TransactionType transactionType,
+                                                        final String currentPaymentStateName, final String lastSuccessPaymentStateName, final UUID transactionId,
+                                                        final TransactionStatus paymentStatus, final BigDecimal processedAmount, final Currency processedCurrency,
+                                                        final String gatewayErrorCode, final String gatewayErrorMsg, final InternalCallContext context) {
         synchronized (this) {
             final PaymentModelDao payment = payments.get(paymentId);
             if (payment != null) {
diff --git a/payment/src/test/java/org/killbill/billing/payment/dao/TestDefaultPaymentDao.java b/payment/src/test/java/org/killbill/billing/payment/dao/TestDefaultPaymentDao.java
index 67434d6..e92f546 100644
--- a/payment/src/test/java/org/killbill/billing/payment/dao/TestDefaultPaymentDao.java
+++ b/payment/src/test/java/org/killbill/billing/payment/dao/TestDefaultPaymentDao.java
@@ -61,16 +61,18 @@ public class TestDefaultPaymentDao extends PaymentTestSuiteWithEmbeddedDB {
         final Currency processedCurrency = Currency.USD;
         final String gatewayErrorCode = UUID.randomUUID().toString().substring(0, 5);
         final String gatewayErrorMsg = UUID.randomUUID().toString();
-        paymentDao.updatePaymentAndTransactionOnCompletion(specifiedSecondPaymentTransactionModelDao.getPaymentId(),
-                                                                 "SOME_ERRORED_STATE",
-                                                                 "SOME_ERRORED_STATE",
-                                                                 specifiedSecondPaymentTransactionModelDao.getId(),
-                                                                 TransactionStatus.PAYMENT_FAILURE,
-                                                                 processedAmount,
-                                                                 processedCurrency,
-                                                                 gatewayErrorCode,
-                                                                 gatewayErrorMsg,
-                                                                 accountCallContext);
+        paymentDao.updatePaymentAndTransactionOnCompletion(accountId,
+                                                           specifiedSecondPaymentTransactionModelDao.getPaymentId(),
+                                                           specifiedFirstPaymentTransactionModelDao.getTransactionType(),
+                                                           "SOME_ERRORED_STATE",
+                                                           "SOME_ERRORED_STATE",
+                                                           specifiedSecondPaymentTransactionModelDao.getId(),
+                                                           TransactionStatus.PAYMENT_FAILURE,
+                                                           processedAmount,
+                                                           processedCurrency,
+                                                           gatewayErrorCode,
+                                                           gatewayErrorMsg,
+                                                           accountCallContext);
 
         final PaymentTransactionModelDao updatedSecondPaymentTransactionModelDao = paymentDao.getPaymentTransaction(specifiedSecondPaymentTransactionModelDao.getId(), accountCallContext);
         Assert.assertEquals(updatedSecondPaymentTransactionModelDao.getTransactionStatus(), TransactionStatus.PAYMENT_FAILURE);
diff --git a/payment/src/test/java/org/killbill/billing/payment/dao/TestPaymentDao.java b/payment/src/test/java/org/killbill/billing/payment/dao/TestPaymentDao.java
index beff2d2..d8e3b15 100644
--- a/payment/src/test/java/org/killbill/billing/payment/dao/TestPaymentDao.java
+++ b/payment/src/test/java/org/killbill/billing/payment/dao/TestPaymentDao.java
@@ -164,7 +164,7 @@ public class TestPaymentDao extends PaymentTestSuiteWithEmbeddedDB {
         final List<PaymentTransactionModelDao> transactions = paymentDao.getTransactionsForPayment(savedPayment.getId(), internalCallContext);
         assertEquals(transactions.size(), 2);
 
-        paymentDao.updatePaymentAndTransactionOnCompletion(savedPayment.getId(), "AUTH_ABORTED", "AUTH_SUCCESS", transactionModelDao2.getId(), TransactionStatus.SUCCESS,
+        paymentDao.updatePaymentAndTransactionOnCompletion(accountId, savedPayment.getId(), savedTransactionModelDao2.getTransactionType(), "AUTH_ABORTED", "AUTH_SUCCESS", transactionModelDao2.getId(), TransactionStatus.SUCCESS,
                                                                  BigDecimal.ONE, Currency.USD, null, "nothing", internalCallContext);
 
         final PaymentModelDao savedPayment4 = paymentDao.getPayment(savedPayment.getId(), internalCallContext);
@@ -187,7 +187,7 @@ public class TestPaymentDao extends PaymentTestSuiteWithEmbeddedDB {
         assertNull(savedTransactionModelDao4.getGatewayErrorCode());
         assertEquals(savedTransactionModelDao4.getGatewayErrorMsg(), "nothing");
 
-        paymentDao.updatePaymentAndTransactionOnCompletion(savedPayment.getId(), "AUTH_ABORTED", null, transactionModelDao2.getId(), TransactionStatus.SUCCESS,
+        paymentDao.updatePaymentAndTransactionOnCompletion(accountId, savedPayment.getId(), savedTransactionModelDao2.getTransactionType(), "AUTH_ABORTED", null, transactionModelDao2.getId(), TransactionStatus.SUCCESS,
                                                                  BigDecimal.ONE, Currency.USD, null, "nothing", internalCallContext);
 
         final PaymentModelDao savedPayment4Again = paymentDao.getPayment(savedPayment.getId(), internalCallContext);
@@ -195,7 +195,7 @@ public class TestPaymentDao extends PaymentTestSuiteWithEmbeddedDB {
         assertEquals(savedPayment4Again.getStateName(), "AUTH_ABORTED");
         assertEquals(savedPayment4Again.getLastSuccessStateName(), "AUTH_SUCCESS");
 
-        paymentDao.updatePaymentAndTransactionOnCompletion(savedPayment.getId(), "AUTH_ABORTED", "AUTH_SUCCESS", transactionModelDao2.getId(), TransactionStatus.SUCCESS,
+        paymentDao.updatePaymentAndTransactionOnCompletion(accountId, savedPayment.getId(), savedTransactionModelDao2.getTransactionType(), "AUTH_ABORTED", "AUTH_SUCCESS", transactionModelDao2.getId(), TransactionStatus.SUCCESS,
                                                                  BigDecimal.ONE, Currency.USD, null, "nothing", internalCallContext);
 
         final PaymentModelDao savedPayment4Final = paymentDao.getPayment(savedPayment.getId(), internalCallContext);