killbill-memoizeit

Details

diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java
index a96e3b0..e69e85c 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/PaymentResource.java
@@ -17,7 +17,9 @@
 
 package org.killbill.billing.jaxrs.resources;
 
+import java.math.BigDecimal;
 import java.net.URI;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -56,6 +58,7 @@ import org.killbill.billing.payment.api.Payment;
 import org.killbill.billing.payment.api.PaymentApi;
 import org.killbill.billing.payment.api.PaymentApiException;
 import org.killbill.billing.payment.api.PaymentOptions;
+import org.killbill.billing.payment.api.PaymentTransaction;
 import org.killbill.billing.payment.api.PluginProperty;
 import org.killbill.billing.payment.api.TransactionType;
 import org.killbill.billing.util.api.AuditUserApi;
@@ -69,7 +72,9 @@ import org.killbill.clock.Clock;
 
 import com.codahale.metrics.annotation.Timed;
 import com.google.common.base.Function;
+import com.google.common.base.Predicate;
 import com.google.common.base.Strings;
+import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableMap;
 import com.wordnik.swagger.annotations.Api;
 import com.wordnik.swagger.annotations.ApiOperation;
@@ -270,39 +275,99 @@ public class PaymentResource extends ComboPaymentResource {
                                                  final String comment,
                                                  final UriInfo uriInfo,
                                                  final HttpServletRequest request) throws PaymentApiException, AccountApiException {
-        verifyNonNullOrEmpty(json, "PaymentTransactionJson body should be specified");
-        verifyNonNullOrEmpty(json.getTransactionType(), "PaymentTransactionJson transactionType needs to be set");
-        if (paymentIdStr == null) {
-            verifyNonNullOrEmpty(json.getPaymentExternalKey(), "PaymentTransactionJson externalKey needs to be set");
-        }
-
         final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
         final CallContext callContext = context.createContext(createdBy, reason, comment, request);
-        final Payment initialPayment = getPaymentByIdOrKey(paymentIdStr, json.getPaymentExternalKey(), pluginProperties, callContext);
+        final Payment initialPayment = getPaymentByIdOrKey(paymentIdStr, json == null ? null : json.getPaymentExternalKey(), pluginProperties, callContext);
 
         final Account account = accountUserApi.getAccountById(initialPayment.getAccountId(), callContext);
-        final Currency currency = json.getCurrency() == null ? account.getCurrency() : Currency.valueOf(json.getCurrency());
+        final BigDecimal amount = json == null ? null : json.getAmount();
+        final Currency currency = json == null || json.getCurrency() == null ? null : Currency.valueOf(json.getCurrency());
+
+        final TransactionType transactionType;
+        final String transactionExternalKey;
+        if (json != null && json.getTransactionId() != null) {
+            final Collection<PaymentTransaction> paymentTransactionCandidates = Collections2.<PaymentTransaction>filter(initialPayment.getTransactions(),
+                                                                                                                        new Predicate<PaymentTransaction>() {
+                                                                                                                            @Override
+                                                                                                                            public boolean apply(final PaymentTransaction input) {
+                                                                                                                                return input.getId().toString().equals(json.getTransactionId());
+                                                                                                                            }
+                                                                                                                        });
+            if (paymentTransactionCandidates.size() == 1) {
+                final PaymentTransaction paymentTransaction = paymentTransactionCandidates.iterator().next();
+                transactionType = paymentTransaction.getTransactionType();
+                transactionExternalKey = paymentTransaction.getExternalKey();
+            } else {
+                return Response.status(Status.NOT_FOUND).build();
+            }
+        } else if (json != null && json.getTransactionExternalKey() != null && json.getTransactionType() != null) {
+            transactionType = TransactionType.valueOf(json.getTransactionType());
+            transactionExternalKey = json.getTransactionExternalKey();
+        } else if (json != null && json.getTransactionExternalKey() != null) {
+            final Collection<PaymentTransaction> paymentTransactionCandidates = Collections2.<PaymentTransaction>filter(initialPayment.getTransactions(),
+                                                                                                                        new Predicate<PaymentTransaction>() {
+                                                                                                                            @Override
+                                                                                                                            public boolean apply(final PaymentTransaction input) {
+                                                                                                                                return input.getExternalKey().equals(json.getTransactionExternalKey());
+                                                                                                                            }
+                                                                                                                        });
+            if (paymentTransactionCandidates.size() == 1) {
+                transactionType = paymentTransactionCandidates.iterator().next().getTransactionType();
+                transactionExternalKey = json.getTransactionExternalKey();
+            } else {
+                // Note: we could bit a bit smarter but keep the logic in the payment system
+                verifyNonNullOrEmpty(null, "PaymentTransactionJson transactionType needs to be set");
+                // Never reached
+                return Response.status(Status.PRECONDITION_FAILED).build();
+            }
+        } else if (json != null && json.getTransactionType() != null) {
+            final Collection<PaymentTransaction> paymentTransactionCandidates = Collections2.<PaymentTransaction>filter(initialPayment.getTransactions(),
+                                                                                                                        new Predicate<PaymentTransaction>() {
+                                                                                                                            @Override
+                                                                                                                            public boolean apply(final PaymentTransaction input) {
+                                                                                                                                return input.getTransactionType().toString().equals(json.getTransactionType());
+                                                                                                                            }
+                                                                                                                        });
+            if (paymentTransactionCandidates.size() == 1) {
+                transactionType = TransactionType.valueOf(json.getTransactionType());
+                transactionExternalKey = paymentTransactionCandidates.iterator().next().getExternalKey();
+            } else {
+                verifyNonNullOrEmpty(null, "PaymentTransactionJson externalKey needs to be set");
+                // Never reached
+                return Response.status(Status.PRECONDITION_FAILED).build();
+            }
+        } else if (initialPayment.getTransactions().size() == 1) {
+            final PaymentTransaction paymentTransaction = initialPayment.getTransactions().get(0);
+            transactionType = paymentTransaction.getTransactionType();
+            transactionExternalKey = paymentTransaction.getExternalKey();
+        } else {
+            verifyNonNullOrEmpty(null, "PaymentTransactionJson transactionType and externalKey need to be set");
+            // Never reached
+            return Response.status(Status.PRECONDITION_FAILED).build();
+        }
 
-        final TransactionType transactionType = TransactionType.valueOf(json.getTransactionType());
         final PaymentOptions paymentOptions = createControlPluginApiPaymentOptions(paymentControlPluginNames);
         switch (transactionType) {
             case AUTHORIZE:
-                paymentApi.createAuthorizationWithPaymentControl(account, initialPayment.getPaymentMethodId(), initialPayment.getId(), json.getAmount(), currency,
-                                                                 json.getPaymentExternalKey(), json.getTransactionExternalKey(),
+                paymentApi.createAuthorizationWithPaymentControl(account, initialPayment.getPaymentMethodId(), initialPayment.getId(), amount, currency,
+                                                                 initialPayment.getExternalKey(), transactionExternalKey,
                                                                  pluginProperties, paymentOptions, callContext);
                 break;
             case PURCHASE:
-                paymentApi.createPurchaseWithPaymentControl(account, initialPayment.getPaymentMethodId(), initialPayment.getId(), json.getAmount(), currency,
-                                                            json.getPaymentExternalKey(), json.getTransactionExternalKey(),
+                paymentApi.createPurchaseWithPaymentControl(account, initialPayment.getPaymentMethodId(), initialPayment.getId(), amount, currency,
+                                                            initialPayment.getExternalKey(), transactionExternalKey,
                                                             pluginProperties, paymentOptions, callContext);
                 break;
             case CREDIT:
-                paymentApi.createCreditWithPaymentControl(account, initialPayment.getPaymentMethodId(), initialPayment.getId(), json.getAmount(), currency,
-                                                          json.getPaymentExternalKey(), json.getTransactionExternalKey(),
+                paymentApi.createCreditWithPaymentControl(account, initialPayment.getPaymentMethodId(), initialPayment.getId(), amount, currency,
+                                                          initialPayment.getExternalKey(), transactionExternalKey,
                                                           pluginProperties, paymentOptions, callContext);
                 break;
+            case REFUND:
+                paymentApi.createRefundWithPaymentControl(account, initialPayment.getId(), amount, currency,
+                                                          transactionExternalKey, pluginProperties, paymentOptions, callContext);
+                break;
             default:
-                // It looks like we need at least REFUND? See https://github.com/killbill/killbill/issues/371
                 return Response.status(Status.PRECONDITION_FAILED).entity("TransactionType " + transactionType + " cannot be completed").build();
         }
         return uriBuilder.buildResponse(uriInfo, PaymentResource.class, "getPayment", initialPayment.getId());
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
index df635ae..1cfdb15 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
@@ -33,6 +33,8 @@ import org.killbill.billing.client.model.PaymentTransaction;
 import org.killbill.billing.client.model.Payments;
 import org.killbill.billing.client.model.PluginProperty;
 import org.killbill.billing.payment.api.TransactionType;
+import org.killbill.billing.payment.plugin.api.PaymentPluginStatus;
+import org.killbill.billing.payment.provider.MockPaymentProviderPlugin;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -53,6 +55,113 @@ public class TestPayment extends TestJaxrsBase {
     }
 
     @Test(groups = "slow")
+    public void testCompletionForInitialTransaction() throws Exception {
+        final Account account = createAccountWithDefaultPaymentMethod();
+        final UUID paymentMethodId = account.getPaymentMethodId();
+        final BigDecimal amount = BigDecimal.TEN;
+
+        final String pending = PaymentPluginStatus.PENDING.toString();
+        final ImmutableMap<String, String> pluginProperties = ImmutableMap.<String, String>of(MockPaymentProviderPlugin.PLUGIN_PROPERTY_PAYMENT_PLUGIN_STATUS_OVERRIDE, pending);
+
+        int paymentNb = 0;
+        for (final TransactionType transactionType : ImmutableList.<TransactionType>of(TransactionType.AUTHORIZE, TransactionType.PURCHASE, TransactionType.CREDIT)) {
+            final BigDecimal authAmount = BigDecimal.ZERO;
+            final String paymentExternalKey = UUID.randomUUID().toString();
+            final String authTransactionExternalKey = UUID.randomUUID().toString();
+            paymentNb++;
+
+            final Payment initialPayment = createVerifyTransaction(account, paymentMethodId, paymentExternalKey, authTransactionExternalKey, transactionType, pending, amount, authAmount, pluginProperties, paymentNb);
+            final PaymentTransaction authPaymentTransaction = initialPayment.getTransactions().get(0);
+
+            // Complete operation: first, only specify the payment id
+            final PaymentTransaction completeTransactionByPaymentId = new PaymentTransaction();
+            completeTransactionByPaymentId.setPaymentId(initialPayment.getPaymentId());
+            final Payment completedPaymentByPaymentId = killBillClient.completePayment(completeTransactionByPaymentId, pluginProperties, createdBy, reason, comment);
+            verifyPayment(account, paymentMethodId, completedPaymentByPaymentId, paymentExternalKey, authTransactionExternalKey, transactionType.toString(), pending, amount, authAmount, BigDecimal.ZERO, BigDecimal.ZERO, 1, paymentNb);
+
+            // Second, only specify the payment external key
+            final PaymentTransaction completeTransactionByPaymentExternalKey = new PaymentTransaction();
+            completeTransactionByPaymentExternalKey.setPaymentExternalKey(initialPayment.getPaymentExternalKey());
+            final Payment completedPaymentByExternalKey = killBillClient.completePayment(completeTransactionByPaymentExternalKey, pluginProperties, createdBy, reason, comment);
+            verifyPayment(account, paymentMethodId, completedPaymentByExternalKey, paymentExternalKey, authTransactionExternalKey, transactionType.toString(), pending, amount, authAmount, BigDecimal.ZERO, BigDecimal.ZERO, 1, paymentNb);
+
+            // Third, specify the payment id and transaction external key
+            final PaymentTransaction completeTransactionWithTypeAndKey = new PaymentTransaction();
+            completeTransactionWithTypeAndKey.setPaymentId(initialPayment.getPaymentId());
+            completeTransactionWithTypeAndKey.setTransactionExternalKey(authPaymentTransaction.getTransactionExternalKey());
+            final Payment completedPaymentByTypeAndKey = killBillClient.completePayment(completeTransactionWithTypeAndKey, pluginProperties, createdBy, reason, comment);
+            verifyPayment(account, paymentMethodId, completedPaymentByTypeAndKey, paymentExternalKey, authTransactionExternalKey, transactionType.toString(), pending, amount, authAmount, BigDecimal.ZERO, BigDecimal.ZERO, 1, paymentNb);
+
+            // Finally, specify the payment id and transaction id
+            final PaymentTransaction completeTransactionWithTypeAndId = new PaymentTransaction();
+            completeTransactionWithTypeAndId.setPaymentId(initialPayment.getPaymentId());
+            completeTransactionWithTypeAndId.setTransactionId(authPaymentTransaction.getTransactionId());
+            final Payment completedPaymentByTypeAndId = killBillClient.completePayment(completeTransactionWithTypeAndId, pluginProperties, createdBy, reason, comment);
+            verifyPayment(account, paymentMethodId, completedPaymentByTypeAndId, paymentExternalKey, authTransactionExternalKey, transactionType.toString(), pending, amount, authAmount, BigDecimal.ZERO, BigDecimal.ZERO, 1, paymentNb);
+        }
+    }
+
+    @Test(groups = "slow")
+    public void testCompletionForSubsequentTransaction() throws Exception {
+        final Account account = createAccountWithDefaultPaymentMethod();
+        final UUID paymentMethodId = account.getPaymentMethodId();
+        final String paymentExternalKey = UUID.randomUUID().toString();
+        final String purchaseTransactionExternalKey = UUID.randomUUID().toString();
+        final BigDecimal purchaseAmount = BigDecimal.TEN;
+
+        // Create a successful purchase
+        final Payment authPayment = createVerifyTransaction(account, paymentMethodId, paymentExternalKey, purchaseTransactionExternalKey, TransactionType.PURCHASE,
+                                                            "SUCCESS", purchaseAmount, BigDecimal.ZERO, ImmutableMap.<String, String>of(), 1);
+
+        final String pending = PaymentPluginStatus.PENDING.toString();
+        final ImmutableMap<String, String> pluginProperties = ImmutableMap.<String, String>of(MockPaymentProviderPlugin.PLUGIN_PROPERTY_PAYMENT_PLUGIN_STATUS_OVERRIDE, pending);
+
+        // Trigger a pending refund
+        final String refundTransactionExternalKey = UUID.randomUUID().toString();
+        final PaymentTransaction refundTransaction = new PaymentTransaction();
+        refundTransaction.setPaymentId(authPayment.getPaymentId());
+        refundTransaction.setTransactionExternalKey(refundTransactionExternalKey);
+        refundTransaction.setAmount(purchaseAmount);
+        refundTransaction.setCurrency(authPayment.getCurrency());
+        final Payment refundPayment = killBillClient.refundPayment(refundTransaction, pluginProperties, createdBy, reason, comment);
+        verifyPaymentWithPendingRefund(account, paymentMethodId, paymentExternalKey, purchaseTransactionExternalKey, purchaseAmount, refundTransactionExternalKey, refundPayment);
+
+        // We cannot complete using just the payment id as JAX-RS doesn't know which transaction to complete
+        try {
+            final PaymentTransaction completeTransactionByPaymentId = new PaymentTransaction();
+            completeTransactionByPaymentId.setPaymentId(refundPayment.getPaymentId());
+            killBillClient.completePayment(completeTransactionByPaymentId, pluginProperties, createdBy, reason, comment);
+            Assert.fail();
+        } catch (final KillBillClientException e) {
+            Assert.assertEquals(e.getMessage(), "PaymentTransactionJson transactionType and externalKey need to be set");
+        }
+
+        // We cannot complete using just the payment external key as JAX-RS doesn't know which transaction to complete
+        try {
+            final PaymentTransaction completeTransactionByPaymentExternalKey = new PaymentTransaction();
+            completeTransactionByPaymentExternalKey.setPaymentExternalKey(refundPayment.getPaymentExternalKey());
+            killBillClient.completePayment(completeTransactionByPaymentExternalKey, pluginProperties, createdBy, reason, comment);
+            Assert.fail();
+        } catch (final KillBillClientException e) {
+            Assert.assertEquals(e.getMessage(), "PaymentTransactionJson transactionType and externalKey need to be set");
+        }
+
+        // Finally, it should work if we specify the payment id and transaction external key
+        final PaymentTransaction completeTransactionWithTypeAndKey = new PaymentTransaction();
+        completeTransactionWithTypeAndKey.setPaymentId(refundPayment.getPaymentId());
+        completeTransactionWithTypeAndKey.setTransactionExternalKey(refundTransactionExternalKey);
+        final Payment completedPaymentByTypeAndKey = killBillClient.completePayment(completeTransactionWithTypeAndKey, pluginProperties, createdBy, reason, comment);
+        verifyPaymentWithPendingRefund(account, paymentMethodId, paymentExternalKey, purchaseTransactionExternalKey, purchaseAmount, refundTransactionExternalKey, completedPaymentByTypeAndKey);
+
+        // Also, it should work if we specify the payment id and transaction id
+        final PaymentTransaction completeTransactionWithTypeAndId = new PaymentTransaction();
+        completeTransactionWithTypeAndId.setPaymentId(refundPayment.getPaymentId());
+        completeTransactionWithTypeAndId.setTransactionId(refundPayment.getTransactions().get(1).getTransactionId());
+        final Payment completedPaymentByTypeAndId = killBillClient.completePayment(completeTransactionWithTypeAndId, pluginProperties, createdBy, reason, comment);
+        verifyPaymentWithPendingRefund(account, paymentMethodId, paymentExternalKey, purchaseTransactionExternalKey, purchaseAmount, refundTransactionExternalKey, completedPaymentByTypeAndId);
+    }
+
+    @Test(groups = "slow")
     public void testComboAuthorization() throws Exception {
         final Account accountJson = getAccount();
         accountJson.setAccountId(null);
@@ -81,14 +190,15 @@ public class TestPayment extends TestJaxrsBase {
         final String voidTransactionExternalKey = UUID.randomUUID().toString();
         final Payment voidPayment = killBillClient.voidPayment(null, paymentExternalKey, voidTransactionExternalKey, ImmutableMap.<String, String>of(), createdBy, reason, comment);
         verifyPaymentTransaction(accountJson, voidPayment.getPaymentId(), paymentExternalKey, voidPayment.getTransactions().get(1),
-                                 voidTransactionExternalKey, null, "VOID");
+                                 voidTransactionExternalKey, null, "VOID", "SUCCESS");
     }
 
     private void testCreateRetrievePayment(final Account account, @Nullable final UUID paymentMethodId,
                                            final String paymentExternalKey, final int paymentNb) throws Exception {
         // Authorization
         final String authTransactionExternalKey = UUID.randomUUID().toString();
-        final Payment authPayment = createVerifyTransaction(account, paymentMethodId, paymentExternalKey, authTransactionExternalKey, TransactionType.AUTHORIZE, ImmutableMap.<String, String>of(), paymentNb);
+        final Payment authPayment = createVerifyTransaction(account, paymentMethodId, paymentExternalKey, authTransactionExternalKey, TransactionType.AUTHORIZE,
+                                                            "SUCCESS", BigDecimal.TEN, BigDecimal.TEN, ImmutableMap.<String, String>of(), paymentNb);
 
         // Capture 1
         final String capture1TransactionExternalKey = UUID.randomUUID().toString();
@@ -100,10 +210,10 @@ public class TestPayment extends TestJaxrsBase {
         captureTransaction.setTransactionExternalKey(capture1TransactionExternalKey);
         // captureAuthorization is using paymentId
         final Payment capturedPayment1 = killBillClient.captureAuthorization(captureTransaction, createdBy, reason, comment);
-        verifyPayment(account, paymentMethodId, capturedPayment1, paymentExternalKey, authTransactionExternalKey,
-                      BigDecimal.TEN, BigDecimal.ONE, BigDecimal.ZERO, 2, paymentNb);
+        verifyPayment(account, paymentMethodId, capturedPayment1, paymentExternalKey, authTransactionExternalKey, "AUTHORIZE", "SUCCESS",
+                      BigDecimal.TEN, BigDecimal.TEN, BigDecimal.ONE, BigDecimal.ZERO, 2, paymentNb);
         verifyPaymentTransaction(account, authPayment.getPaymentId(), paymentExternalKey, capturedPayment1.getTransactions().get(1),
-                                 capture1TransactionExternalKey, captureTransaction.getAmount(), "CAPTURE");
+                                 capture1TransactionExternalKey, captureTransaction.getAmount(), "CAPTURE", "SUCCESS");
 
         // Capture 2
         final String capture2TransactionExternalKey = UUID.randomUUID().toString();
@@ -111,10 +221,10 @@ public class TestPayment extends TestJaxrsBase {
         // captureAuthorization is using externalKey
         captureTransaction.setPaymentId(null);
         final Payment capturedPayment2 = killBillClient.captureAuthorization(captureTransaction, createdBy, reason, comment);
-        verifyPayment(account, paymentMethodId, capturedPayment2, paymentExternalKey, authTransactionExternalKey,
-                      BigDecimal.TEN, new BigDecimal("2"), BigDecimal.ZERO, 3, paymentNb);
+        verifyPayment(account, paymentMethodId, capturedPayment2, paymentExternalKey, authTransactionExternalKey, "AUTHORIZE", "SUCCESS",
+                      BigDecimal.TEN, BigDecimal.TEN, new BigDecimal("2"), BigDecimal.ZERO, 3, paymentNb);
         verifyPaymentTransaction(account, authPayment.getPaymentId(), paymentExternalKey, capturedPayment2.getTransactions().get(2),
-                                 capture2TransactionExternalKey, captureTransaction.getAmount(), "CAPTURE");
+                                 capture2TransactionExternalKey, captureTransaction.getAmount(), "CAPTURE", "SUCCESS");
 
         // Refund
         final String refundTransactionExternalKey = UUID.randomUUID().toString();
@@ -125,10 +235,10 @@ public class TestPayment extends TestJaxrsBase {
         refundTransaction.setPaymentExternalKey(paymentExternalKey);
         refundTransaction.setTransactionExternalKey(refundTransactionExternalKey);
         final Payment refundPayment = killBillClient.refundPayment(refundTransaction, createdBy, reason, comment);
-        verifyPayment(account, paymentMethodId, refundPayment, paymentExternalKey, authTransactionExternalKey,
-                      BigDecimal.TEN, new BigDecimal("2"), new BigDecimal("2"), 4, paymentNb);
+        verifyPayment(account, paymentMethodId, refundPayment, paymentExternalKey, authTransactionExternalKey, "AUTHORIZE", "SUCCESS",
+                      BigDecimal.TEN, BigDecimal.TEN, new BigDecimal("2"), new BigDecimal("2"), 4, paymentNb);
         verifyPaymentTransaction(account, authPayment.getPaymentId(), paymentExternalKey, refundPayment.getTransactions().get(3),
-                                 refundTransactionExternalKey, refundTransaction.getAmount(), "REFUND");
+                                 refundTransactionExternalKey, refundTransaction.getAmount(), "REFUND", "SUCCESS");
     }
 
     private Payment createVerifyTransaction(final Account account,
@@ -136,17 +246,20 @@ public class TestPayment extends TestJaxrsBase {
                                             final String paymentExternalKey,
                                             final String transactionExternalKey,
                                             final TransactionType transactionType,
+                                            final String transactionStatus,
+                                            final BigDecimal transactionAmount,
+                                            final BigDecimal authAmount,
                                             final Map<String, String> pluginProperties,
                                             final int paymentNb) throws KillBillClientException {
         final PaymentTransaction authTransaction = new PaymentTransaction();
-        authTransaction.setAmount(BigDecimal.TEN);
+        authTransaction.setAmount(transactionAmount);
         authTransaction.setCurrency(account.getCurrency());
         authTransaction.setPaymentExternalKey(paymentExternalKey);
         authTransaction.setTransactionExternalKey(transactionExternalKey);
         authTransaction.setTransactionType(transactionType.toString());
         final Payment payment = killBillClient.createPayment(account.getAccountId(), paymentMethodId, authTransaction, pluginProperties, createdBy, reason, comment);
 
-        verifyPaymentNoTransaction(account, paymentMethodId, payment, paymentExternalKey, BigDecimal.TEN, BigDecimal.ZERO, BigDecimal.ZERO, 1, paymentNb);
+        verifyPayment(account, paymentMethodId, payment, paymentExternalKey, transactionExternalKey, transactionType.toString(), transactionStatus, transactionAmount, authAmount, BigDecimal.ZERO, BigDecimal.ZERO, 1, paymentNb);
 
         return payment;
     }
@@ -174,14 +287,17 @@ public class TestPayment extends TestJaxrsBase {
                                @Nullable final UUID paymentMethodId,
                                final Payment payment,
                                final String paymentExternalKey,
-                               final String authTransactionExternalKey,
-                               final BigDecimal authAmount,
+                               final String firstTransactionExternalKey,
+                               final String firstTransactionType,
+                               final String firstTransactionStatus,
+                               final BigDecimal firstTransactionAmount,
+                               final BigDecimal paymentAuthAmount,
                                final BigDecimal capturedAmount,
                                final BigDecimal refundedAmount,
                                final int nbTransactions,
                                final int paymentNb) throws KillBillClientException {
-        verifyPaymentNoTransaction(account, paymentMethodId, payment, paymentExternalKey, authAmount, capturedAmount, refundedAmount, nbTransactions, paymentNb);
-        verifyPaymentTransaction(account, payment.getPaymentId(), paymentExternalKey, payment.getTransactions().get(0), authTransactionExternalKey, authAmount, "AUTHORIZE");
+        verifyPaymentNoTransaction(account, paymentMethodId, payment, paymentExternalKey, paymentAuthAmount, capturedAmount, refundedAmount, nbTransactions, paymentNb);
+        verifyPaymentTransaction(account, payment.getPaymentId(), paymentExternalKey, payment.getTransactions().get(0), firstTransactionExternalKey, firstTransactionAmount, firstTransactionType, firstTransactionStatus);
     }
 
     private void verifyPaymentNoTransaction(final Account account,
@@ -222,11 +338,12 @@ public class TestPayment extends TestJaxrsBase {
                                           final PaymentTransaction paymentTransaction,
                                           final String transactionExternalKey,
                                           @Nullable final BigDecimal amount,
-                                          final String transactionType) {
+                                          final String transactionType,
+                                          final String transactionStatus) {
         Assert.assertEquals(paymentTransaction.getPaymentId(), paymentId);
         Assert.assertNotNull(paymentTransaction.getTransactionId());
         Assert.assertEquals(paymentTransaction.getTransactionType(), transactionType);
-        Assert.assertEquals(paymentTransaction.getStatus(), "SUCCESS");
+        Assert.assertEquals(paymentTransaction.getStatus(), transactionStatus);
         if (amount == null) {
             Assert.assertNull(paymentTransaction.getAmount());
             Assert.assertNull(paymentTransaction.getCurrency());
@@ -237,4 +354,9 @@ public class TestPayment extends TestJaxrsBase {
         Assert.assertEquals(paymentTransaction.getTransactionExternalKey(), transactionExternalKey);
         Assert.assertEquals(paymentTransaction.getPaymentExternalKey(), paymentExternalKey);
     }
+
+    private void verifyPaymentWithPendingRefund(final Account account, final UUID paymentMethodId, final String paymentExternalKey, final String authTransactionExternalKey, final BigDecimal purchaseAmount, final String refundTransactionExternalKey, final Payment refundPayment) throws KillBillClientException {
+        verifyPayment(account, paymentMethodId, refundPayment, paymentExternalKey, authTransactionExternalKey, "PURCHASE", "SUCCESS", purchaseAmount, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, 2, 1);
+        verifyPaymentTransaction(account, refundPayment.getPaymentId(), paymentExternalKey, refundPayment.getTransactions().get(1), refundTransactionExternalKey, purchaseAmount, "REFUND", "PENDING");
+    }
 }