Search in sources :

Example 1 with State

use of org.killbill.automaton.State in project killbill by killbill.

the class TestRetryablePayment method testRetryLogicFromRetriedStateWithPaymentApiException.

@Test(groups = "fast")
public void testRetryLogicFromRetriedStateWithPaymentApiException() {
    mockRetryProviderPlugin.setAborted(false).setNextRetryDate(null);
    mockRetryAuthorizeOperationCallback.setResult(null).setException(new PaymentApiException(ErrorCode.__UNKNOWN_ERROR_CODE, "foo"));
    runner.setOperationCallback(mockRetryAuthorizeOperationCallback).setContext(paymentStateContext);
    final State state = retrySMHelper.getRetriedState();
    final UUID transactionId = UUID.randomUUID();
    final UUID paymentId = UUID.randomUUID();
    final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow, paymentExternalKey, transactionId, paymentTransactionExternalKey, TransactionType.AUTHORIZE, state.getName(), amount, currency, null, EMPTY_PROPERTIES);
    paymentDao.insertPaymentAttemptWithProperties(attempt, internalCallContext);
    paymentDao.insertPaymentWithFirstTransaction(new PaymentModelDao(paymentId, utcNow, utcNow, account.getId(), paymentMethodId, -1, paymentExternalKey), new PaymentTransactionModelDao(transactionId, attempt.getId(), paymentTransactionExternalKey, utcNow, utcNow, paymentId, TransactionType.AUTHORIZE, utcNow, TransactionStatus.PAYMENT_FAILURE, amount, currency, "bla", "foo"), internalCallContext);
    processor.retryPaymentTransaction(attempt.getId(), ImmutableList.<String>of(MockPaymentControlProviderPlugin.PLUGIN_NAME), internalCallContext);
    final List<PaymentAttemptModelDao> pas = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionExternalKey, internalCallContext);
    assertEquals(pas.size(), 2);
    final PaymentAttemptModelDao failedAttempt = Iterables.tryFind(pas, new Predicate<PaymentAttemptModelDao>() {

        @Override
        public boolean apply(final PaymentAttemptModelDao input) {
            return input.getTransactionType() == TransactionType.AUTHORIZE && input.getStateName().equals("ABORTED");
        }
    }).orNull();
    assertNotNull(failedAttempt);
}
Also used : PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) PaymentModelDao(org.killbill.billing.payment.dao.PaymentModelDao) State(org.killbill.automaton.State) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) UUID(java.util.UUID) Predicate(com.google.common.base.Predicate) Test(org.testng.annotations.Test)

Example 2 with State

use of org.killbill.automaton.State in project killbill by killbill.

the class TestRetryablePayment method testRetryLogicFromRetriedStateWithLockFailure.

@Test(groups = "fast")
public void testRetryLogicFromRetriedStateWithLockFailure() throws LockFailedException {
    GlobalLock lock = null;
    try {
        // Grab lock so that operation later will fail...
        lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), account.getId().toString(), 1);
        mockRetryProviderPlugin.setAborted(false).setNextRetryDate(null);
        mockRetryAuthorizeOperationCallback.setResult(OperationResult.SUCCESS).setException(null);
        runner.setOperationCallback(mockRetryAuthorizeOperationCallback).setContext(paymentStateContext);
        final State state = retrySMHelper.getRetriedState();
        final UUID transactionId = UUID.randomUUID();
        final UUID paymentId = UUID.randomUUID();
        final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow, paymentExternalKey, transactionId, paymentTransactionExternalKey, TransactionType.AUTHORIZE, state.getName(), amount, currency, null, EMPTY_PROPERTIES);
        paymentDao.insertPaymentAttemptWithProperties(attempt, internalCallContext);
        paymentDao.insertPaymentWithFirstTransaction(new PaymentModelDao(paymentId, utcNow, utcNow, account.getId(), paymentMethodId, -1, paymentExternalKey), new PaymentTransactionModelDao(transactionId, attempt.getId(), paymentTransactionExternalKey, utcNow, utcNow, paymentId, TransactionType.AUTHORIZE, utcNow, TransactionStatus.PAYMENT_FAILURE, amount, currency, "bla", "foo"), internalCallContext);
        processor.retryPaymentTransaction(attempt.getId(), ImmutableList.<String>of(MockPaymentControlProviderPlugin.PLUGIN_NAME), internalCallContext);
        final List<PaymentAttemptModelDao> pas = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionExternalKey, internalCallContext);
        assertEquals(pas.size(), 2);
        final PaymentAttemptModelDao failedAttempt = Iterables.tryFind(pas, new Predicate<PaymentAttemptModelDao>() {

            @Override
            public boolean apply(final PaymentAttemptModelDao input) {
                return input.getTransactionType() == TransactionType.AUTHORIZE && input.getStateName().equals("ABORTED");
            }
        }).orNull();
        assertNotNull(failedAttempt);
    } finally {
        if (lock != null) {
            lock.release();
        }
    }
}
Also used : GlobalLock(org.killbill.commons.locker.GlobalLock) PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) PaymentModelDao(org.killbill.billing.payment.dao.PaymentModelDao) State(org.killbill.automaton.State) UUID(java.util.UUID) Predicate(com.google.common.base.Predicate) Test(org.testng.annotations.Test)

