Search in sources :

Example 1 with MissingEntryException

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

the class PluginControlPaymentAutomatonRunner method run.

public Payment run(final State state, final boolean isApiPayment, final Boolean isSuccess, final TransactionType transactionType, final ControlOperation controlOperation, final Account account, @Nullable final UUID paymentMethodId, @Nullable final UUID paymentId, @Nullable final String paymentExternalKey, @Nullable final UUID transactionId, final String paymentTransactionExternalKey, @Nullable final BigDecimal amount, @Nullable final Currency currency, final Iterable<PluginProperty> properties, @Nullable final List<String> paymentControlPluginNames, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
    final PaymentStateControlContext paymentStateContext = createContext(isApiPayment, isSuccess, transactionType, account, paymentMethodId, paymentId, paymentExternalKey, transactionId, paymentTransactionExternalKey, amount, currency, properties, paymentControlPluginNames, callContext, internalCallContext);
    try {
        final OperationCallback callback = createOperationCallback(controlOperation, paymentStateContext);
        final LeavingStateCallback leavingStateCallback = new DefaultControlInitiated(this, paymentStateContext, paymentDao, paymentControlStateMachineHelper.getInitialState(), paymentControlStateMachineHelper.getRetriedState(), transactionType);
        final EnteringStateCallback enteringStateCallback = new DefaultControlCompleted(this, paymentStateContext, paymentControlStateMachineHelper.getRetriedState(), retryServiceScheduler);
        state.runOperation(paymentControlStateMachineHelper.getOperation(), callback, enteringStateCallback, leavingStateCallback);
    } catch (final MissingEntryException e) {
        throw new PaymentApiException(e.getCause(), ErrorCode.PAYMENT_INTERNAL_ERROR, MoreObjects.firstNonNull(e.getMessage(), ""));
    } catch (final OperationException e) {
        if (e.getCause() instanceof PaymentApiException) {
            throw (PaymentApiException) e.getCause();
        // If the control plugin tries to pass us back a PaymentApiException we throw it
        } else if (e.getCause() instanceof PaymentControlApiException && e.getCause().getCause() instanceof PaymentApiException) {
            throw (PaymentApiException) e.getCause().getCause();
        } else if (e.getCause() != null || paymentStateContext.getResult() == null) {
            throw new PaymentApiException(e.getCause(), ErrorCode.PAYMENT_INTERNAL_ERROR, MoreObjects.firstNonNull(e.getMessage(), ""));
        }
    }
    // we don't throw, and return the failed Payment instead to be consistent with what happens when we don't go through control api.
    return paymentStateContext.getResult();
}
Also used : DefaultControlInitiated(org.killbill.billing.payment.core.sm.control.DefaultControlInitiated) OperationCallback(org.killbill.automaton.Operation.OperationCallback) DefaultControlCompleted(org.killbill.billing.payment.core.sm.control.DefaultControlCompleted) MissingEntryException(org.killbill.automaton.MissingEntryException) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) LeavingStateCallback(org.killbill.automaton.State.LeavingStateCallback) EnteringStateCallback(org.killbill.automaton.State.EnteringStateCallback) OperationException(org.killbill.automaton.OperationException) PaymentControlApiException(org.killbill.billing.control.plugin.api.PaymentControlApiException) PaymentStateControlContext(org.killbill.billing.payment.core.sm.control.PaymentStateControlContext)

Example 2 with MissingEntryException

use of org.killbill.automaton.MissingEntryException 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)

Example 3 with MissingEntryException

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

the class PaymentAutomatonRunner method runStateMachineOperation.

