killbill-uncached
payment: make transactionStatus Nullable in AdminPaymentApi#fixPaymentTransactionState This …
6/24/2016 10:54:06 PM
Changes
Details
diff --git a/payment/src/main/java/org/killbill/billing/payment/api/DefaultAdminPaymentApi.java b/payment/src/main/java/org/killbill/billing/payment/api/DefaultAdminPaymentApi.java
index 6b02b9b..2e654e5 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/DefaultAdminPaymentApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/DefaultAdminPaymentApi.java
@@ -21,17 +21,20 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
import org.killbill.billing.callcontext.InternalCallContext;
+import org.killbill.billing.payment.core.PaymentTransactionInfoPluginConverter;
import org.killbill.billing.payment.dao.PaymentDao;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
+import org.killbill.billing.util.config.PaymentConfig;
-public class DefaultAdminPaymentApi implements AdminPaymentApi {
+public class DefaultAdminPaymentApi extends DefaultApiBase implements AdminPaymentApi {
private final PaymentDao paymentDao;
private final InternalCallContextFactory internalCallContextFactory;
@Inject
- public DefaultAdminPaymentApi(final PaymentDao paymentDao, final InternalCallContextFactory internalCallContextFactory) {
+ public DefaultAdminPaymentApi(final PaymentConfig paymentConfig, final PaymentDao paymentDao, final InternalCallContextFactory internalCallContextFactory) {
+ super(paymentConfig);
this.paymentDao = paymentDao;
this.internalCallContextFactory = internalCallContextFactory;
}
@@ -39,12 +42,21 @@ public class DefaultAdminPaymentApi implements AdminPaymentApi {
@Override
public void fixPaymentTransactionState(final Payment payment,
final PaymentTransaction paymentTransaction,
- final TransactionStatus transactionStatus,
+ @Nullable final TransactionStatus transactionStatusMaybeNull,
@Nullable final String lastSuccessPaymentState,
final String currentPaymentStateName,
final Iterable<PluginProperty> properties,
final CallContext callContext) throws PaymentApiException {
final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(payment.getAccountId(), callContext);
+
+ final TransactionStatus transactionStatus;
+ if (transactionStatusMaybeNull == null) {
+ checkNotNullParameter(paymentTransaction.getPaymentInfoPlugin(), "PaymentTransactionInfoPlugin");
+ transactionStatus = PaymentTransactionInfoPluginConverter.toTransactionStatus(paymentTransaction.getPaymentInfoPlugin());
+ } else {
+ transactionStatus = transactionStatusMaybeNull;
+ }
+
paymentDao.updatePaymentAndTransactionOnCompletion(payment.getAccountId(),
null,
payment.getId(),
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestDefaultAdminPaymentApi.java b/payment/src/test/java/org/killbill/billing/payment/api/TestDefaultAdminPaymentApi.java
new file mode 100644
index 0000000..03f6d8a
--- /dev/null
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestDefaultAdminPaymentApi.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2016 Groupon, Inc
+ * Copyright 2016 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.api;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.killbill.billing.ErrorCode;
+import org.killbill.billing.account.api.Account;
+import org.killbill.billing.catalog.api.Currency;
+import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
+import org.killbill.billing.osgi.api.OSGIServiceDescriptor;
+import org.killbill.billing.payment.PaymentTestSuiteWithEmbeddedDB;
+import org.killbill.billing.payment.dao.PaymentModelDao;
+import org.killbill.billing.payment.dao.PaymentTransactionModelDao;
+import org.killbill.billing.payment.plugin.api.PaymentPluginStatus;
+import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
+import org.killbill.billing.payment.provider.DefaultNoOpPaymentInfoPlugin;
+import org.killbill.billing.payment.provider.MockPaymentControlProviderPlugin;
+import org.killbill.billing.payment.provider.MockPaymentProviderPlugin;
+import org.mockito.Mockito;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestDefaultAdminPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
+
+ private MockPaymentProviderPlugin mockPaymentProviderPlugin;
+ private Account account;
+
+ @BeforeClass(groups = "slow")
+ protected void beforeClass() throws Exception {
+ super.beforeClass();
+ mockPaymentProviderPlugin = (MockPaymentProviderPlugin) registry.getServiceForName(MockPaymentProviderPlugin.PLUGIN_NAME);
+ }
+
+ @BeforeMethod(groups = "slow")
+ public void beforeMethod() throws Exception {
+ super.beforeMethod();
+
+ mockPaymentProviderPlugin.clear();
+ account = testHelper.createTestAccount("bobo@gmail.com", true);
+
+ final PaymentControlPluginApi mockPaymentControlProviderPlugin = new MockPaymentControlProviderPlugin();
+ controlPluginRegistry.registerService(new OSGIServiceDescriptor() {
+ @Override
+ public String getPluginSymbolicName() {
+ return null;
+ }
+
+ @Override
+ public String getPluginName() {
+ return MockPaymentControlProviderPlugin.PLUGIN_NAME;
+ }
+
+ @Override
+ public String getRegistrationName() {
+ return MockPaymentControlProviderPlugin.PLUGIN_NAME;
+ }
+ },
+ mockPaymentControlProviderPlugin);
+ }
+
+ @Test(groups = "slow")
+ public void testFixPaymentTransactionState() throws PaymentApiException {
+ final Payment payment = paymentApi.createAuthorization(account,
+ account.getPaymentMethodId(),
+ null,
+ BigDecimal.TEN,
+ Currency.EUR,
+ UUID.randomUUID().toString(),
+ UUID.randomUUID().toString(),
+ ImmutableList.<PluginProperty>of(),
+ callContext);
+
+ final PaymentModelDao paymentModelDao = paymentDao.getPayment(payment.getId(), internalCallContext);
+ final PaymentTransactionModelDao paymentTransactionModelDao = paymentDao.getPaymentTransaction(payment.getTransactions().get(0).getId(), internalCallContext);
+ Assert.assertEquals(paymentModelDao.getStateName(), "AUTH_SUCCESS");
+ Assert.assertEquals(paymentModelDao.getLastSuccessStateName(), "AUTH_SUCCESS");
+ Assert.assertEquals(paymentTransactionModelDao.getTransactionStatus(), TransactionStatus.SUCCESS);
+ Assert.assertEquals(paymentTransactionModelDao.getProcessedAmount().compareTo(BigDecimal.TEN), 0);
+ Assert.assertEquals(paymentTransactionModelDao.getProcessedCurrency(), Currency.EUR);
+ Assert.assertEquals(paymentTransactionModelDao.getGatewayErrorCode(), "");
+ Assert.assertEquals(paymentTransactionModelDao.getGatewayErrorMsg(), "");
+
+ adminPaymentApi.fixPaymentTransactionState(payment, payment.getTransactions().get(0), TransactionStatus.PAYMENT_FAILURE, null, "AUTH_ERRORED", ImmutableList.<PluginProperty>of(), callContext);
+
+ final PaymentModelDao refreshedPaymentModelDao = paymentDao.getPayment(payment.getId(), internalCallContext);
+ final PaymentTransactionModelDao refreshedPaymentTransactionModelDao = paymentDao.getPaymentTransaction(payment.getTransactions().get(0).getId(), internalCallContext);
+ Assert.assertEquals(refreshedPaymentModelDao.getStateName(), "AUTH_ERRORED");
+ // TODO Shouldn't we allow the user to override this too?
+ Assert.assertEquals(refreshedPaymentModelDao.getLastSuccessStateName(), "AUTH_SUCCESS");
+ Assert.assertEquals(refreshedPaymentTransactionModelDao.getTransactionStatus(), TransactionStatus.PAYMENT_FAILURE);
+ Assert.assertEquals(refreshedPaymentTransactionModelDao.getProcessedAmount().compareTo(BigDecimal.TEN), 0);
+ Assert.assertEquals(refreshedPaymentTransactionModelDao.getProcessedCurrency(), Currency.EUR);
+ Assert.assertEquals(refreshedPaymentTransactionModelDao.getGatewayErrorCode(), "");
+ Assert.assertEquals(refreshedPaymentTransactionModelDao.getGatewayErrorMsg(), "");
+ }
+
+ @Test(groups = "slow", description = "https://github.com/killbill/killbill/issues/551")
+ public void testFixPaymentTransactionStateNoPaymentTransactionInfoPlugin() throws PaymentApiException {
+ final Payment payment = paymentApi.createAuthorization(account,
+ account.getPaymentMethodId(),
+ null,
+ BigDecimal.TEN,
+ Currency.EUR,
+ UUID.randomUUID().toString(),
+ UUID.randomUUID().toString(),
+ ImmutableList.<PluginProperty>of(),
+ callContext);
+
+ final PaymentModelDao paymentModelDao = paymentDao.getPayment(payment.getId(), internalCallContext);
+ final PaymentTransactionModelDao paymentTransactionModelDao = paymentDao.getPaymentTransaction(payment.getTransactions().get(0).getId(), internalCallContext);
+ Assert.assertEquals(paymentModelDao.getStateName(), "AUTH_SUCCESS");
+ Assert.assertEquals(paymentModelDao.getLastSuccessStateName(), "AUTH_SUCCESS");
+ Assert.assertEquals(paymentTransactionModelDao.getTransactionStatus(), TransactionStatus.SUCCESS);
+ Assert.assertEquals(paymentTransactionModelDao.getProcessedAmount().compareTo(BigDecimal.TEN), 0);
+ Assert.assertEquals(paymentTransactionModelDao.getProcessedCurrency(), Currency.EUR);
+ Assert.assertEquals(paymentTransactionModelDao.getGatewayErrorCode(), "");
+ Assert.assertEquals(paymentTransactionModelDao.getGatewayErrorMsg(), "");
+
+ try {
+ // Since no transaction status is passed, PaymentTransactionInfoPlugin should be set
+ adminPaymentApi.fixPaymentTransactionState(payment, Mockito.mock(DefaultPaymentTransaction.class), null, null, "AUTH_ERRORED", ImmutableList.<PluginProperty>of(), callContext);
+ } catch (final PaymentApiException e) {
+ Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INVALID_PARAMETER.getCode());
+ }
+ }
+
+ @Test(groups = "slow", description = "https://github.com/killbill/killbill/issues/551")
+ public void testFixPaymentTransactionStateFromPaymentTransactionInfoPlugin() throws PaymentApiException {
+ final Payment payment = paymentApi.createAuthorization(account,
+ account.getPaymentMethodId(),
+ null,
+ BigDecimal.TEN,
+ Currency.EUR,
+ UUID.randomUUID().toString(),
+ UUID.randomUUID().toString(),
+ ImmutableList.<PluginProperty>of(),
+ callContext);
+
+ final PaymentModelDao paymentModelDao = paymentDao.getPayment(payment.getId(), internalCallContext);
+ final PaymentTransactionModelDao paymentTransactionModelDao = paymentDao.getPaymentTransaction(payment.getTransactions().get(0).getId(), internalCallContext);
+ Assert.assertEquals(paymentModelDao.getStateName(), "AUTH_SUCCESS");
+ Assert.assertEquals(paymentModelDao.getLastSuccessStateName(), "AUTH_SUCCESS");
+ Assert.assertEquals(paymentTransactionModelDao.getTransactionStatus(), TransactionStatus.SUCCESS);
+ Assert.assertEquals(paymentTransactionModelDao.getProcessedAmount().compareTo(BigDecimal.TEN), 0);
+ Assert.assertEquals(paymentTransactionModelDao.getProcessedCurrency(), Currency.EUR);
+ Assert.assertEquals(paymentTransactionModelDao.getGatewayErrorCode(), "");
+ Assert.assertEquals(paymentTransactionModelDao.getGatewayErrorMsg(), "");
+
+ final PaymentTransactionInfoPlugin infoPlugin = new DefaultNoOpPaymentInfoPlugin(paymentTransactionModelDao.getPaymentId(),
+ paymentTransactionModelDao.getId(),
+ paymentTransactionModelDao.getTransactionType(),
+ paymentTransactionModelDao.getAmount(),
+ paymentTransactionModelDao.getCurrency(),
+ paymentTransactionModelDao.getEffectiveDate(),
+ paymentTransactionModelDao.getCreatedDate(),
+ PaymentPluginStatus.ERROR,
+ "error-code",
+ "error-msg");
+ final PaymentTransaction newPaymentTransaction = new DefaultPaymentTransaction(paymentTransactionModelDao.getId(),
+ paymentTransactionModelDao.getAttemptId(),
+ paymentTransactionModelDao.getTransactionExternalKey(),
+ paymentTransactionModelDao.getCreatedDate(),
+ paymentTransactionModelDao.getUpdatedDate(),
+ paymentTransactionModelDao.getPaymentId(),
+ paymentTransactionModelDao.getTransactionType(),
+ paymentTransactionModelDao.getEffectiveDate(),
+ TransactionStatus.PAYMENT_FAILURE,
+ paymentTransactionModelDao.getAmount(),
+ paymentTransactionModelDao.getCurrency(),
+ paymentTransactionModelDao.getProcessedAmount(),
+ paymentTransactionModelDao.getProcessedCurrency(),
+ infoPlugin.getGatewayErrorCode(),
+ infoPlugin.getGatewayError(),
+ infoPlugin);
+ adminPaymentApi.fixPaymentTransactionState(payment, newPaymentTransaction, null, null, "AUTH_ERRORED", ImmutableList.<PluginProperty>of(), callContext);
+
+ final PaymentModelDao refreshedPaymentModelDao = paymentDao.getPayment(payment.getId(), internalCallContext);
+ final PaymentTransactionModelDao refreshedPaymentTransactionModelDao = paymentDao.getPaymentTransaction(payment.getTransactions().get(0).getId(), internalCallContext);
+ Assert.assertEquals(refreshedPaymentModelDao.getStateName(), "AUTH_ERRORED");
+ // TODO Shouldn't we allow the user to override this too?
+ Assert.assertEquals(refreshedPaymentModelDao.getLastSuccessStateName(), "AUTH_SUCCESS");
+ Assert.assertEquals(refreshedPaymentTransactionModelDao.getTransactionStatus(), TransactionStatus.PAYMENT_FAILURE);
+ Assert.assertEquals(refreshedPaymentTransactionModelDao.getProcessedAmount().compareTo(BigDecimal.TEN), 0);
+ Assert.assertEquals(refreshedPaymentTransactionModelDao.getProcessedCurrency(), Currency.EUR);
+ Assert.assertEquals(refreshedPaymentTransactionModelDao.getGatewayErrorCode(), "error-code");
+ Assert.assertEquals(refreshedPaymentTransactionModelDao.getGatewayErrorMsg(), "error-msg");
+ }
+}
diff --git a/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteWithEmbeddedDB.java b/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteWithEmbeddedDB.java
index 786dae5..0d21398 100644
--- a/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteWithEmbeddedDB.java
+++ b/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteWithEmbeddedDB.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014 Groupon, Inc
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2016 Groupon, Inc
+ * Copyright 2014-2016 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
@@ -23,6 +23,7 @@ import org.killbill.billing.account.api.AccountInternalApi;
import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
import org.killbill.billing.invoice.api.InvoiceInternalApi;
import org.killbill.billing.osgi.api.OSGIServiceRegistration;
+import org.killbill.billing.payment.api.AdminPaymentApi;
import org.killbill.billing.payment.api.PaymentApi;
import org.killbill.billing.payment.api.PaymentGatewayApi;
import org.killbill.billing.payment.core.PaymentExecutors;
@@ -66,6 +67,8 @@ public abstract class PaymentTestSuiteWithEmbeddedDB extends GuicyKillbillTestSu
@Inject
protected PaymentApi paymentApi;
@Inject
+ protected AdminPaymentApi adminPaymentApi;
+ @Inject
protected PaymentGatewayApi paymentGatewayApi;
@Inject
protected AccountInternalApi accountApi;