Search in sources :

Example 26 with PaymentTransactionModelDao

use of org.killbill.billing.payment.dao.PaymentTransactionModelDao in project killbill by killbill.

the class PaymentProcessor method cancelScheduledPaymentTransaction.

public void cancelScheduledPaymentTransaction(@Nullable final UUID paymentTransactionId, @Nullable final String paymentTransactionExternalKey, final CallContext callContext) throws PaymentApiException {
    final InternalCallContext internalCallContextWithoutAccountRecordId = internalCallContextFactory.createInternalCallContextWithoutAccountRecordId(callContext);
    final String effectivePaymentTransactionExternalKey;
    if (paymentTransactionExternalKey == null) {
        final PaymentTransactionModelDao transaction = paymentDao.getPaymentTransaction(paymentTransactionId, internalCallContextWithoutAccountRecordId);
        effectivePaymentTransactionExternalKey = transaction.getTransactionExternalKey();
    } else {
        effectivePaymentTransactionExternalKey = paymentTransactionExternalKey;
    }
    final List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttemptByTransactionExternalKey(effectivePaymentTransactionExternalKey, internalCallContextWithoutAccountRecordId);
    if (attempts.isEmpty()) {
        return;
    }
    final PaymentAttemptModelDao lastPaymentAttempt = attempts.get(attempts.size() - 1);
    final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(lastPaymentAttempt.getAccountId(), callContext);
    cancelScheduledPaymentTransaction(lastPaymentAttempt.getId(), internalCallContext);
}
Also used : PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext)

Example 27 with PaymentTransactionModelDao

use of org.killbill.billing.payment.dao.PaymentTransactionModelDao in project killbill by killbill.

the class PaymentProcessor method toPayment.

// Used in bulk get API (getAccountPayments)
private Payment toPayment(final PaymentModelDao curPaymentModelDao, final Collection<PaymentTransactionModelDao> curTransactionsModelDao, @Nullable final Iterable<PaymentTransactionInfoPlugin> pluginTransactions, final boolean withAttempts, final InternalTenantContext internalTenantContext) {
    final Collection<PaymentTransactionModelDao> transactionsModelDao = new LinkedList<PaymentTransactionModelDao>(curTransactionsModelDao);
    invokeJanitor(curPaymentModelDao, transactionsModelDao, pluginTransactions, internalTenantContext);
    final Collection<PaymentTransaction> transactions = new LinkedList<PaymentTransaction>();
    for (final PaymentTransactionModelDao newPaymentTransactionModelDao : transactionsModelDao) {
        final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin = findPaymentTransactionInfoPlugin(newPaymentTransactionModelDao, pluginTransactions);
        final PaymentTransaction transaction = new DefaultPaymentTransaction(newPaymentTransactionModelDao.getId(), newPaymentTransactionModelDao.getAttemptId(), newPaymentTransactionModelDao.getTransactionExternalKey(), newPaymentTransactionModelDao.getCreatedDate(), newPaymentTransactionModelDao.getUpdatedDate(), newPaymentTransactionModelDao.getPaymentId(), newPaymentTransactionModelDao.getTransactionType(), newPaymentTransactionModelDao.getEffectiveDate(), newPaymentTransactionModelDao.getTransactionStatus(), newPaymentTransactionModelDao.getAmount(), newPaymentTransactionModelDao.getCurrency(), newPaymentTransactionModelDao.getProcessedAmount(), newPaymentTransactionModelDao.getProcessedCurrency(), newPaymentTransactionModelDao.getGatewayErrorCode(), newPaymentTransactionModelDao.getGatewayErrorMsg(), paymentTransactionInfoPlugin);
        transactions.add(transaction);
    }
    final Ordering<PaymentTransaction> perPaymentTransactionOrdering = Ordering.<PaymentTransaction>from(new Comparator<PaymentTransaction>() {

        @Override
        public int compare(final PaymentTransaction o1, final PaymentTransaction o2) {
            return o1.getEffectiveDate().compareTo(o2.getEffectiveDate());
        }
    });
    final List<PaymentTransaction> sortedTransactions = perPaymentTransactionOrdering.immutableSortedCopy(transactions);
    return new DefaultPayment(curPaymentModelDao.getId(), curPaymentModelDao.getCreatedDate(), curPaymentModelDao.getUpdatedDate(), curPaymentModelDao.getAccountId(), curPaymentModelDao.getPaymentMethodId(), curPaymentModelDao.getPaymentNumber(), curPaymentModelDao.getExternalKey(), sortedTransactions, (withAttempts && !sortedTransactions.isEmpty()) ? getPaymentAttempts(paymentDao.getPaymentAttempts(curPaymentModelDao.getExternalKey(), internalTenantContext), internalTenantContext) : null);
}
Also used : DefaultPaymentTransaction(org.killbill.billing.payment.api.DefaultPaymentTransaction) PaymentTransaction(org.killbill.billing.payment.api.PaymentTransaction) DefaultPayment(org.killbill.billing.payment.api.DefaultPayment) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) DefaultPaymentTransaction(org.killbill.billing.payment.api.DefaultPaymentTransaction) PaymentTransactionInfoPlugin(org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin) LinkedList(java.util.LinkedList)