Example 3 with State

use of org.killbill.automaton.State in project killbill by killbill.

the class TestRetryablePayment method testRetryToSuccessWithPaymentApiExceptionAndRetry.

@Test(groups = "fast")
public void testRetryToSuccessWithPaymentApiExceptionAndRetry() {
    mockRetryProviderPlugin.setAborted(false).setNextRetryDate(new DateTime().plusDays(1));
    mockRetryAuthorizeOperationCallback.setResult(null).setException(new PaymentApiException(ErrorCode.__UNKNOWN_ERROR_CODE, "bla"));
    runner.setOperationCallback(mockRetryAuthorizeOperationCallback).setContext(paymentStateContext);
    final State state = retrySMHelper.getRetriedState();
    final UUID transactionId = UUID.randomUUID();
    paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow, paymentExternalKey, transactionId, paymentTransactionExternalKey, TransactionType.AUTHORIZE, state.getName(), amount, currency, null, EMPTY_PROPERTIES), internalCallContext);
    try {
        runner.run(state, false, TransactionType.AUTHORIZE, ControlOperation.AUTHORIZE, account, paymentMethodId, null, paymentExternalKey, paymentTransactionExternalKey, amount, currency, null, emptyProperties, null, callContext, internalCallContext);
        fail("Expecting paymentApiException...");
    } catch (final PaymentApiException e) {
        final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionExternalKey, internalCallContext).get(0);
        assertEquals(pa.getTransactionExternalKey(), paymentTransactionExternalKey);
        assertEquals(pa.getStateName(), "RETRIED");
        assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
    }
}
Also used : PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) State(org.killbill.automaton.State) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) UUID(java.util.UUID) DateTime(org.joda.time.DateTime) Test(org.testng.annotations.Test)

Example 4 with State

use of org.killbill.automaton.State in project killbill by killbill.

the class TestRetryablePayment method testRetryLogicFromRetriedStateWithSuccess.