private void runStateMachineOperation(final String initialStateName, final TransactionType transactionType, final LeavingStateCallback leavingStateCallback, final OperationCallback operationCallback, final EnteringStateCallback enteringStateCallback, final Boolean includeDeletedPaymentMethod, final PaymentStateContext paymentStateContext, final PaymentAutomatonDAOHelper daoHelper) throws PaymentApiException {
    try {
        final StateMachineConfig stateMachineConfig = paymentSMHelper.getStateMachineConfig(daoHelper.getPaymentProviderPluginName(includeDeletedPaymentMethod), paymentStateContext.getInternalCallContext());
        final StateMachine initialStateMachine = stateMachineConfig.getStateMachineForState(initialStateName);
        final State initialState = initialStateMachine.getState(initialStateName);
        final Operation operation = paymentSMHelper.getOperationForTransaction(stateMachineConfig, transactionType);
        initialState.runOperation(operation, operationCallback, enteringStateCallback, leavingStateCallback);
    } catch (final MissingEntryException e) {
        throw new PaymentApiException(e.getCause(), ErrorCode.PAYMENT_INVALID_OPERATION, transactionType, initialStateName);
    } catch (final OperationException e) {
        if (e.getCause() == null) {
            throw new PaymentApiException(e, ErrorCode.PAYMENT_INTERNAL_ERROR, MoreObjects.firstNonNull(e.getMessage(), ""));
        } else if (e.getCause() instanceof PaymentApiException) {
            throw (PaymentApiException) e.getCause();
        } else {
            throw new PaymentApiException(e.getCause(), ErrorCode.PAYMENT_INTERNAL_ERROR, MoreObjects.firstNonNull(e.getMessage(), ""));
        }
    }
}
Also used : StateMachine(org.killbill.automaton.StateMachine) State(org.killbill.automaton.State) StateMachineConfig(org.killbill.automaton.StateMachineConfig) MissingEntryException(org.killbill.automaton.MissingEntryException) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) PurchaseOperation(org.killbill.billing.payment.core.sm.payments.PurchaseOperation) RefundOperation(org.killbill.billing.payment.core.sm.payments.RefundOperation) AuthorizeOperation(org.killbill.billing.payment.core.sm.payments.AuthorizeOperation) VoidOperation(org.killbill.billing.payment.core.sm.payments.VoidOperation) Operation(org.killbill.automaton.Operation) CreditOperation(org.killbill.billing.payment.core.sm.payments.CreditOperation) ChargebackOperation(org.killbill.billing.payment.core.sm.payments.ChargebackOperation) CaptureOperation(org.killbill.billing.payment.core.sm.payments.CaptureOperation) OperationException(org.killbill.automaton.OperationException)

Example 4 with MissingEntryException

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

the class PluginControlPaymentAutomatonRunner method run.

public Payment run(final State state, final boolean isApiPayment, final Boolean isSuccess, final TransactionType transactionType, final ControlOperation controlOperation, final Account account, @Nullable final UUID paymentMethodId, @Nullable final UUID paymentId, @Nullable final String paymentExternalKey, @Nullable final UUID transactionId, final String paymentTransactionExternalKey, @Nullable final BigDecimal amount, @Nullable final Currency currency, @Nullable final DateTime effectiveDate, final Iterable<PluginProperty> properties, @Nullable final List<String> paymentControlPluginNames, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
    final PaymentStateControlContext paymentStateContext = createContext(isApiPayment, isSuccess, transactionType, account, paymentMethodId, paymentId, paymentExternalKey, transactionId, paymentTransactionExternalKey, amount, currency, effectiveDate, properties, paymentControlPluginNames, callContext, internalCallContext);
    try {
        final OperationCallback callback = createOperationCallback(controlOperation, paymentStateContext);
        final LeavingStateCallback leavingStateCallback = new DefaultControlInitiated(this, paymentStateContext, paymentDao, paymentControlStateMachineHelper.getInitialState(), paymentControlStateMachineHelper.getRetriedState(), transactionType);
        final EnteringStateCallback enteringStateCallback = new DefaultControlCompleted(this, paymentStateContext, paymentControlStateMachineHelper.getRetriedState(), retryServiceScheduler);
        state.runOperation(paymentControlStateMachineHelper.getOperation(), callback, enteringStateCallback, leavingStateCallback);
    } catch (final MissingEntryException e) {
        throw new PaymentApiException(e.getCause(), ErrorCode.PAYMENT_INTERNAL_ERROR, MoreObjects.firstNonNull(e.getMessage(), ""));
    } catch (final OperationException e) {
        if (e.getCause() instanceof PaymentApiException) {
            throw (PaymentApiException) e.getCause();
        // If the control plugin tries to pass us back a PaymentApiException we throw it
        } else if (e.getCause() instanceof PaymentControlApiException && e.getCause().getCause() instanceof PaymentApiException) {
            throw (PaymentApiException) e.getCause().getCause();
        } else if (e.getCause() != null || paymentStateContext.getResult() == null) {
            throw new PaymentApiException(e.getCause(), ErrorCode.PAYMENT_INTERNAL_ERROR, MoreObjects.firstNonNull(e.getMessage(), ""));
        }
    }
    // we don't throw, and return the failed Payment instead to be consistent with what happens when we don't go through control api.
    return paymentStateContext.getResult();
}
Also used : DefaultControlInitiated(org.killbill.billing.payment.core.sm.control.DefaultControlInitiated) OperationCallback(org.killbill.automaton.Operation.OperationCallback) DefaultControlCompleted(org.killbill.billing.payment.core.sm.control.DefaultControlCompleted) MissingEntryException(org.killbill.automaton.MissingEntryException) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) LeavingStateCallback(org.killbill.automaton.State.LeavingStateCallback) EnteringStateCallback(org.killbill.automaton.State.EnteringStateCallback) OperationException(org.killbill.automaton.OperationException) PaymentControlApiException(org.killbill.billing.control.plugin.api.PaymentControlApiException) PaymentStateControlContext(org.killbill.billing.payment.core.sm.control.PaymentStateControlContext)

