killbill-uncached

Introduce a new PaymentTransactionInfoPluginConverter

6/11/2015 11:38:52 PM

Details

diff --git a/payment/src/main/java/org/killbill/billing/payment/core/janitor/ErroredPaymentTask.java b/payment/src/main/java/org/killbill/billing/payment/core/janitor/ErroredPaymentTask.java
index 7b376ae..596323f 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/janitor/ErroredPaymentTask.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/janitor/ErroredPaymentTask.java
@@ -30,6 +30,7 @@ import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.osgi.api.OSGIServiceRegistration;
 import org.killbill.billing.payment.api.PluginProperty;
 import org.killbill.billing.payment.api.TransactionStatus;
+import org.killbill.billing.payment.core.PaymentTransactionInfoPluginConverter;
 import org.killbill.billing.payment.core.sm.payments.PaymentEnteringStateCallback;
 import org.killbill.billing.payment.core.sm.PaymentStateMachineHelper;
 import org.killbill.billing.payment.core.sm.PluginRoutingPaymentAutomatonRunner;
@@ -114,7 +115,7 @@ public class ErroredPaymentTask extends CompletionTaskBase<PaymentModelDao> {
         }
 
         // Compute new transactionStatus based on pluginInfo state; and if that did not change, bail early.
-        final TransactionStatus transactionStatus = PaymentEnteringStateCallback.paymentPluginStatusToTransactionStatus(pluginErroredTransaction);
+        final TransactionStatus transactionStatus = PaymentTransactionInfoPluginConverter.toTransactionStatus(pluginErroredTransaction);
         if (transactionStatus == unknownTransaction.getTransactionStatus()) {
             return;
         }
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PaymentTransactionInfoPluginConverter.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentTransactionInfoPluginConverter.java
new file mode 100644
index 0000000..d60d540
--- /dev/null
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentTransactionInfoPluginConverter.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.payment.core;
+
+import javax.annotation.Nullable;
+
+import org.killbill.automaton.OperationResult;
+import org.killbill.billing.payment.api.TransactionStatus;
+import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+
+//
+// Conversion between the plugin result to the payment state and transaction status
+//
+public class PaymentTransactionInfoPluginConverter {
+
+    public static TransactionStatus toTransactionStatus(@Nullable final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin) {
+        //
+        // paymentTransactionInfoPlugin when we got an exception from the plugin, or if the plugin behaves badly
+        // and decides to return null; in all cases this is seen as a PLUGIN_FAILURE
+        //
+        if (paymentTransactionInfoPlugin == null || paymentTransactionInfoPlugin.getStatus() == null) {
+            return TransactionStatus.PLUGIN_FAILURE;
+        }
+
+        switch (paymentTransactionInfoPlugin.getStatus()) {
+            case PROCESSED:
+                return TransactionStatus.SUCCESS;
+            case PENDING:
+                return TransactionStatus.PENDING;
+            case ERROR:
+                return TransactionStatus.PAYMENT_FAILURE;
+            // This will be picked up by Janitor to figure out what really happened and correct the state if needed
+            case UNDEFINED:
+            default:
+                return TransactionStatus.UNKNOWN;
+        }
+    }
+
+    public static OperationResult toOperationResult(@Nullable final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin) {
+        if (paymentTransactionInfoPlugin == null || paymentTransactionInfoPlugin.getStatus() == null) {
+            return OperationResult.EXCEPTION;
+        }
+
+        switch (paymentTransactionInfoPlugin.getStatus()) {
+            case PROCESSED:
+                return OperationResult.SUCCESS;
+            case PENDING:
+                return OperationResult.PENDING;
+            case ERROR:
+                return OperationResult.FAILURE;
+            // Might change later if Janitor fixes the state
+            case UNDEFINED:
+            default:
+                return OperationResult.EXCEPTION;
+        }
+    }
+}
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 0ec8b99..8db48a9 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
@@ -101,7 +101,7 @@ public class PaymentAutomatonDAOHelper {
         paymentStateContext.setOnLeavingStateExistingTransactions(existingTransactions);
     }
 