@Test(groups = "fast")
public void testRetryLogicFromRetriedStateWithSuccess() throws PaymentApiException {
    mockRetryProviderPlugin.setAborted(false).setNextRetryDate(null);
    mockRetryAuthorizeOperationCallback.setResult(OperationResult.SUCCESS).setException(null);
    runner.setOperationCallback(mockRetryAuthorizeOperationCallback).setContext(paymentStateContext);
    final State state = retrySMHelper.getRetriedState();
    final UUID transactionId = UUID.randomUUID();
    final UUID paymentId = UUID.randomUUID();
    final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow, paymentExternalKey, transactionId, paymentTransactionExternalKey, TransactionType.AUTHORIZE, state.getName(), amount, currency, null, EMPTY_PROPERTIES);
    paymentDao.insertPaymentAttemptWithProperties(attempt, internalCallContext);
    paymentDao.insertPaymentWithFirstTransaction(new PaymentModelDao(paymentId, utcNow, utcNow, account.getId(), paymentMethodId, -1, paymentExternalKey), new PaymentTransactionModelDao(transactionId, attempt.getId(), paymentTransactionExternalKey, utcNow, utcNow, paymentId, TransactionType.AUTHORIZE, utcNow, TransactionStatus.PAYMENT_FAILURE, amount, currency, "bla", "foo"), internalCallContext);
    processor.retryPaymentTransaction(attempt.getId(), ImmutableList.<String>of(MockPaymentControlProviderPlugin.PLUGIN_NAME), internalCallContext);
    final List<PaymentAttemptModelDao> pas = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionExternalKey, internalCallContext);
    assertEquals(pas.size(), 2);
    final PaymentAttemptModelDao successfulAttempt = Iterables.tryFind(pas, new Predicate<PaymentAttemptModelDao>() {

        @Override
        public boolean apply(final PaymentAttemptModelDao input) {
            return input.getTransactionType() == TransactionType.AUTHORIZE && input.getStateName().equals("SUCCESS");
        }
    }).orNull();
    assertNotNull(successfulAttempt);
}
Also used : PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) PaymentModelDao(org.killbill.billing.payment.dao.PaymentModelDao) State(org.killbill.automaton.State) UUID(java.util.UUID) Predicate(com.google.common.base.Predicate) Test(org.testng.annotations.Test)

Example 5 with State

use of org.killbill.automaton.State in project killbill by killbill.

the class PluginControlPaymentProcessor method retryPaymentTransaction.