Example 28 with PaymentTransactionModelDao

use of org.killbill.billing.payment.dao.PaymentTransactionModelDao in project killbill by killbill.

the class CompletionControlOperation method doOperationCallback.

@Override
public OperationResult doOperationCallback() throws OperationException {
    final List<String> controlPluginNameList = paymentStateControlContext.getPaymentControlPluginNames();
    final String controlPluginNames = JOINER.join(controlPluginNameList);
    return dispatchWithAccountLockAndTimeout(controlPluginNames, new DispatcherCallback<PluginDispatcherReturnType<OperationResult>, OperationException>() {

        @Override
        public PluginDispatcherReturnType<OperationResult> doOperation() throws OperationException {
            final PaymentTransactionModelDao transaction = paymentStateContext.getPaymentTransactionModelDao();
            final PaymentControlContext updatedPaymentControlContext = new DefaultPaymentControlContext(paymentStateContext.getAccount(), paymentStateContext.getPaymentMethodId(), paymentStateControlContext.getAttemptId(), transaction.getPaymentId(), paymentStateContext.getPaymentExternalKey(), transaction.getId(), paymentStateContext.getPaymentTransactionExternalKey(), PaymentApiType.PAYMENT_TRANSACTION, paymentStateContext.getTransactionType(), null, transaction.getAmount(), transaction.getCurrency(), transaction.getProcessedAmount(), transaction.getProcessedCurrency(), paymentStateControlContext.isApiPayment(), paymentStateContext.getCallContext());
            try {
                final Payment result = doCallSpecificOperationCallback();
                ((PaymentStateControlContext) paymentStateContext).setResult(result);
                final boolean success = transaction.getTransactionStatus() == TransactionStatus.SUCCESS || transaction.getTransactionStatus() == TransactionStatus.PENDING;
                if (success) {
                    executePluginOnSuccessCalls(paymentStateControlContext.getPaymentControlPluginNames(), updatedPaymentControlContext);
                    // Remove scheduled retry, if any
                    paymentProcessor.cancelScheduledPaymentTransaction(paymentStateControlContext.getAttemptId(), paymentStateControlContext.getInternalCallContext());
                    return PluginDispatcher.createPluginDispatcherReturnType(OperationResult.SUCCESS);
                } else {
                    throw new OperationException(null, executePluginOnFailureCallsAndSetRetryDate(updatedPaymentControlContext));
                }
            } catch (final PaymentApiException e) {
                // Wrap PaymentApiException, and throw a new OperationException with an ABORTED/FAILURE state based on the retry result.
                throw new OperationException(e, executePluginOnFailureCallsAndSetRetryDate(updatedPaymentControlContext));
            } catch (final RuntimeException e) {
                // Attempts to set the retry date in context if needed.
                throw new OperationException(e, executePluginOnFailureCallsAndSetRetryDate(updatedPaymentControlContext));
            }
        }
    });
}
Also used : PluginDispatcherReturnType(org.killbill.billing.payment.dispatcher.PluginDispatcher.PluginDispatcherReturnType) Payment(org.killbill.billing.payment.api.Payment) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) DefaultPaymentControlContext(org.killbill.billing.payment.core.sm.control.ControlPluginRunner.DefaultPaymentControlContext) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) PaymentControlContext(org.killbill.billing.control.plugin.api.PaymentControlContext) DefaultPaymentControlContext(org.killbill.billing.payment.core.sm.control.ControlPluginRunner.DefaultPaymentControlContext) OperationException(org.killbill.automaton.OperationException)