-    public void processPaymentInfoPlugin(final TransactionStatus paymentStatus, @Nullable final PaymentTransactionInfoPlugin paymentInfoPlugin,
+    public void processPaymentInfoPlugin(final TransactionStatus transactionStatus, @Nullable final PaymentTransactionInfoPlugin paymentInfoPlugin,
                                          final String currentPaymentStateName) {
         final BigDecimal processedAmount = paymentInfoPlugin == null ? null : paymentInfoPlugin.getAmount();
         final Currency processedCurrency = paymentInfoPlugin == null ? null : paymentInfoPlugin.getCurrency();
@@ -115,7 +115,7 @@ public class PaymentAutomatonDAOHelper {
                                                            currentPaymentStateName,
                                                            lastSuccessPaymentState,
                                                            paymentStateContext.getPaymentTransactionModelDao().getId(),
-                                                           paymentStatus,
+                                                           transactionStatus,
                                                            processedAmount,
                                                            processedCurrency,
                                                            gatewayErrorCode,
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentEnteringStateCallback.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentEnteringStateCallback.java
index f61ef7c..5b340aa 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentEnteringStateCallback.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentEnteringStateCallback.java
@@ -28,6 +28,7 @@ import org.killbill.billing.events.BusInternalEvent;
 import org.killbill.billing.payment.api.DefaultPaymentErrorEvent;
 import org.killbill.billing.payment.api.PaymentApiException;
 import org.killbill.billing.payment.api.TransactionStatus;
+import org.killbill.billing.payment.core.PaymentTransactionInfoPluginConverter;
 import org.killbill.billing.payment.core.sm.PaymentAutomatonDAOHelper;
 import org.killbill.billing.payment.core.sm.PaymentStateContext;
 import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
@@ -53,8 +54,8 @@ public abstract class PaymentEnteringStateCallback implements EnteringStateCallb
 
         // If the transaction was not created -- for instance we had an exception in leavingState callback then we bail; if not, then update state:
         if (paymentStateContext.getPaymentTransactionModelDao() != null && paymentStateContext.getPaymentTransactionModelDao().getId() != null) {
-            final PaymentTransactionInfoPlugin paymentInfoPlugin = paymentStateContext.getPaymentInfoPlugin();
-            final TransactionStatus transactionStatus = paymentPluginStatusToTransactionStatus(paymentInfoPlugin);
+            final PaymentTransactionInfoPlugin paymentInfoPlugin = paymentStateContext.getPaymentTransactionInfoPlugin();
+            final TransactionStatus transactionStatus = PaymentTransactionInfoPluginConverter.toTransactionStatus(paymentInfoPlugin);
             // The bus event will be posted from the transaction
             daoHelper.processPaymentInfoPlugin(transactionStatus, paymentInfoPlugin, newState.getName());
         } else if (!paymentStateContext.isApiPayment()) {
@@ -76,30 +77,4 @@ public abstract class PaymentEnteringStateCallback implements EnteringStateCallb
             }
         }
     }
-
-    public static TransactionStatus paymentPluginStatusToTransactionStatus(@Nullable final PaymentTransactionInfoPlugin paymentInfoPlugin) {
-
-        //
-        // paymentInfoPlugin when we got an exception from the plugin, or if the plugin behaves badly
-        // and decides to return null; in all cases this is seen as a PLUGIN_FAILURE
-        //
-        if (paymentInfoPlugin == null || paymentInfoPlugin.getStatus() == null) {
-            return TransactionStatus.PLUGIN_FAILURE;
-        }
-
-        //
-        // The plugin returned a status or it timedout and we added manually a UNKNOWN status to end up here
-        //
-        switch (paymentInfoPlugin.getStatus()) {
-            case PROCESSED:
-                return TransactionStatus.SUCCESS;
-            case PENDING:
-                return TransactionStatus.PENDING;
-            case ERROR:
-                return TransactionStatus.PAYMENT_FAILURE;
-            case UNDEFINED:
-            default:
-                return TransactionStatus.UNKNOWN;
-        }
-    }
 }
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java
index 70c2159..d072424 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/payments/PaymentOperation.java
@@ -29,6 +29,7 @@ import org.killbill.billing.ErrorCode;
 import org.killbill.billing.payment.api.PaymentApiException;
 import org.killbill.billing.payment.api.TransactionStatus;
 import org.killbill.billing.payment.api.TransactionType;