Example 5 with MissingEntryException

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

the class PluginControlPaymentAutomatonRunner method completeRun.

public Payment completeRun(final PaymentStateControlContext paymentStateContext) throws PaymentApiException {
    try {
        final OperationCallback callback = new CompletionControlOperation(locker, paymentPluginDispatcher, paymentConfig, paymentStateContext, paymentRefresher, paymentProcessor, controlPluginRunner);
        final LeavingStateCallback leavingStateCallback = new NoopControlInitiated();
        final EnteringStateCallback enteringStateCallback = new DefaultControlCompleted(this, paymentStateContext, paymentControlStateMachineHelper.getRetriedState(), retryServiceScheduler);
        paymentControlStateMachineHelper.getInitialState().runOperation(paymentControlStateMachineHelper.getOperation(), callback, enteringStateCallback, leavingStateCallback);
    } catch (final MissingEntryException e) {
        throw new PaymentApiException(e.getCause(), ErrorCode.PAYMENT_INTERNAL_ERROR, MoreObjects.firstNonNull(e.getMessage(), ""));
    } catch (final OperationException e) {
        if (e.getCause() instanceof PaymentApiException) {
            throw (PaymentApiException) e.getCause();
        // If the control plugin tries to pass us back a PaymentApiException we throw it
        } else if (e.getCause() instanceof PaymentControlApiException && e.getCause().getCause() instanceof PaymentApiException) {
            throw (PaymentApiException) e.getCause().getCause();
        } else if (e.getCause() != null || paymentStateContext.getResult() == null) {
            throw new PaymentApiException(e.getCause(), ErrorCode.PAYMENT_INTERNAL_ERROR, MoreObjects.firstNonNull(e.getMessage(), ""));
        }
    }
    // we don't throw, and return the failed Payment instead to be consistent with what happens when we don't go through control api.
    return paymentStateContext.getResult();
}
Also used : OperationCallback(org.killbill.automaton.Operation.OperationCallback) CompletionControlOperation(org.killbill.billing.payment.core.sm.control.CompletionControlOperation) NoopControlInitiated(org.killbill.billing.payment.core.sm.control.NoopControlInitiated) DefaultControlCompleted(org.killbill.billing.payment.core.sm.control.DefaultControlCompleted) MissingEntryException(org.killbill.automaton.MissingEntryException) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) LeavingStateCallback(org.killbill.automaton.State.LeavingStateCallback) EnteringStateCallback(org.killbill.automaton.State.EnteringStateCallback) OperationException(org.killbill.automaton.OperationException) PaymentControlApiException(org.killbill.billing.control.plugin.api.PaymentControlApiException)

Aggregations

MissingEntryException (org.killbill.automaton.MissingEntryException)5 PaymentApiException (org.killbill.billing.payment.api.PaymentApiException)5 OperationException (org.killbill.automaton.OperationException)4 OperationCallback (org.killbill.automaton.Operation.OperationCallback)3 EnteringStateCallback (org.killbill.automaton.State.EnteringStateCallback)3 LeavingStateCallback (org.killbill.automaton.State.LeavingStateCallback)3 PaymentControlApiException (org.killbill.billing.control.plugin.api.PaymentControlApiException)3 DefaultControlCompleted (org.killbill.billing.payment.core.sm.control.DefaultControlCompleted)3 State (org.killbill.automaton.State)2 DefaultControlInitiated (org.killbill.billing.payment.core.sm.control.DefaultControlInitiated)2 PaymentStateControlContext (org.killbill.billing.payment.core.sm.control.PaymentStateControlContext)2 Predicate (com.google.common.base.Predicate)1 UUID (java.util.UUID)1 Operation (org.killbill.automaton.Operation)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