Example 29 with PaymentTransactionModelDao

use of org.killbill.billing.payment.dao.PaymentTransactionModelDao in project killbill by killbill.

the class DefaultControlInitiated method leavingState.

@Override
public void leavingState(final State state) throws OperationException {
    final DateTime utcNow = pluginControlPaymentAutomatonRunner.getClock().getUTCNow();
    // Retrieve the associated payment transaction, if any
    PaymentTransactionModelDao paymentTransactionModelDaoCandidate = null;
    if (stateContext.getTransactionId() != null) {
        paymentTransactionModelDaoCandidate = paymentDao.getPaymentTransaction(stateContext.getTransactionId(), stateContext.getInternalCallContext());
        Preconditions.checkNotNull(paymentTransactionModelDaoCandidate, "paymentTransaction cannot be null for id " + stateContext.getTransactionId());
    } else if (stateContext.getPaymentTransactionExternalKey() != null) {
        final List<PaymentTransactionModelDao> paymentTransactionModelDaos = paymentDao.getPaymentTransactionsByExternalKey(stateContext.getPaymentTransactionExternalKey(), stateContext.getInternalCallContext());
        if (!paymentTransactionModelDaos.isEmpty()) {
            paymentTransactionModelDaoCandidate = paymentTransactionModelDaos.get(paymentTransactionModelDaos.size() - 1);
        }
    }
    final PaymentTransactionModelDao paymentTransactionModelDao = paymentTransactionModelDaoCandidate != null && TRANSIENT_TRANSACTION_STATUSES.contains(paymentTransactionModelDaoCandidate.getTransactionStatus()) ? paymentTransactionModelDaoCandidate : null;
    if (stateContext.getPaymentId() != null && stateContext.getPaymentExternalKey() == null) {
        final PaymentModelDao payment = paymentDao.getPayment(stateContext.getPaymentId(), stateContext.getInternalCallContext());
        Preconditions.checkNotNull(payment, "payment cannot be null for id " + stateContext.getPaymentId());
        stateContext.setPaymentExternalKey(payment.getExternalKey());
        stateContext.setPaymentMethodId(payment.getPaymentMethodId());
    } else if (stateContext.getPaymentExternalKey() == null) {
        final UUID paymentIdForNewPayment = UUIDs.randomUUID();
        stateContext.setPaymentIdForNewPayment(paymentIdForNewPayment);
        stateContext.setPaymentExternalKey(paymentIdForNewPayment.toString());
    }
    if (paymentTransactionModelDao != null) {
        stateContext.setPaymentTransactionModelDao(paymentTransactionModelDao);
        stateContext.setProcessedAmount(paymentTransactionModelDao.getProcessedAmount());
        stateContext.setProcessedCurrency(paymentTransactionModelDao.getProcessedCurrency());
    } else if (stateContext.getPaymentTransactionExternalKey() == null) {
        final UUID paymentTransactionIdForNewPaymentTransaction = UUIDs.randomUUID();
        stateContext.setPaymentTransactionIdForNewPaymentTransaction(paymentTransactionIdForNewPaymentTransaction);
        stateContext.setPaymentTransactionExternalKey(paymentTransactionIdForNewPaymentTransaction.toString());
    }
    if (stateContext.getPaymentMethodId() == null) {
        // Similar logic in PaymentAutomatonRunner
        stateContext.setPaymentMethodId(stateContext.getAccount().getPaymentMethodId());
    }
    if (state.getName().equals(initialState.getName()) || state.getName().equals(retriedState.getName())) {
        try {
            final PaymentAttemptModelDao attempt;
            if (paymentTransactionModelDao != null && paymentTransactionModelDao.getAttemptId() != null) {
                attempt = pluginControlPaymentAutomatonRunner.getPaymentDao().getPaymentAttempt(paymentTransactionModelDao.getAttemptId(), stateContext.getInternalCallContext());
                Preconditions.checkNotNull(attempt, "attempt cannot be null for id " + paymentTransactionModelDao.getAttemptId());
            } else {
                //
                // We don't serialize any properties at this stage to avoid serializing sensitive information.
                // However, if after going through the control plugins, the attempt end up in RETRIED state,
                // the properties will be serialized in the enteringState callback (any plugin that sets a
                // retried date is responsible to correctly remove sensitive information such as CVV, ...)
                //
                final byte[] serializedProperties = PluginPropertySerializer.serialize(ImmutableList.<PluginProperty>of());
                attempt = new PaymentAttemptModelDao(stateContext.getAccount().getId(), stateContext.getPaymentMethodId(), utcNow, utcNow, stateContext.getPaymentExternalKey(), stateContext.getTransactionId(), stateContext.getPaymentTransactionExternalKey(), transactionType, initialState.getName(), stateContext.getAmount(), stateContext.getCurrency(), stateContext.getPaymentControlPluginNames(), serializedProperties);
                pluginControlPaymentAutomatonRunner.getPaymentDao().insertPaymentAttemptWithProperties(attempt, stateContext.getInternalCallContext());
            }
            stateContext.setAttemptId(attempt.getId());
        } catch (final PluginPropertySerializerException e) {
            throw new OperationException(e);
        }
    }
}
Also used : PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) PaymentModelDao(org.killbill.billing.payment.dao.PaymentModelDao) PluginPropertySerializerException(org.killbill.billing.payment.dao.PluginPropertySerializer.PluginPropertySerializerException) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) UUID(java.util.UUID) DateTime(org.joda.time.DateTime) OperationException(org.killbill.automaton.OperationException)

