/* * Copyright 2014-2017 Groupon, Inc * Copyright 2014-2017 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.sm; import java.math.BigDecimal; import java.util.List; import java.util.UUID; import javax.annotation.Nullable; import org.killbill.automaton.State; import org.killbill.billing.account.api.Account; import org.killbill.billing.catalog.api.Currency; import org.killbill.billing.payment.PaymentTestSuiteWithEmbeddedDB; import org.killbill.billing.payment.api.PaymentApiException; import org.killbill.billing.payment.api.PluginProperty; import org.killbill.billing.payment.api.TransactionStatus; import org.killbill.billing.payment.api.TransactionType; import org.killbill.billing.payment.core.sm.payments.PaymentLeavingStateCallback; import org.killbill.billing.payment.dao.PaymentModelDao; import org.killbill.billing.payment.dao.PaymentTransactionModelDao; import org.mockito.Mockito; import org.testng.Assert; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; public class TestPaymentLeavingStateCallback extends PaymentTestSuiteWithEmbeddedDB { private final State state = Mockito.mock(State.class); private PaymentStateContext paymentStateContext; private PaymentLeavingStateTestCallback callback; private Account account; @Test(groups = "slow") public void testLeaveStateForNewPayment() throws Exception { setUp(null); callback.leavingState(state); // Verify a new transaction was created verifyPaymentTransaction(); // Verify a new payment was created final PaymentModelDao payment = paymentDao.getPayment(paymentStateContext.getPaymentTransactionModelDao().getPaymentId(), internalCallContext); Assert.assertEquals(payment.getExternalKey(), paymentStateContext.getPaymentExternalKey()); Assert.assertNull(payment.getStateName()); // Verify the payment has only one transaction Assert.assertEquals(paymentDao.getTransactionsForPayment(payment.getId(), internalCallContext).size(), 1); } @Test(groups = "slow") public void testLeaveStateForExistingPayment() throws Exception { final UUID paymentId = UUID.randomUUID(); setUp(paymentId); // Verify the payment has only one transaction final List<PaymentTransactionModelDao> transactions = paymentDao.getTransactionsForPayment(paymentId, internalCallContext); Assert.assertEquals(transactions.size(), 1); // Reset paymentExternalKey to something else paymentStateContext.setPaymentTransactionExternalKey(UUID.randomUUID().toString()); callback.leavingState(state); // Verify a new transaction was created verifyPaymentTransaction(); // Verify the payment has now two transactions Assert.assertEquals(paymentDao.getTransactionsForPayment(paymentId, internalCallContext).size(), 2); } private void verifyPaymentTransaction() { Assert.assertNotNull(paymentStateContext.getPaymentTransactionModelDao().getPaymentId()); Assert.assertEquals(paymentStateContext.getPaymentTransactionModelDao().getTransactionExternalKey(), paymentStateContext.getPaymentTransactionExternalKey()); Assert.assertEquals(paymentStateContext.getPaymentTransactionModelDao().getTransactionStatus(), TransactionStatus.UNKNOWN); Assert.assertEquals(paymentStateContext.getPaymentTransactionModelDao().getAmount().compareTo(paymentStateContext.getAmount()), 0); Assert.assertEquals(paymentStateContext.getPaymentTransactionModelDao().getCurrency(), paymentStateContext.getCurrency()); Assert.assertNull(paymentStateContext.getPaymentTransactionModelDao().getProcessedAmount()); Assert.assertNull(paymentStateContext.getPaymentTransactionModelDao().getProcessedCurrency()); Assert.assertNull(paymentStateContext.getPaymentTransactionModelDao().getGatewayErrorCode()); Assert.assertNull(paymentStateContext.getPaymentTransactionModelDao().getGatewayErrorMsg()); } private void setUp(@Nullable final UUID paymentId) throws Exception { account = Mockito.mock(Account.class); Mockito.when(account.getId()).thenReturn(UUID.randomUUID()); paymentStateContext = new PaymentStateContext(true, paymentId, null, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), TransactionType.CAPTURE, account, UUID.randomUUID(), new BigDecimal("192.3920111"), Currency.BRL, null, null, false, null, ImmutableList.<PluginProperty>of(), internalCallContext, callContext); if (paymentId != null) { // Create the first payment manually final PaymentModelDao newPaymentModelDao = new PaymentModelDao(paymentId, clock.getUTCNow(), clock.getUTCNow(), paymentStateContext.getAccount().getId(), paymentStateContext.getPaymentMethodId(), 1, paymentStateContext.getPaymentExternalKey() ); final PaymentTransactionModelDao newPaymentTransactionModelDao = new PaymentTransactionModelDao(clock.getUTCNow(), clock.getUTCNow(), null, paymentStateContext.getPaymentTransactionExternalKey(), paymentId, paymentStateContext.getTransactionType(), clock.getUTCNow(), TransactionStatus.UNKNOWN, paymentStateContext.getAmount(), paymentStateContext.getCurrency(), null, null); paymentDao.insertPaymentWithFirstTransaction(newPaymentModelDao, newPaymentTransactionModelDao, internalCallContext); } final PaymentAutomatonDAOHelper daoHelper = new PaymentAutomatonDAOHelper(paymentStateContext, clock.getUTCNow(), paymentDao, paymentPluginServiceRegistration, internalCallContext, eventBus, paymentSMHelper); callback = new PaymentLeavingStateTestCallback(daoHelper, paymentStateContext); Mockito.when(state.getName()).thenReturn("NEW_STATE"); } private static final class PaymentLeavingStateTestCallback extends PaymentLeavingStateCallback { private PaymentLeavingStateTestCallback(final PaymentAutomatonDAOHelper daoHelper, final PaymentStateContext paymentStateContext) throws PaymentApiException { super(daoHelper, paymentStateContext); } } }