killbill-memoizeit

payment: set keys as the id by default when going through control

3/16/2017 5:16:26 AM

Changes

Details

diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPaymentWithControl.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPaymentWithControl.java
index 05879f6..f5b74e6 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPaymentWithControl.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPaymentWithControl.java
@@ -30,18 +30,18 @@ import org.killbill.billing.account.api.Account;
 import org.killbill.billing.account.api.AccountData;
 import org.killbill.billing.api.TestApiListener.NextEvent;
 import org.killbill.billing.catalog.api.Currency;
-import org.killbill.billing.osgi.api.OSGIServiceDescriptor;
-import org.killbill.billing.osgi.api.OSGIServiceRegistration;
-import org.killbill.billing.payment.api.Payment;
-import org.killbill.billing.payment.api.PaymentOptions;
-import org.killbill.billing.payment.api.PluginProperty;
-import org.killbill.billing.payment.api.TransactionType;
 import org.killbill.billing.control.plugin.api.OnFailurePaymentControlResult;
 import org.killbill.billing.control.plugin.api.OnSuccessPaymentControlResult;
 import org.killbill.billing.control.plugin.api.PaymentControlApiException;
 import org.killbill.billing.control.plugin.api.PaymentControlContext;
 import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
 import org.killbill.billing.control.plugin.api.PriorPaymentControlResult;
+import org.killbill.billing.osgi.api.OSGIServiceDescriptor;
+import org.killbill.billing.osgi.api.OSGIServiceRegistration;
+import org.killbill.billing.payment.api.Payment;
+import org.killbill.billing.payment.api.PaymentOptions;
+import org.killbill.billing.payment.api.PluginProperty;
+import org.killbill.billing.payment.api.TransactionType;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
@@ -118,10 +118,23 @@ public class TestPaymentWithControl extends TestIntegrationBase {
                                                                                  properties, paymentOptions, callContext);
         assertListenerStatus();
 