Example 30 with PaymentTransactionModelDao

use of org.killbill.billing.payment.dao.PaymentTransactionModelDao in project killbill by killbill.

the class ChargebackInitiated method leavingState.

@Override
public void leavingState(final State oldState) throws OperationException {
    // Sanity: chargeback reversals can only happen after a successful chargeback
    if (OperationResult.FAILURE.equals(paymentStateContext.getOverridePluginOperationResult())) {
        final List<PaymentTransactionModelDao> paymentTransactionsForCurrentPayment = paymentStateContext.getPaymentId() != null ? daoHelper.getPaymentDao().getTransactionsForPayment(paymentStateContext.getPaymentId(), paymentStateContext.getInternalCallContext()) : ImmutableList.<PaymentTransactionModelDao>of();
        final Iterable<PaymentTransactionModelDao> existingPaymentTransactionsForTransactionIdOrKey = filterExistingPaymentTransactionsForTransactionIdOrKey(paymentTransactionsForCurrentPayment, paymentStateContext.getTransactionId(), paymentStateContext.getPaymentTransactionExternalKey());
        if (Iterables.<PaymentTransactionModelDao>isEmpty(existingPaymentTransactionsForTransactionIdOrKey)) {
            // Chargeback reversals can only happen after a successful chargeback
            throw new OperationException(new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_SUCCESS_PAYMENT, paymentStateContext.getPaymentId()));
        }
    }
    super.leavingState(oldState);
}
Also used : PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) OperationException(org.killbill.automaton.OperationException)

Aggregations

PaymentTransactionModelDao (org.killbill.billing.payment.dao.PaymentTransactionModelDao)39 PaymentModelDao (org.killbill.billing.payment.dao.PaymentModelDao)17 PaymentApiException (org.killbill.billing.payment.api.PaymentApiException)16 Test (org.testng.annotations.Test)16 UUID (java.util.UUID)12 BigDecimal (java.math.BigDecimal)10 PaymentAttemptModelDao (org.killbill.billing.payment.dao.PaymentAttemptModelDao)10 Predicate (com.google.common.base.Predicate)8 Payment (org.killbill.billing.payment.api.Payment)7 Account (org.killbill.billing.account.api.Account)6 PaymentTransactionInfoPlugin (org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin)6 ImmutableList (com.google.common.collect.ImmutableList)5 List (java.util.List)5 LinkedList (java.util.LinkedList)4 LocalDate (org.joda.time.LocalDate)4 Invoice (org.killbill.billing.invoice.api.Invoice)4 PluginProperty (org.killbill.billing.payment.api.PluginProperty)4 ArrayList (java.util.ArrayList)3 TimeoutException (java.util.concurrent.TimeoutException)3 OperationException (org.killbill.automaton.OperationException)3