public void retryPaymentTransaction(final UUID attemptId, final List<String> paymentControlPluginNames, final InternalCallContext internalCallContext) {
    final PaymentAttemptModelDao attempt = paymentDao.getPaymentAttempt(attemptId, internalCallContext);
    log.info("Retrying attemptId='{}', paymentExternalKey='{}', transactionExternalKey='{}'. paymentControlPluginNames='{}'", attemptId, attempt.getPaymentExternalKey(), attempt.getTransactionExternalKey(), paymentControlPluginNames);
    final PaymentModelDao paymentModelDao = paymentDao.getPaymentByExternalKey(attempt.getPaymentExternalKey(), internalCallContext);
    final UUID paymentId = paymentModelDao != null ? paymentModelDao.getId() : null;
    final CallContext callContext = buildCallContext(internalCallContext);
    final String transactionType = TransactionType.PURCHASE.name();
    Account account = null;
    Payment payment = null;
    PaymentTransaction paymentTransaction = null;
    try {
        account = accountInternalApi.getAccountById(attempt.getAccountId(), internalCallContext);
        final State state = paymentControlStateMachineHelper.getState(attempt.getStateName());
        final Iterable<PluginProperty> pluginProperties = PluginPropertySerializer.deserialize(attempt.getPluginProperties());
        logEnterAPICall(log, transactionType, account, attempt.getPaymentMethodId(), paymentId, null, attempt.getAmount(), attempt.getCurrency(), attempt.getPaymentExternalKey(), attempt.getTransactionExternalKey(), null, paymentControlPluginNames);
        payment = pluginControlledPaymentAutomatonRunner.run(state, false, attempt.getTransactionType(), ControlOperation.valueOf(attempt.getTransactionType().toString()), account, attempt.getPaymentMethodId(), paymentId, attempt.getPaymentExternalKey(), attempt.getTransactionExternalKey(), // The amount on the payment attempt drives the amount of the new payment transaction
        attempt.getAmount(), attempt.getCurrency(), null, pluginProperties, paymentControlPluginNames, callContext, internalCallContext);
        log.debug("retryPaymentTransaction result: payment='{}'", payment);
        paymentTransaction = Iterables.<PaymentTransaction>find(Lists.<PaymentTransaction>reverse(payment.getTransactions()), new Predicate<PaymentTransaction>() {

            @Override
            public boolean apply(final PaymentTransaction input) {
                return attempt.getTransactionExternalKey().equals(input.getExternalKey());
            }
        });
    } catch (final AccountApiException e) {
        log.warn("Failed to retry attemptId='{}', paymentControlPlugins='{}'", attemptId, toPluginNamesOnError(paymentControlPluginNames), e);
    } catch (final PaymentApiException e) {
        // Log exception unless nothing left to be paid
        if (e.getCode() == ErrorCode.PAYMENT_PLUGIN_API_ABORTED.getCode() && paymentControlPluginNames != null && paymentControlPluginNames.size() == 1 && InvoicePaymentControlPluginApi.PLUGIN_NAME.equals(paymentControlPluginNames.get(0))) {
            log.warn("Failed to retry attemptId='{}', paymentControlPlugins='{}'", attemptId, toPluginNamesOnError(paymentControlPluginNames));
        } else {
            log.warn("Failed to retry attemptId='{}', paymentControlPlugins='{}'", attemptId, toPluginNamesOnError(paymentControlPluginNames), e);
        }
    } catch (final PluginPropertySerializerException e) {
        log.warn("Failed to retry attemptId='{}', paymentControlPlugins='{}'", attemptId, toPluginNamesOnError(paymentControlPluginNames), e);
    } catch (final MissingEntryException e) {
        log.warn("Failed to retry attemptId='{}', paymentControlPlugins='{}'", attemptId, toPluginNamesOnError(paymentControlPluginNames), e);
    } finally {
        logExitAPICall(log, transactionType, account, payment != null ? payment.getPaymentMethodId() : null, payment != null ? payment.getId() : null, paymentTransaction != null ? paymentTransaction.getId() : null, paymentTransaction != null ? paymentTransaction.getProcessedAmount() : null, paymentTransaction != null ? paymentTransaction.getProcessedCurrency() : null, payment != null ? payment.getExternalKey() : null, paymentTransaction != null ? paymentTransaction.getExternalKey() : null, paymentTransaction != null ? paymentTransaction.getTransactionStatus() : null, paymentControlPluginNames, null);
    }
}
Also used : PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) Account(org.killbill.billing.account.api.Account) PaymentModelDao(org.killbill.billing.payment.dao.PaymentModelDao) PluginPropertySerializerException(org.killbill.billing.payment.dao.PluginPropertySerializer.PluginPropertySerializerException) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) CallContext(org.killbill.billing.util.callcontext.CallContext) Predicate(com.google.common.base.Predicate) PaymentTransaction(org.killbill.billing.payment.api.PaymentTransaction) PluginProperty(org.killbill.billing.payment.api.PluginProperty) Payment(org.killbill.billing.payment.api.Payment) State(org.killbill.automaton.State) AccountApiException(org.killbill.billing.account.api.AccountApiException) MissingEntryException(org.killbill.automaton.MissingEntryException) UUID(java.util.UUID)

Aggregations

State (org.killbill.automaton.State)8 UUID (java.util.UUID)7 PaymentAttemptModelDao (org.killbill.billing.payment.dao.PaymentAttemptModelDao)7 Test (org.testng.annotations.Test)6 Predicate (com.google.common.base.Predicate)5 PaymentApiException (org.killbill.billing.payment.api.PaymentApiException)5 PaymentModelDao (org.killbill.billing.payment.dao.PaymentModelDao)4 PaymentTransactionModelDao (org.killbill.billing.payment.dao.PaymentTransactionModelDao)3 MissingEntryException (org.killbill.automaton.MissingEntryException)2 ImmutableList (com.google.common.collect.ImmutableList)1 List (java.util.List)1 DateTime (org.joda.time.DateTime)1 Operation (org.killbill.automaton.Operation)1 OperationException (org.killbill.automaton.OperationException)1 StateMachine (org.killbill.automaton.StateMachine)1 StateMachineConfig (org.killbill.automaton.StateMachineConfig)1 Account (org.killbill.billing.account.api.Account)1 AccountApiException (org.killbill.billing.account.api.AccountApiException)1 InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)1 Payment (org.killbill.billing.payment.api.Payment)1