+import org.killbill.billing.payment.core.PaymentTransactionInfoPluginConverter;
 import org.killbill.billing.payment.core.ProcessorBase.WithAccountLockCallback;
 import org.killbill.billing.payment.core.sm.OperationCallbackBase;
 import org.killbill.billing.payment.core.sm.PaymentAutomatonDAOHelper;
@@ -108,7 +109,7 @@ public abstract class PaymentOperation extends OperationCallbackBase<PaymentTran
                                                                                                 PaymentPluginStatus.UNDEFINED,
                                                                                                 null);
 
-        paymentStateContext.setPaymentInfoPlugin(paymentInfoPlugin);
+        paymentStateContext.setPaymentTransactionInfoPlugin(paymentInfoPlugin);
         return new OperationException(e, OperationResult.EXCEPTION);
     }
 
@@ -173,8 +174,8 @@ public abstract class PaymentOperation extends OperationCallbackBase<PaymentTran
                 // Throws if plugin is  ot correctly implemented (e.g returns null result, values,..)
                 sanityOnPaymentInfoPlugin(paymentInfoPlugin);
 
-                paymentStateContext.setPaymentInfoPlugin(paymentInfoPlugin);
-                return processPaymentInfoPlugin();
+                paymentStateContext.setPaymentTransactionInfoPlugin(paymentInfoPlugin);
+                return PaymentTransactionInfoPluginConverter.toOperationResult(paymentStateContext.getPaymentTransactionInfoPlugin());
             } else {
                 final PaymentTransactionInfoPlugin paymentInfoPlugin = new DefaultNoOpPaymentInfoPlugin(paymentStateContext.getPaymentId(),
                                                                                                         paymentStateContext.getTransactionId(),
@@ -185,7 +186,7 @@ public abstract class PaymentOperation extends OperationCallbackBase<PaymentTran
                                                                                                         paymentStateContext.getPaymentTransactionModelDao().getCreatedDate(),
                                                                                                         buildPaymentPluginStatusFromOperationResult(paymentStateContext.getOverridePluginOperationResult()),
                                                                                                         null);
-                paymentStateContext.setPaymentInfoPlugin(paymentInfoPlugin);
+                paymentStateContext.setPaymentTransactionInfoPlugin(paymentInfoPlugin);
                 return paymentStateContext.getOverridePluginOperationResult();
             }
         } catch (final PaymentPluginApiException e) {
@@ -207,37 +208,19 @@ public abstract class PaymentOperation extends OperationCallbackBase<PaymentTran
         }
     }
 