+        Payment paymentWithAttempts = paymentApi.getPayment(payment.getId(), false, true, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertEquals(paymentWithAttempts.getPaymentAttempts().size(), 1);
+        Assert.assertEquals(paymentWithAttempts.getExternalKey(), paymentWithAttempts.getPaymentAttempts().get(0).getPaymentExternalKey());
+        Assert.assertEquals(paymentWithAttempts.getTransactions().get(0).getExternalKey(), paymentWithAttempts.getPaymentAttempts().get(0).getTransactionExternalKey());
+        // Verify fix for https://github.com/killbill/killbill/issues/349 when no external key is set
+        Assert.assertEquals(paymentWithAttempts.getId().toString(), paymentWithAttempts.getPaymentAttempts().get(0).getPaymentExternalKey());
+        Assert.assertEquals(paymentWithAttempts.getTransactions().get(0).getId().toString(), paymentWithAttempts.getPaymentAttempts().get(0).getTransactionExternalKey());
+
         busHandler.pushExpectedEvents(NextEvent.PAYMENT);
         paymentApi.createCaptureWithPaymentControl(account, payment.getId(), BigDecimal.ONE, account.getCurrency(), null, properties, paymentOptions, callContext);
         assertListenerStatus();
 
+        paymentWithAttempts = paymentApi.getPayment(payment.getId(), false, true, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertEquals(paymentWithAttempts.getPaymentAttempts().size(), 2);
+        Assert.assertEquals(paymentWithAttempts.getTransactions().get(1).getExternalKey(), paymentWithAttempts.getPaymentAttempts().get(1).getTransactionExternalKey());
+        Assert.assertEquals(paymentWithAttempts.getTransactions().get(1).getId().toString(), paymentWithAttempts.getPaymentAttempts().get(1).getTransactionExternalKey());
+
         Assert.assertEquals(testPaymentControlWithControl.getCalls().size(), 2);
         Assert.assertEquals(testPaymentControlWithControl.getCalls().get(TransactionType.AUTHORIZE.toString()), new Integer(1));
         Assert.assertEquals(testPaymentControlWithControl.getCalls().get(TransactionType.CAPTURE.toString()), new Integer(1));
@@ -132,14 +145,36 @@ public class TestPaymentWithControl extends TestIntegrationBase {
         final AccountData accountData = getAccountData(1);
         final Account account = createAccountWithNonOsgiPaymentMethod(accountData);
 
+        final String paymentExternalKey = "something-that-is-not-a-uuid";
+        final String paymentTransactionExternalKey = "something-that-is-not-a-uuid-2";
+
         busHandler.pushExpectedEvents(NextEvent.PAYMENT);
-        final Payment payment = paymentApi.createAuthorizationWithPaymentControl(account, account.getPaymentMethodId(), null, BigDecimal.ONE, account.getCurrency(), null, null,
+        final Payment payment = paymentApi.createAuthorizationWithPaymentControl(account, account.getPaymentMethodId(), null, BigDecimal.ONE, account.getCurrency(), paymentExternalKey, paymentTransactionExternalKey,
                                                                                  properties, paymentOptions, callContext);
         assertListenerStatus();
 
+        Payment paymentWithAttempts = paymentApi.getPayment(payment.getId(), false, true, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertEquals(paymentWithAttempts.getPaymentAttempts().size(), 1);
+        Assert.assertEquals(paymentWithAttempts.getExternalKey(), paymentExternalKey);
+        Assert.assertEquals(paymentWithAttempts.getTransactions().get(0).getExternalKey(), paymentTransactionExternalKey);
+        Assert.assertEquals(paymentWithAttempts.getExternalKey(), paymentWithAttempts.getPaymentAttempts().get(0).getPaymentExternalKey());
+        Assert.assertEquals(paymentWithAttempts.getTransactions().get(0).getExternalKey(), paymentWithAttempts.getPaymentAttempts().get(0).getTransactionExternalKey());
+        // Verify fix for https://github.com/killbill/killbill/issues/349 when external key is set
+        Assert.assertNotEquals(paymentWithAttempts.getId().toString(), paymentWithAttempts.getPaymentAttempts().get(0).getPaymentExternalKey());
+        Assert.assertNotEquals(paymentWithAttempts.getTransactions().get(0).getId().toString(), paymentWithAttempts.getPaymentAttempts().get(0).getTransactionExternalKey());
+
+        final String paymentTransactionExternalKey2 = "something-that-is-not-a-uuid-3";
+
         busHandler.pushExpectedEvents(NextEvent.PAYMENT);
-        paymentApi.createVoidWithPaymentControl(account, payment.getId(), null, properties, paymentOptions, callContext);
+        paymentApi.createVoidWithPaymentControl(account, payment.getId(), paymentTransactionExternalKey2, properties, paymentOptions, callContext);
         assertListenerStatus();
+
+        paymentWithAttempts = paymentApi.getPayment(payment.getId(), false, true, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertEquals(paymentWithAttempts.getPaymentAttempts().size(), 2);
+        Assert.assertEquals(paymentWithAttempts.getTransactions().get(1).getExternalKey(), paymentTransactionExternalKey2);
+        Assert.assertEquals(paymentWithAttempts.getTransactions().get(1).getExternalKey(), paymentWithAttempts.getPaymentAttempts().get(1).getTransactionExternalKey());
+        Assert.assertNotEquals(paymentWithAttempts.getTransactions().get(1).getId().toString(), paymentWithAttempts.getPaymentAttempts().get(1).getTransactionExternalKey());
+
         Assert.assertEquals(testPaymentControlWithControl.getCalls().size(), 2);
         Assert.assertEquals(testPaymentControlWithControl.getCalls().get(TransactionType.AUTHORIZE.toString()), new Integer(1));
         Assert.assertEquals(testPaymentControlWithControl.getCalls().get(TransactionType.VOID.toString()), new Integer(1));
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 d52b6da..6174f20 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
@@ -90,7 +90,7 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
 
             final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
             payment = paymentProcessor.createAuthorization(IS_API_PAYMENT, NULL_ATTEMPT_ID, account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey,
-                                                                         SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
+                                                           null, null, SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
 
             paymentTransaction = findPaymentTransaction(payment, paymentTransactionExternalKey);
 
@@ -187,7 +187,7 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
 
             final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
             payment = paymentProcessor.createCapture(IS_API_PAYMENT, NULL_ATTEMPT_ID, account, paymentId, amount, currency, paymentTransactionExternalKey,
-                                                                   SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
+                                                     null, SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
 
             paymentTransaction = findPaymentTransaction(payment, paymentTransactionExternalKey);
 
@@ -283,7 +283,7 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
 
             final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
             payment = paymentProcessor.createPurchase(IS_API_PAYMENT, NULL_ATTEMPT_ID, account, paymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey,
-                                                                    SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
+                                                      null, null, SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
 
             paymentTransaction = findPaymentTransaction(payment, paymentTransactionExternalKey);
 
@@ -388,7 +388,7 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
 
             final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
             payment = paymentProcessor.createVoid(IS_API_PAYMENT, NULL_ATTEMPT_ID, account, paymentId, paymentTransactionExternalKey,
-                                                                SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
+                                                  null, SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
 
             paymentTransaction = findPaymentTransaction(payment, paymentTransactionExternalKey);
 
@@ -480,7 +480,7 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
 
             final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
             payment = paymentProcessor.createRefund(IS_API_PAYMENT, NULL_ATTEMPT_ID, account, paymentId, amount, currency, paymentTransactionExternalKey,
-                                                                  SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
+                                                    null, SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
 
             paymentTransaction = findPaymentTransaction(payment, paymentTransactionExternalKey);
 
@@ -581,7 +581,7 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
                                                paymentMethodProcessor.createOrGetExternalPaymentMethod(UUIDs.randomUUID().toString(), account, properties, callContext, internalCallContext);
 
             payment = paymentProcessor.createCredit(IS_API_PAYMENT, NULL_ATTEMPT_ID, account, nonNullPaymentMethodId, paymentId, amount, currency, paymentExternalKey, paymentTransactionExternalKey,
-                                                                  SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
+                                                    null, null, SHOULD_LOCK_ACCOUNT, properties, callContext, internalCallContext);
 
             paymentTransaction = findPaymentTransaction(payment, paymentTransactionExternalKey);
 
@@ -784,8 +784,8 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
             logEnterAPICall(log, transactionType, account, null, paymentId, null, amount, currency, null, paymentTransactionExternalKey, null, null);
 
             final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
-            payment = paymentProcessor.createChargeback(IS_API_PAYMENT, NULL_ATTEMPT_ID, account, paymentId, paymentTransactionExternalKey, amount, currency, true,
-                                                                      callContext, internalCallContext);
+            payment = paymentProcessor.createChargeback(IS_API_PAYMENT, NULL_ATTEMPT_ID, account, paymentId, paymentTransactionExternalKey, amount, currency, null, true,
+                                                        callContext, internalCallContext);
 
             paymentTransaction = findPaymentTransaction(payment, paymentTransactionExternalKey);
 
@@ -870,7 +870,7 @@ public class DefaultPaymentApi extends DefaultApiBase implements PaymentApi {
             logEnterAPICall(log, transactionType, account, null, paymentId, null, null, null, null, paymentTransactionExternalKey, null, null);
 
             final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
-            payment = paymentProcessor.createChargebackReversal(IS_API_PAYMENT, NULL_ATTEMPT_ID, account, paymentId, paymentTransactionExternalKey, null, null, true, callContext, internalCallContext);
+            payment = paymentProcessor.createChargebackReversal(IS_API_PAYMENT, NULL_ATTEMPT_ID, account, paymentId, paymentTransactionExternalKey, null, null, null, true, callContext, internalCallContext);
 
             paymentTransaction = findPaymentTransaction(payment, paymentTransactionExternalKey);
 
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 3b5f57e..4db7ea5 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
@@ -130,48 +130,48 @@ public class PaymentProcessor extends ProcessorBase {
     }
 
     public Payment createAuthorization(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, @Nullable final UUID paymentMethodId, @Nullable final UUID paymentId, final BigDecimal amount, final Currency currency,
-                                       @Nullable final String paymentExternalKey, @Nullable final String paymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
+                                       @Nullable final String paymentExternalKey, @Nullable final String paymentTransactionExternalKey, @Nullable final UUID paymentIdForNewPayment, @Nullable final UUID paymentTransactionIdForNewPaymentTransaction, final boolean shouldLockAccountAndDispatch,
                                        final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-        return performOperation(isApiPayment, attemptId, TransactionType.AUTHORIZE, account, paymentMethodId, paymentId, null, amount, currency, paymentExternalKey, paymentTransactionExternalKey, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
+        return performOperation(isApiPayment, attemptId, TransactionType.AUTHORIZE, account, paymentMethodId, paymentId, null, amount, currency, paymentExternalKey, paymentTransactionExternalKey, paymentIdForNewPayment, paymentTransactionIdForNewPaymentTransaction, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
     }
 
     public Payment createCapture(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, final UUID paymentId, final BigDecimal amount, final Currency currency,
-                                 @Nullable final String paymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
+                                 @Nullable final String paymentTransactionExternalKey, @Nullable final UUID paymentTransactionIdForNewPaymentTransaction, final boolean shouldLockAccountAndDispatch,
                                  final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-        return performOperation(isApiPayment, attemptId, TransactionType.CAPTURE, account, null, paymentId, null, amount, currency, null, paymentTransactionExternalKey, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
+        return performOperation(isApiPayment, attemptId, TransactionType.CAPTURE, account, null, paymentId, null, amount, currency, null, paymentTransactionExternalKey, null, paymentTransactionIdForNewPaymentTransaction, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
     }
 
     public Payment createPurchase(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, @Nullable final UUID paymentMethodId, @Nullable final UUID paymentId, final BigDecimal amount, final Currency currency,
-                                  @Nullable final String paymentExternalKey, @Nullable final String paymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
+                                  @Nullable final String paymentExternalKey, @Nullable final String paymentTransactionExternalKey, @Nullable final UUID paymentIdForNewPayment, @Nullable final UUID paymentTransactionIdForNewPaymentTransaction, final boolean shouldLockAccountAndDispatch,
                                   final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-        return performOperation(isApiPayment, attemptId, TransactionType.PURCHASE, account, paymentMethodId, paymentId, null, amount, currency, paymentExternalKey, paymentTransactionExternalKey, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
+        return performOperation(isApiPayment, attemptId, TransactionType.PURCHASE, account, paymentMethodId, paymentId, null, amount, currency, paymentExternalKey, paymentTransactionExternalKey, paymentIdForNewPayment, paymentTransactionIdForNewPaymentTransaction, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
     }
 
-    public Payment createVoid(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, final UUID paymentId, @Nullable final String paymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
+    public Payment createVoid(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, final UUID paymentId, @Nullable final String paymentTransactionExternalKey, @Nullable final UUID paymentTransactionIdForNewPaymentTransaction, final boolean shouldLockAccountAndDispatch,
                               final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-        return performOperation(isApiPayment, attemptId, TransactionType.VOID, account, null, paymentId, null, null, null, null, paymentTransactionExternalKey, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
+        return performOperation(isApiPayment, attemptId, TransactionType.VOID, account, null, paymentId, null, null, null, null, paymentTransactionExternalKey, null, paymentTransactionIdForNewPaymentTransaction, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
     }
 
     public Payment createRefund(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, final UUID paymentId, final BigDecimal amount, final Currency currency,
-                                final String paymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
+                                final String paymentTransactionExternalKey, @Nullable final UUID paymentTransactionIdForNewPaymentTransaction, final boolean shouldLockAccountAndDispatch,
                                 final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-        return performOperation(isApiPayment, attemptId, TransactionType.REFUND, account, null, paymentId, null, amount, currency, null, paymentTransactionExternalKey, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
+        return performOperation(isApiPayment, attemptId, TransactionType.REFUND, account, null, paymentId, null, amount, currency, null, paymentTransactionExternalKey, null, paymentTransactionIdForNewPaymentTransaction, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
     }
 
     public Payment createCredit(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, @Nullable final UUID paymentMethodId, @Nullable final UUID paymentId, final BigDecimal amount, final Currency currency,
-                                @Nullable final String paymentExternalKey, @Nullable final String paymentTransactionExternalKey, final boolean shouldLockAccountAndDispatch,
+                                @Nullable final String paymentExternalKey, @Nullable final String paymentTransactionExternalKey, @Nullable final UUID paymentIdForNewPayment, @Nullable final UUID paymentTransactionIdForNewPaymentTransaction, final boolean shouldLockAccountAndDispatch,
                                 final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-        return performOperation(isApiPayment, attemptId, TransactionType.CREDIT, account, paymentMethodId, paymentId, null, amount, currency, paymentExternalKey, paymentTransactionExternalKey, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
+        return performOperation(isApiPayment, attemptId, TransactionType.CREDIT, account, paymentMethodId, paymentId, null, amount, currency, paymentExternalKey, paymentTransactionExternalKey, paymentIdForNewPayment, paymentTransactionIdForNewPaymentTransaction, shouldLockAccountAndDispatch, null, properties, callContext, internalCallContext);
     }
 
-    public Payment createChargeback(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, final UUID paymentId, @Nullable final String paymentTransactionExternalKey, final BigDecimal amount, final Currency currency, final boolean shouldLockAccountAndDispatch,
+    public Payment createChargeback(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, final UUID paymentId, @Nullable final String paymentTransactionExternalKey, final BigDecimal amount, final Currency currency, @Nullable final UUID paymentTransactionIdForNewPaymentTransaction, final boolean shouldLockAccountAndDispatch,
                                     final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-        return performOperation(isApiPayment, attemptId, TransactionType.CHARGEBACK, account, null, paymentId, null, amount, currency, null, paymentTransactionExternalKey, shouldLockAccountAndDispatch, null, PLUGIN_PROPERTIES, callContext, internalCallContext);
+        return performOperation(isApiPayment, attemptId, TransactionType.CHARGEBACK, account, null, paymentId, null, amount, currency, null, paymentTransactionExternalKey, null, paymentTransactionIdForNewPaymentTransaction, shouldLockAccountAndDispatch, null, PLUGIN_PROPERTIES, callContext, internalCallContext);
     }
 
-    public Payment createChargebackReversal(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, final UUID paymentId, @Nullable final String paymentTransactionExternalKey, final BigDecimal amount, final Currency currency, final boolean shouldLockAccountAndDispatch,
-                                    final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
-        return performOperation(isApiPayment, attemptId, TransactionType.CHARGEBACK, account, null, paymentId, null, amount, currency, null, paymentTransactionExternalKey, shouldLockAccountAndDispatch, OperationResult.FAILURE, PLUGIN_PROPERTIES, callContext, internalCallContext);
+    public Payment createChargebackReversal(final boolean isApiPayment, @Nullable final UUID attemptId, final Account account, final UUID paymentId, @Nullable final String paymentTransactionExternalKey, final BigDecimal amount, final Currency currency, @Nullable final UUID paymentTransactionIdForNewPaymentTransaction, final boolean shouldLockAccountAndDispatch,
+                                            final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
+        return performOperation(isApiPayment, attemptId, TransactionType.CHARGEBACK, account, null, paymentId, null, amount, currency, null, paymentTransactionExternalKey, null, paymentTransactionIdForNewPaymentTransaction, shouldLockAccountAndDispatch, OperationResult.FAILURE, PLUGIN_PROPERTIES, callContext, internalCallContext);
     }
 
     public Payment notifyPendingPaymentOfStateChanged(final Account account, final UUID transactionId, final boolean isSuccess, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
@@ -184,7 +184,7 @@ public class PaymentProcessor extends ProcessorBase {
 
         final boolean runJanitor = false;
         return performOperation(true, runJanitor, null, transactionModelDao.getTransactionType(), account, null, transactionModelDao.getPaymentId(),
-                                transactionModelDao.getId(), transactionModelDao.getAmount(), transactionModelDao.getCurrency(), null, transactionModelDao.getTransactionExternalKey(), true,
+                                transactionModelDao.getId(), transactionModelDao.getAmount(), transactionModelDao.getCurrency(), null, transactionModelDao.getTransactionExternalKey(), null, null, true,
                                 overridePluginResult, PLUGIN_PROPERTIES, callContext, internalCallContext);
     }
 
@@ -441,6 +441,8 @@ public class PaymentProcessor extends ProcessorBase {
                                      @Nullable final Currency currency,
                                      @Nullable final String paymentExternalKey,
                                      @Nullable final String paymentTransactionExternalKey,
+                                     @Nullable final UUID paymentIdForNewPayment,
+                                     @Nullable final UUID paymentTransactionIdForNewPaymentTransaction,
                                      final boolean shouldLockAccountAndDispatch,
                                      @Nullable final OperationResult overridePluginOperationResult,
                                      final Iterable<PluginProperty> properties,
@@ -449,7 +451,7 @@ public class PaymentProcessor extends ProcessorBase {
         boolean runJanitor = true;
         return performOperation(isApiPayment, runJanitor, attemptId, transactionType, account, paymentMethodId, paymentId,
                                 transactionId, amount, currency, paymentExternalKey, paymentTransactionExternalKey,
-                                shouldLockAccountAndDispatch, overridePluginOperationResult, properties, callContext, internalCallContext);
+                                paymentIdForNewPayment, paymentTransactionIdForNewPaymentTransaction, shouldLockAccountAndDispatch, overridePluginOperationResult, properties, callContext, internalCallContext);
     }
 
     private Payment performOperation(final boolean isApiPayment,
@@ -464,6 +466,8 @@ public class PaymentProcessor extends ProcessorBase {
                                      @Nullable final Currency currency,
                                      @Nullable final String paymentExternalKey,
                                      @Nullable final String paymentTransactionExternalKey,
+                                     @Nullable final UUID paymentIdForNewPayment,
+                                     @Nullable final UUID paymentTransactionIdForNewPaymentTransaction,
                                      final boolean shouldLockAccountAndDispatch,
                                      @Nullable final OperationResult overridePluginOperationResult,
                                      final Iterable<PluginProperty> properties,
@@ -480,6 +484,8 @@ public class PaymentProcessor extends ProcessorBase {
                                                                                                         paymentTransactionExternalKey,
                                                                                                         amount,
                                                                                                         currency,
+                                                                                                        paymentIdForNewPayment,
+                                                                                                        paymentTransactionIdForNewPaymentTransaction,
                                                                                                         shouldLockAccountAndDispatch,
                                                                                                         overridePluginOperationResult,
                                                                                                         properties,
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/AuthorizeControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/AuthorizeControlOperation.java
index 8da4e82..93ce8b7 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/AuthorizeControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/AuthorizeControlOperation.java
@@ -46,6 +46,8 @@ public class AuthorizeControlOperation extends OperationControlCallback {
                                                     paymentStateControlContext.getCurrency(),
                                                     paymentStateControlContext.getPaymentExternalKey(),
                                                     paymentStateControlContext.getPaymentTransactionExternalKey(),
+                                                    paymentStateControlContext.getPaymentIdForNewPayment(),
+                                                    paymentStateControlContext.getPaymentTransactionIdForNewPaymentTransaction(),
                                                     false,
                                                     paymentStateControlContext.getProperties(),
                                                     paymentStateControlContext.getCallContext(),
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CaptureControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CaptureControlOperation.java
index 36776b3..af79455 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CaptureControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CaptureControlOperation.java
@@ -44,6 +44,7 @@ public class CaptureControlOperation extends OperationControlCallback {
                                               paymentStateControlContext.getAmount(),
                                               paymentStateControlContext.getCurrency(),
                                               paymentStateControlContext.getPaymentTransactionExternalKey(),
+                                              paymentStateControlContext.getPaymentTransactionIdForNewPaymentTransaction(),
                                               false,
                                               paymentStateControlContext.getProperties(),
                                               paymentStateControlContext.getCallContext(),
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackControlOperation.java
index 99e6a97..d53481f 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackControlOperation.java
@@ -45,6 +45,7 @@ public class ChargebackControlOperation extends OperationControlCallback {
                                                  paymentStateControlContext.getPaymentTransactionExternalKey(),
                                                  paymentStateControlContext.getAmount(),
                                                  paymentStateControlContext.getCurrency(),
+                                                 paymentStateControlContext.getPaymentTransactionIdForNewPaymentTransaction(),
                                                  false,
                                                  paymentStateControlContext.getCallContext(),
                                                  paymentStateControlContext.getInternalCallContext());
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackReversalControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackReversalControlOperation.java
index a0af618..d258b1e 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackReversalControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/ChargebackReversalControlOperation.java
@@ -45,6 +45,7 @@ public class ChargebackReversalControlOperation extends OperationControlCallback
                                                          paymentStateControlContext.getPaymentTransactionExternalKey(),
                                                          paymentStateControlContext.getAmount(),
                                                          paymentStateControlContext.getCurrency(),
+                                                         paymentStateControlContext.getPaymentTransactionIdForNewPaymentTransaction(),
                                                          false,
                                                          paymentStateControlContext.getCallContext(),
                                                          paymentStateControlContext.getInternalCallContext());
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CreditControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CreditControlOperation.java
index 9e91396..e8c3e91 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CreditControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CreditControlOperation.java
@@ -46,6 +46,8 @@ public class CreditControlOperation extends OperationControlCallback {
                                              paymentStateControlContext.getCurrency(),
                                              paymentStateControlContext.getPaymentExternalKey(),
                                              paymentStateControlContext.getPaymentTransactionExternalKey(),
+                                             paymentStateControlContext.getPaymentIdForNewPayment(),
+                                             paymentStateControlContext.getPaymentTransactionIdForNewPaymentTransaction(),
                                              false,
                                              paymentStateControlContext.getProperties(),
                                              paymentStateControlContext.getCallContext(),
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/DefaultControlInitiated.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/DefaultControlInitiated.java
index 4b35883..cbf4136 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/DefaultControlInitiated.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/DefaultControlInitiated.java
@@ -18,6 +18,7 @@
 package org.killbill.billing.payment.core.sm.control;
 
 import java.util.List;
+import java.util.UUID;
 
 import org.joda.time.DateTime;
 import org.killbill.automaton.OperationException;
@@ -85,7 +86,9 @@ public class DefaultControlInitiated implements LeavingStateCallback {
             stateContext.setPaymentExternalKey(payment.getExternalKey());
             stateContext.setPaymentMethodId(payment.getPaymentMethodId());
         } else if (stateContext.getPaymentExternalKey() == null) {
-            stateContext.setPaymentExternalKey(UUIDs.randomUUID().toString());
+            final UUID paymentIdForNewPayment = UUIDs.randomUUID();
+            stateContext.setPaymentIdForNewPayment(paymentIdForNewPayment);
+            stateContext.setPaymentExternalKey(paymentIdForNewPayment.toString());
         }
 
         if (paymentTransactionModelDao != null) {
@@ -93,7 +96,9 @@ public class DefaultControlInitiated implements LeavingStateCallback {
             stateContext.setProcessedAmount(paymentTransactionModelDao.getProcessedAmount());
             stateContext.setProcessedCurrency(paymentTransactionModelDao.getProcessedCurrency());
         } else if (stateContext.getPaymentTransactionExternalKey() == null) {
-            stateContext.setPaymentTransactionExternalKey(UUIDs.randomUUID().toString());
+            final UUID paymentTransactionIdForNewPaymentTransaction = UUIDs.randomUUID();
+            stateContext.setPaymentTransactionIdForNewPaymentTransaction(paymentTransactionIdForNewPaymentTransaction);
+            stateContext.setPaymentTransactionExternalKey(paymentTransactionIdForNewPaymentTransaction.toString());
         }
 
         if (stateContext.getPaymentMethodId() == null) {
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PaymentStateControlContext.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PaymentStateControlContext.java
index 920c660..599e653 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PaymentStateControlContext.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PaymentStateControlContext.java
@@ -61,11 +61,19 @@ public class PaymentStateControlContext extends PaymentStateContext {
                                       final BigDecimal amount,
                                       final Currency currency,
                                       final Iterable<PluginProperty> properties, final InternalCallContext internalCallContext, final CallContext callContext) {
-        super(isApiPayment, paymentId, transactionId, null, paymentExternalKey, paymentTransactionExternalKey, transactionType, account, paymentMethodId, amount, currency, true, null, properties, internalCallContext, callContext);
+        super(isApiPayment, paymentId, transactionId, null, paymentExternalKey, paymentTransactionExternalKey, transactionType, account, paymentMethodId, amount, currency, null, null, true, null, properties, internalCallContext, callContext);
         this.paymentControlPluginNames = paymentControlPluginNames;
         this.isSuccess = isSuccess;
     }
 
+    public void setPaymentIdForNewPayment(final UUID paymentIdForNewPayment) {
+        this.paymentIdForNewPayment = paymentIdForNewPayment;
+    }
+
+    public void setPaymentTransactionIdForNewPaymentTransaction(final UUID paymentTransactionIdForNewPaymentTransaction) {
+        this.paymentTransactionIdForNewPaymentTransaction = paymentTransactionIdForNewPaymentTransaction;
+    }
+
     public DateTime getRetryDate() {
         return retryDate;
     }
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PurchaseControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PurchaseControlOperation.java
index 401b780..cacc797 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PurchaseControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/PurchaseControlOperation.java
@@ -46,6 +46,8 @@ public class PurchaseControlOperation extends OperationControlCallback {
                                                paymentStateControlContext.getCurrency(),
                                                paymentStateControlContext.getPaymentExternalKey(),
                                                paymentStateControlContext.getPaymentTransactionExternalKey(),
+                                               paymentStateControlContext.getPaymentIdForNewPayment(),
+                                               paymentStateControlContext.getPaymentTransactionIdForNewPaymentTransaction(),
                                                false,
                                                paymentStateControlContext.getProperties(),
                                                paymentStateControlContext.getCallContext(),
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/RefundControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/RefundControlOperation.java
index 64fda3f..8ed65db 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/RefundControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/RefundControlOperation.java
@@ -44,6 +44,7 @@ public class RefundControlOperation extends OperationControlCallback {
                                              paymentStateControlContext.getAmount(),
                                              paymentStateControlContext.getCurrency(),
                                              paymentStateControlContext.getPaymentTransactionExternalKey(),
+                                             paymentStateControlContext.getPaymentTransactionIdForNewPaymentTransaction(),
                                              false,
                                              paymentStateControlContext.getProperties(),
                                              paymentStateControlContext.getCallContext(),
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/VoidControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/VoidControlOperation.java
index f600e8b..9433a56 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/VoidControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/VoidControlOperation.java
@@ -42,6 +42,7 @@ public class VoidControlOperation extends OperationControlCallback {
                                            paymentStateControlContext.getAccount(),
                                            paymentStateControlContext.getPaymentId(),
                                            paymentStateControlContext.getPaymentTransactionExternalKey(),
+                                           paymentStateControlContext.getPaymentTransactionIdForNewPaymentTransaction(),
                                            false,
                                            paymentStateControlContext.getProperties(),
                                            paymentStateControlContext.getCallContext(),
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 c9a2ae0..5b11b15 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
@@ -195,11 +195,20 @@ public class PaymentAutomatonDAOHelper {
         final DateTime createdDate = utcNow;
         final DateTime updatedDate = utcNow;
 
-        return new PaymentModelDao(createdDate,
-                                   updatedDate,
-                                   paymentStateContext.getAccount().getId(),
-                                   paymentStateContext.getPaymentMethodId(),
-                                   paymentStateContext.getPaymentExternalKey());
+        if (paymentStateContext.getPaymentIdForNewPayment() != null) {
+            return new PaymentModelDao(paymentStateContext.getPaymentIdForNewPayment(),
+                                       createdDate,
+                                       updatedDate,
+                                       paymentStateContext.getAccount().getId(),
+                                       paymentStateContext.getPaymentMethodId(),
+                                       paymentStateContext.getPaymentExternalKey());
+        } else {
+            return new PaymentModelDao(createdDate,
+                                       updatedDate,
+                                       paymentStateContext.getAccount().getId(),
+                                       paymentStateContext.getPaymentMethodId(),
+                                       paymentStateContext.getPaymentExternalKey());
+        }
     }
 
     private PaymentTransactionModelDao buildNewPaymentTransactionModelDao(final UUID paymentId) {
@@ -209,18 +218,34 @@ public class PaymentAutomatonDAOHelper {
         final String gatewayErrorCode = null;
         final String gatewayErrorMsg = null;
 
-        return new PaymentTransactionModelDao(createdDate,
-                                              updatedDate,
-                                              paymentStateContext.getAttemptId(),
-                                              paymentStateContext.getPaymentTransactionExternalKey(),
-                                              paymentId,
-                                              paymentStateContext.getTransactionType(),
-                                              effectiveDate,
-                                              TransactionStatus.UNKNOWN,
-                                              paymentStateContext.getAmount(),
-                                              paymentStateContext.getCurrency(),
-                                              gatewayErrorCode,
-                                              gatewayErrorMsg);
+        if (paymentStateContext.getPaymentTransactionIdForNewPaymentTransaction() != null) {
+            return new PaymentTransactionModelDao(paymentStateContext.getPaymentTransactionIdForNewPaymentTransaction(),
+                                                  createdDate,
+                                                  updatedDate,
+                                                  paymentStateContext.getAttemptId(),
+                                                  paymentStateContext.getPaymentTransactionExternalKey(),
+                                                  paymentId,
+                                                  paymentStateContext.getTransactionType(),
+                                                  effectiveDate,
+                                                  TransactionStatus.UNKNOWN,
+                                                  paymentStateContext.getAmount(),
+                                                  paymentStateContext.getCurrency(),
+                                                  gatewayErrorCode,
+                                                  gatewayErrorMsg);
+        } else {
+            return new PaymentTransactionModelDao(createdDate,
+                                                  updatedDate,
+                                                  paymentStateContext.getAttemptId(),
+                                                  paymentStateContext.getPaymentTransactionExternalKey(),
+                                                  paymentId,
+                                                  paymentStateContext.getTransactionType(),
+                                                  effectiveDate,
+                                                  TransactionStatus.UNKNOWN,
+                                                  paymentStateContext.getAmount(),
+                                                  paymentStateContext.getCurrency(),
+                                                  gatewayErrorCode,
+                                                  gatewayErrorMsg);
+        }
     }
 
     public String getPluginName() {
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 04c768b..331d317 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
@@ -122,6 +122,8 @@ public class PaymentAutomatonRunner {
                                                         final String paymentTransactionExternalKey,
                                                         @Nullable final BigDecimal amount,
                                                         @Nullable final Currency currency,
+                                                        @Nullable final UUID paymentIdForNewPayment,
+                                                        @Nullable final UUID paymentTransactionIdForNewPaymentTransaction,
                                                         final boolean shouldLockAccount,
                                                         final OperationResult overridePluginOperationResult,
                                                         final Iterable<PluginProperty> properties,
@@ -142,6 +144,8 @@ public class PaymentAutomatonRunner {
                                        paymentMethodId,
                                        amount,
                                        currency,
+                                       paymentIdForNewPayment,
+                                       paymentTransactionIdForNewPaymentTransaction,
                                        shouldLockAccount,
                                        overridePluginOperationResult,
                                        properties,
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 8975b22..632f15d 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
@@ -33,6 +33,7 @@ import org.killbill.billing.payment.dao.PaymentTransactionModelDao;
 import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
 import org.killbill.billing.util.callcontext.CallContext;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 
 public class PaymentStateContext {
@@ -56,6 +57,8 @@ public class PaymentStateContext {
     // Set in the control layer in the leavingState callback
     private String paymentExternalKey;
     private String paymentTransactionExternalKey;
+    protected UUID paymentIdForNewPayment;
+    protected UUID paymentTransactionIdForNewPaymentTransaction;
 
     // Set in the control layer after creating the attempt in the enteringState callback
     private UUID attemptId;
@@ -72,20 +75,20 @@ public class PaymentStateContext {
     private final CallContext callContext;
     private final boolean isApiPayment;
 
-    // Use to create new transactions only
+    @VisibleForTesting
     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(isApiPayment, paymentId, null, null, null, paymentTransactionExternalKey, transactionType, account, paymentMethodId,
-             amount, currency, shouldLockAccountAndDispatch, null, properties, internalCallContext, callContext);
+             amount, currency, null, null, shouldLockAccountAndDispatch, null, properties, internalCallContext, callContext);
     }
 
     // Used to create new payment and transactions
     public PaymentStateContext(final boolean isApiPayment, @Nullable final UUID paymentId, final UUID transactionId, @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 OperationResult overridePluginOperationResult, final Iterable<PluginProperty> properties,
+                               @Nullable final UUID paymentIdForNewPayment, @Nullable final UUID paymentTransactionIdForNewPaymentTransaction, final boolean shouldLockAccountAndDispatch, final OperationResult overridePluginOperationResult, final Iterable<PluginProperty> properties,
                                final InternalCallContext internalCallContext, final CallContext callContext) {
         this.isApiPayment = isApiPayment;
         this.paymentId = paymentId;
@@ -98,6 +101,8 @@ public class PaymentStateContext {
         this.paymentMethodId = paymentMethodId;
         this.amount = amount;
         this.currency = currency;
+        this.paymentIdForNewPayment = paymentIdForNewPayment;
+        this.paymentTransactionIdForNewPaymentTransaction = paymentTransactionIdForNewPaymentTransaction;
         this.shouldLockAccountAndDispatch = shouldLockAccountAndDispatch;
         this.overridePluginOperationResult = overridePluginOperationResult;
         this.properties = properties;
@@ -234,4 +239,11 @@ public class PaymentStateContext {
         this.properties = properties;
     }
 
+    public UUID getPaymentIdForNewPayment() {
+        return paymentIdForNewPayment;
+    }
+
+    public UUID getPaymentTransactionIdForNewPaymentTransaction() {
+        return paymentTransactionIdForNewPaymentTransaction;
+    }
 }
diff --git a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentModelDao.java b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentModelDao.java
index 618d50d..7db4e0d 100644
--- a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentModelDao.java
+++ b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentModelDao.java
@@ -52,9 +52,14 @@ public class PaymentModelDao extends EntityModelDaoBase implements EntityModelDa
         this.externalKey = MoreObjects.firstNonNull(externalKey, id.toString());
     }
 
+    public PaymentModelDao(final UUID id, @Nullable final DateTime createdDate, @Nullable final DateTime updatedDate, final UUID accountId,
+                           final UUID paymentMethodId, @Nullable final String externalKey) {
+        this(id, createdDate, updatedDate, accountId, paymentMethodId, INVALID_PAYMENT_NUMBER, externalKey);
+    }
+
     public PaymentModelDao(@Nullable final DateTime createdDate, @Nullable final DateTime updatedDate, final UUID accountId,
                            final UUID paymentMethodId, @Nullable final String externalKey) {
-        this(UUIDs.randomUUID(), createdDate, updatedDate, accountId, paymentMethodId, INVALID_PAYMENT_NUMBER, externalKey);
+        this(UUIDs.randomUUID(), createdDate, updatedDate, accountId, paymentMethodId, externalKey);
     }
 
     public UUID getAccountId() { return accountId; }
diff --git a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentTransactionModelDao.java b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentTransactionModelDao.java
index da7363b..88d40c6 100644
--- a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentTransactionModelDao.java
+++ b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentTransactionModelDao.java
@@ -70,10 +70,16 @@ public class PaymentTransactionModelDao extends EntityModelDaoBase implements En
         this.gatewayErrorMsg = gatewayErrorMsg;
     }
 
+    public PaymentTransactionModelDao(final UUID id, @Nullable final DateTime createdDate, @Nullable final DateTime updatedDate, @Nullable final UUID attemptId,
+                                      @Nullable final String transactionExternalKey, final UUID paymentId, final TransactionType transactionType, final DateTime effectiveDate,
+                                      final TransactionStatus paymentStatus, final BigDecimal amount, final Currency currency, final String gatewayErrorCode, final String gatewayErrorMsg) {
+        this(id, attemptId, transactionExternalKey, createdDate, updatedDate, paymentId, transactionType, effectiveDate, paymentStatus, amount, currency, gatewayErrorCode, gatewayErrorMsg);
+    }
+
     public PaymentTransactionModelDao(@Nullable final DateTime createdDate, @Nullable final DateTime updatedDate, @Nullable final UUID attemptId,
                                       @Nullable final String transactionExternalKey, final UUID paymentId, final TransactionType transactionType, final DateTime effectiveDate,
                                       final TransactionStatus paymentStatus, final BigDecimal amount, final Currency currency, final String gatewayErrorCode, final String gatewayErrorMsg) {
-        this(UUIDs.randomUUID(), attemptId, transactionExternalKey, createdDate, updatedDate, paymentId, transactionType, effectiveDate, paymentStatus, amount, currency, gatewayErrorCode, gatewayErrorMsg);
+        this(UUIDs.randomUUID(), createdDate, updatedDate, attemptId, transactionExternalKey, paymentId, transactionType, effectiveDate, paymentStatus, amount, currency, gatewayErrorCode, gatewayErrorMsg);
     }
 
     public UUID getPaymentId() {
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 6380bfa..350bf9f 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
@@ -42,7 +42,6 @@ import org.killbill.billing.payment.core.sm.control.ControlPluginRunner;
 import org.killbill.billing.payment.core.sm.control.PaymentStateControlContext;
 import org.killbill.billing.payment.dao.PaymentDao;
 import org.killbill.billing.payment.dispatcher.PluginDispatcher;
-import org.killbill.billing.payment.plugin.api.PaymentPluginApi;
 import org.killbill.billing.payment.retry.BaseRetryService.RetryServiceScheduler;
 import org.killbill.billing.tag.TagInternalApi;
 import org.killbill.billing.util.callcontext.CallContext;
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 3d37638..88655c2 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
@@ -114,8 +114,10 @@ public class TestPaymentAutomatonDAOHelper extends PaymentTestSuiteWithEmbeddedD
         Mockito.when(account.getId()).thenReturn(UUID.randomUUID());
         // No default payment method
 
-        paymentStateContext = new PaymentStateContext(true, paymentId,
-                                                      null, null,
+        paymentStateContext = new PaymentStateContext(true,
+                                                      paymentId,
+                                                      null,
+                                                      null,
                                                       paymentExternalKey,
                                                       paymentTransactionExternalKey,
                                                       TransactionType.CAPTURE,
@@ -123,8 +125,11 @@ public class TestPaymentAutomatonDAOHelper extends PaymentTestSuiteWithEmbeddedD
                                                       UUID.randomUUID(),
                                                       amount,
                                                       currency,
+                                                      null,
+                                                      null,
                                                       false,
-                                                      null, ImmutableList.<PluginProperty>of(),
+                                                      null,
+                                                      ImmutableList.<PluginProperty>of(),
                                                       internalCallContext,
                                                       callContext);
 
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 91576ee..6b1f308 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
@@ -112,6 +112,8 @@ public class TestPaymentLeavingStateCallback extends PaymentTestSuiteWithEmbedde
                                                       UUID.randomUUID(),
                                                       new BigDecimal("192.3920111"),
                                                       Currency.BRL,
+                                                      null,
+                                                      null,
                                                       false,
                                                       null, ImmutableList.<PluginProperty>of(),
                                                       internalCallContext,
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 fef77fb..8ee5efb 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
@@ -116,6 +116,8 @@ public class TestPaymentOperation extends PaymentTestSuiteNoDB {
                                                       UUID.randomUUID(),
                                                       new BigDecimal("192.3920111"),
                                                       Currency.BRL,
+                                                      null,
+                                                      null,
                                                       false,
                                                       null, ImmutableList.<PluginProperty>of(),
                                                       internalCallContext,
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 ea77ad2..294a5f8 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
@@ -206,8 +206,10 @@ public class TestPluginOperation extends PaymentTestSuiteNoDB {
     private PaymentOperation getPluginOperation(final boolean shouldLockAccount, final int timeoutSeconds) throws PaymentApiException {
         final PluginDispatcher<OperationResult> paymentPluginDispatcher = new PluginDispatcher<OperationResult>(timeoutSeconds, paymentExecutors);
 
-        final PaymentStateContext paymentStateContext = new PaymentStateContext(true, UUID.randomUUID(),
-                                                                                null, null,
+        final PaymentStateContext paymentStateContext = new PaymentStateContext(true,
+                                                                                UUID.randomUUID(),
+                                                                                null,
+                                                                                null,
                                                                                 UUID.randomUUID().toString(),
                                                                                 UUID.randomUUID().toString(),
                                                                                 TransactionType.CAPTURE,
@@ -215,8 +217,11 @@ public class TestPluginOperation extends PaymentTestSuiteNoDB {
                                                                                 UUID.randomUUID(),
                                                                                 new BigDecimal("192.3920111"),
                                                                                 Currency.BRL,
+                                                                                null,
+                                                                                null,
                                                                                 shouldLockAccount,
-                                                                                null, ImmutableList.<PluginProperty>of(),
+                                                                                null,
+                                                                                ImmutableList.<PluginProperty>of(),
                                                                                 internalCallContext,
                                                                                 callContext);
 
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 754d1fe..3e026fa 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
@@ -81,7 +81,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
 
         final String authorizationKey = UUID.randomUUID().toString();
         final Payment authorization = paymentProcessor.createAuthorization(true, null, account, null, null, TEN, CURRENCY, paymentExternalKey, authorizationKey,
-                                                                           SHOULD_LOCK_ACCOUNT, pluginPropertiesToDriveTransationToUnknown, callContext, internalCallContext);
+                                                                           null, null, SHOULD_LOCK_ACCOUNT, pluginPropertiesToDriveTransationToUnknown, callContext, internalCallContext);
         verifyPayment(authorization, paymentExternalKey, ZERO, ZERO, ZERO, 1);
         final UUID paymentId = authorization.getId();
         verifyPaymentTransaction(authorization.getTransactions().get(0), authorizationKey, TransactionType.AUTHORIZE, TEN, paymentId);
@@ -105,7 +105,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         // AUTH pre-3DS
         final String authorizationKey = UUID.randomUUID().toString();
         final Payment authorization = paymentProcessor.createAuthorization(true, null, account, null, null, TEN, CURRENCY, paymentExternalKey, authorizationKey,
-                                                                           SHOULD_LOCK_ACCOUNT, pluginPropertiesToDriveTransationToPending, callContext, internalCallContext);
+                                                                           null, null, SHOULD_LOCK_ACCOUNT, pluginPropertiesToDriveTransationToPending, callContext, internalCallContext);
         verifyPayment(authorization, paymentExternalKey, ZERO, ZERO, ZERO, 1);
         final UUID paymentId = authorization.getId();
         verifyPaymentTransaction(authorization.getTransactions().get(0), authorizationKey, TransactionType.AUTHORIZE, TEN, paymentId);
@@ -113,7 +113,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
 
         // AUTH post-3DS
         final Payment authorizationPost3DS = paymentProcessor.createAuthorization(true, null, account, null, paymentId, TEN, CURRENCY, paymentExternalKey, authorizationKey,
-                                                                                  SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
+                                                                                  null, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(authorizationPost3DS, paymentExternalKey, TEN, ZERO, ZERO, 1);
         verifyPaymentTransaction(authorizationPost3DS.getTransactions().get(0), authorizationKey, TransactionType.AUTHORIZE, TEN, paymentId);
         paymentBusListener.verify(2, account.getId(), paymentId, TEN, TransactionStatus.SUCCESS);
@@ -121,7 +121,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         // CAPTURE
         final String capture1Key = UUID.randomUUID().toString();
         final Payment partialCapture1 = paymentProcessor.createCapture(true, null, account, paymentId, FIVE, CURRENCY, capture1Key,
-                                                                       SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
+                                                                       null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(partialCapture1, paymentExternalKey, TEN, FIVE, ZERO, 2);
         verifyPaymentTransaction(partialCapture1.getTransactions().get(1), capture1Key, TransactionType.CAPTURE, FIVE, paymentId);
         paymentBusListener.verify(3, account.getId(), paymentId, FIVE, TransactionStatus.SUCCESS);
@@ -129,7 +129,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         // CAPTURE
         final String capture2Key = UUID.randomUUID().toString();
         final Payment partialCapture2 = paymentProcessor.createCapture(true, null, account, paymentId, FIVE, CURRENCY, capture2Key,
-                                                                       SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
+                                                                       null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(partialCapture2, paymentExternalKey, TEN, TEN, ZERO, 3);
         verifyPaymentTransaction(partialCapture2.getTransactions().get(2), capture2Key, TransactionType.CAPTURE, FIVE, paymentId);
         paymentBusListener.verify(4, account.getId(), paymentId, FIVE, TransactionStatus.SUCCESS);
@@ -137,7 +137,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         // REFUND
         final String refund1Key = UUID.randomUUID().toString();
         final Payment partialRefund1 = paymentProcessor.createRefund(true, null, account, paymentId, FIVE, CURRENCY, refund1Key,
-                                                                     SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
+                                                                     null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(partialRefund1, paymentExternalKey, TEN, TEN, FIVE, 4);
         verifyPaymentTransaction(partialRefund1.getTransactions().get(3), refund1Key, TransactionType.REFUND, FIVE, paymentId);
         paymentBusListener.verify(5, account.getId(), paymentId, FIVE, TransactionStatus.SUCCESS);
@@ -145,7 +145,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         // REFUND
         final String refund2Key = UUID.randomUUID().toString();
         final Payment partialRefund2 = paymentProcessor.createRefund(true, null, account, paymentId, FIVE, CURRENCY, refund2Key,
-                                                                     SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
+                                                                     null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(partialRefund2, paymentExternalKey, TEN, TEN, TEN, 5);
         verifyPaymentTransaction(partialRefund2.getTransactions().get(4), refund2Key, TransactionType.REFUND, FIVE, paymentId);
         paymentBusListener.verify(6, account.getId(), paymentId, FIVE, TransactionStatus.SUCCESS);
@@ -158,7 +158,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         // AUTH
         final String authorizationKey = UUID.randomUUID().toString();
         final Payment authorization = paymentProcessor.createAuthorization(true, null, account, null, null, TEN, CURRENCY, paymentExternalKey, authorizationKey,
-                                                                           SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
+                                                                           null, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(authorization, paymentExternalKey, TEN, ZERO, ZERO, 1);
         final UUID paymentId = authorization.getId();
         verifyPaymentTransaction(authorization.getTransactions().get(0), authorizationKey, TransactionType.AUTHORIZE, TEN, paymentId);
@@ -167,7 +167,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         // VOID
         final String voidKey = UUID.randomUUID().toString();
         final Payment voidTransaction = paymentProcessor.createVoid(true, null, account, paymentId, voidKey,
-                                                                    SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
+                                                                    null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(voidTransaction, paymentExternalKey, ZERO, ZERO, ZERO, 2);
         verifyPaymentTransaction(voidTransaction.getTransactions().get(1), voidKey, TransactionType.VOID, null, paymentId);
         paymentBusListener.verify(2, account.getId(), paymentId, null, TransactionStatus.SUCCESS);
@@ -180,7 +180,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         // PURCHASE
         final String purchaseKey = UUID.randomUUID().toString();
         final Payment purchase = paymentProcessor.createPurchase(true, null, account, null, null, TEN, CURRENCY, paymentExternalKey, purchaseKey,
-                                                                 SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
+                                                                 null, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(purchase, paymentExternalKey, ZERO, ZERO, ZERO, 1);
         final UUID paymentId = purchase.getId();
         verifyPaymentTransaction(purchase.getTransactions().get(0), purchaseKey, TransactionType.PURCHASE, TEN, paymentId);
@@ -194,7 +194,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         // CREDIT
         final String creditKey = UUID.randomUUID().toString();
         final Payment purchase = paymentProcessor.createCredit(true, null, account, null, null, TEN, CURRENCY, paymentExternalKey, creditKey,
-                                                               SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
+                                                               null, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
         verifyPayment(purchase, paymentExternalKey, ZERO, ZERO, ZERO, 1);
         final UUID paymentId = purchase.getId();
         verifyPaymentTransaction(purchase.getTransactions().get(0), creditKey, TransactionType.CREDIT, TEN, paymentId);
@@ -209,7 +209,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         // AUTH
         final String authorizationKey = UUID.randomUUID().toString();
         final Payment authorization = paymentProcessor.createAuthorization(true, null, account, null, null, TEN, CURRENCY, paymentExternalKey, authorizationKey,
-                                                                           SHOULD_LOCK_ACCOUNT, pluginPropertiesToDriveTransationToPending, callContext, internalCallContext);
+                                                                           null, null, SHOULD_LOCK_ACCOUNT, pluginPropertiesToDriveTransationToPending, callContext, internalCallContext);
         verifyPayment(authorization, paymentExternalKey, ZERO, ZERO, ZERO, 1);
         final UUID paymentId = authorization.getId();
         verifyPaymentTransaction(authorization.getTransactions().get(0), authorizationKey, TransactionType.AUTHORIZE, TEN, paymentId);
@@ -219,7 +219,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         final String refundKey = UUID.randomUUID().toString();
         try {
             paymentProcessor.createRefund(true, null, account, paymentId, TEN, CURRENCY, refundKey,
-                                          SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
+                                          null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext);
             Assert.fail();
         } catch (final PaymentApiException e) {
             Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INVALID_OPERATION.getCode());
@@ -238,7 +238,7 @@ public class TestPaymentProcessor extends PaymentTestSuiteWithEmbeddedDB {
         // Create Pending AUTH
         final String authorizationKey = UUID.randomUUID().toString();
         final Payment authorization = paymentProcessor.createAuthorization(true, null, account, null, null, TEN, CURRENCY, paymentExternalKey, authorizationKey,
-                                                                           SHOULD_LOCK_ACCOUNT, pluginPropertiesToDriveTransationToPending, callContext, internalCallContext);
+                                                                           null, null, SHOULD_LOCK_ACCOUNT, pluginPropertiesToDriveTransationToPending, callContext, internalCallContext);
         final PaymentTransaction pendingTransaction = authorization.getTransactions().get(0);
         Assert.assertEquals(pendingTransaction.getTransactionStatus(), TransactionStatus.PENDING);