-    private OperationResult processPaymentInfoPlugin() {
-        if (paymentStateContext.getPaymentInfoPlugin() == null || paymentStateContext.getPaymentInfoPlugin().getStatus() == null) {
-            return OperationResult.EXCEPTION;
-        }
-
-        switch (paymentStateContext.getPaymentInfoPlugin().getStatus()) {
-            case PROCESSED:
-                return OperationResult.SUCCESS;
-            case PENDING:
-                return OperationResult.PENDING;
-            case ERROR:
-                return OperationResult.FAILURE;
-            case UNDEFINED:
-            default:
-                return OperationResult.EXCEPTION;
-        }
-    }
-
     private void sanityOnPaymentInfoPlugin(final PaymentTransactionInfoPlugin paymentInfoPlugin) throws PaymentApiException {
         if (paymentInfoPlugin == null) {
             throw new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_EXCEPTION, "Payment plugin returned a null result");
         }
         /*
         TODO this breaks our tests so test would have to be fixed
-        if (paymentInfoPlugin.getKbTransactionPaymentId() == null || !paymentInfoPlugin.getKbTransactionPaymentId().equals(paymentStateContext.getTransactionId())) {
+        if (paymentTransactionInfoPlugin.getKbTransactionPaymentId() == null || !paymentTransactionInfoPlugin.getKbTransactionPaymentId().equals(paymentStateContext.getTransactionId())) {
             throw new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_EXCEPTION, "Payment plugin returned invalid kbTransactionId");
         }
-        if (paymentInfoPlugin.getKbPaymentId() == null || !paymentInfoPlugin.getKbPaymentId().equals(paymentStateContext.getPaymentId())) {
+        if (paymentTransactionInfoPlugin.getKbPaymentId() == null || !paymentTransactionInfoPlugin.getKbPaymentId().equals(paymentStateContext.getPaymentId())) {
             throw new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_EXCEPTION, "Payment plugin returned invalid kbPaymentId");
         }
-        if (paymentInfoPlugin.getTransactionType() == null || !paymentInfoPlugin.getKbPaymentId().equals(paymentStateContext.getTransactionType())) {
+        if (paymentTransactionInfoPlugin.getTransactionType() == null || !paymentTransactionInfoPlugin.getKbPaymentId().equals(paymentStateContext.getTransactionType())) {
             throw new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_EXCEPTION, "Payment plugin returned invalid transaction type");
         }
         */
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 49b1c11..034fbc4 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
@@ -44,7 +44,7 @@ public class PaymentStateContext {
     // Stateful objects created by the callbacks and passed to the other following callbacks in the automaton
     protected List<PaymentTransactionModelDao> onLeavingStateExistingTransactions;
     protected PaymentTransactionModelDao paymentTransactionModelDao;
-    protected PaymentTransactionInfoPlugin paymentInfoPlugin;
+    protected PaymentTransactionInfoPlugin paymentTransactionInfoPlugin;
     protected BigDecimal amount;
     protected String paymentExternalKey;
     protected String paymentTransactionExternalKey;
@@ -120,12 +120,12 @@ public class PaymentStateContext {
         this.onLeavingStateExistingTransactions = onLeavingStateExistingTransactions;
     }
 
-    public PaymentTransactionInfoPlugin getPaymentInfoPlugin() {
-        return paymentInfoPlugin;
+    public PaymentTransactionInfoPlugin getPaymentTransactionInfoPlugin() {
+        return paymentTransactionInfoPlugin;
     }
 
-    public void setPaymentInfoPlugin(final PaymentTransactionInfoPlugin paymentInfoPlugin) {
-        this.paymentInfoPlugin = paymentInfoPlugin;
+    public void setPaymentTransactionInfoPlugin(final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin) {
+        this.paymentTransactionInfoPlugin = paymentTransactionInfoPlugin;
     }
 
     public UUID getPaymentId() {
diff --git a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentEnteringStateCallback.java b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentEnteringStateCallback.java
index 806c7a8..c4f53e6 100644
--- a/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentEnteringStateCallback.java
+++ b/payment/src/test/java/org/killbill/billing/payment/core/sm/TestPaymentEnteringStateCallback.java
@@ -89,7 +89,7 @@ public class TestPaymentEnteringStateCallback extends PaymentTestSuiteWithEmbedd
         Mockito.when(paymentInfoPlugin.getStatus()).thenReturn(PaymentPluginStatus.PENDING);
         Mockito.when(paymentInfoPlugin.getGatewayErrorCode()).thenReturn(UUID.randomUUID().toString().substring(0, 5));
         Mockito.when(paymentInfoPlugin.getGatewayError()).thenReturn(UUID.randomUUID().toString());
-        paymentStateContext.setPaymentInfoPlugin(paymentInfoPlugin);
+        paymentStateContext.setPaymentTransactionInfoPlugin(paymentInfoPlugin);
 
         // Process the plugin result
         callback.enteringState(state, operationCallback, operationResult, leavingStateCallback);
@@ -109,7 +109,7 @@ public class TestPaymentEnteringStateCallback extends PaymentTestSuiteWithEmbedd
     public void testEnterStateWithOperationException() throws Exception {
         daoHelper.createNewPaymentTransaction();
         // Simulate a bug in the plugin - i.e. nothing was returned
-        paymentStateContext.setPaymentInfoPlugin(null);
+        paymentStateContext.setPaymentTransactionInfoPlugin(null);
         operationResult = OperationResult.EXCEPTION;
 
         callback.enteringState(state, operationCallback, operationResult, leavingStateCallback);
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 2e617f1..9f6eb58 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
@@ -56,18 +56,18 @@ public class TestPaymentOperation extends PaymentTestSuiteNoDB {
     public void testPaymentFailure() throws Exception {
         setUp(PaymentPluginStatus.ERROR);
 
-        Assert.assertNull(paymentStateContext.getPaymentInfoPlugin());
+        Assert.assertNull(paymentStateContext.getPaymentTransactionInfoPlugin());
 
         Assert.assertEquals(paymentOperation.doOperationCallback(), OperationResult.FAILURE);
 
-        Assert.assertNotNull(paymentStateContext.getPaymentInfoPlugin());
+        Assert.assertNotNull(paymentStateContext.getPaymentTransactionInfoPlugin());
     }
 
     @Test(groups = "fast")
     public void testPluginFailure() throws Exception {
         setUp(null);
 
-        Assert.assertNull(paymentStateContext.getPaymentInfoPlugin());
+        Assert.assertNull(paymentStateContext.getPaymentTransactionInfoPlugin());
 
         try {
             paymentOperation.doOperationCallback();
@@ -76,29 +76,29 @@ public class TestPaymentOperation extends PaymentTestSuiteNoDB {
             Assert.assertEquals(e.getOperationResult(), OperationResult.EXCEPTION);
         }
 
-        Assert.assertNull(paymentStateContext.getPaymentInfoPlugin());
+        Assert.assertNull(paymentStateContext.getPaymentTransactionInfoPlugin());
     }
 
     @Test(groups = "fast")
     public void testPaymentPending() throws Exception {
         setUp(PaymentPluginStatus.PENDING);
 
-        Assert.assertNull(paymentStateContext.getPaymentInfoPlugin());
+        Assert.assertNull(paymentStateContext.getPaymentTransactionInfoPlugin());
 
         Assert.assertEquals(paymentOperation.doOperationCallback(), OperationResult.PENDING);
 
-        Assert.assertNotNull(paymentStateContext.getPaymentInfoPlugin());
+        Assert.assertNotNull(paymentStateContext.getPaymentTransactionInfoPlugin());
     }
 
     @Test(groups = "fast")
     public void testPaymentSuccess() throws Exception {
         setUp(PaymentPluginStatus.PROCESSED);
 
-        Assert.assertNull(paymentStateContext.getPaymentInfoPlugin());
+        Assert.assertNull(paymentStateContext.getPaymentTransactionInfoPlugin());
 
         Assert.assertEquals(paymentOperation.doOperationCallback(), OperationResult.SUCCESS);
 
-        Assert.assertNotNull(paymentStateContext.getPaymentInfoPlugin());
+        Assert.assertNotNull(paymentStateContext.getPaymentTransactionInfoPlugin());
     }
 
     private void setUp(final PaymentPluginStatus paymentPluginStatus) throws Exception {