Search in sources :

Example 16 with PaymentModelDao

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

the class IncompletePaymentTransactionTask method getLatestPaymentTransactionInfoPlugin.

private PaymentTransactionInfoPlugin getLatestPaymentTransactionInfoPlugin(final PaymentTransactionModelDao paymentTransaction, final InternalTenantContext internalTenantContext) {
    final TenantContext tenantContext = internalCallContextFactory.createTenantContext(internalTenantContext);
    final PaymentModelDao payment = paymentDao.getPayment(paymentTransaction.getPaymentId(), internalTenantContext);
    final PaymentTransactionInfoPlugin undefinedPaymentTransaction = new DefaultNoOpPaymentInfoPlugin(payment.getId(), paymentTransaction.getId(), paymentTransaction.getTransactionType(), paymentTransaction.getAmount(), paymentTransaction.getCurrency(), paymentTransaction.getCreatedDate(), paymentTransaction.getCreatedDate(), PaymentPluginStatus.UNDEFINED, null, null);
    PaymentTransactionInfoPlugin paymentTransactionInfoPlugin;
    try {
        final PaymentPluginApi paymentPluginApi = paymentPluginServiceRegistration.getPaymentPluginApi(payment.getPaymentMethodId(), false, internalTenantContext);
        final List<PaymentTransactionInfoPlugin> result = paymentPluginApi.getPaymentInfo(payment.getAccountId(), payment.getId(), ImmutableList.<PluginProperty>of(), tenantContext);
        paymentTransactionInfoPlugin = Iterables.tryFind(result, new Predicate<PaymentTransactionInfoPlugin>() {

            @Override
            public boolean apply(final PaymentTransactionInfoPlugin input) {
                return input.getKbTransactionPaymentId().equals(paymentTransaction.getId());
            }
        }).or(new Supplier<PaymentTransactionInfoPlugin>() {

            @Override
            public PaymentTransactionInfoPlugin get() {
                return undefinedPaymentTransaction;
            }
        });
    } catch (final Exception e) {
        paymentTransactionInfoPlugin = undefinedPaymentTransaction;
    }
    return paymentTransactionInfoPlugin;
}
Also used : PaymentPluginApi(org.killbill.billing.payment.plugin.api.PaymentPluginApi) DefaultNoOpPaymentInfoPlugin(org.killbill.billing.payment.provider.DefaultNoOpPaymentInfoPlugin) PaymentModelDao(org.killbill.billing.payment.dao.PaymentModelDao) InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) TenantContext(org.killbill.billing.util.callcontext.TenantContext) PaymentTransactionInfoPlugin(org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin) Supplier(com.google.common.base.Supplier) AccountApiException(org.killbill.billing.account.api.AccountApiException) LockFailedException(org.killbill.commons.locker.LockFailedException)

Example 17 with PaymentModelDao

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

the class PaymentAutomatonDAOHelper method getPayment.

public PaymentModelDao getPayment() throws PaymentApiException {
    final PaymentModelDao paymentModelDao;
    paymentModelDao = paymentDao.getPayment(paymentStateContext.getPaymentId(), internalCallContext);
    if (paymentModelDao == null) {
        throw new PaymentApiException(ErrorCode.PAYMENT_NO_SUCH_PAYMENT, paymentStateContext.getPaymentId());
    }
    return paymentModelDao;
}
Also used : PaymentModelDao(org.killbill.billing.payment.dao.PaymentModelDao) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException)

Example 18 with PaymentModelDao

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

the class IncompletePaymentTransactionTask method tryToProcessNotification.

public void tryToProcessNotification(final JanitorNotificationKey notificationKey, final UUID userToken, final Long accountRecordId, final long tenantRecordId) throws LockFailedException {
    final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContext(tenantRecordId, accountRecordId);
    tryToDoJanitorOperationWithAccountLock(new JanitorIterationCallback() {

        @Override
        public Void doIteration() {
            // State may have changed since we originally retrieved with no lock
            final PaymentTransactionModelDao rehydratedPaymentTransaction = paymentDao.getPaymentTransaction(notificationKey.getUuidKey(), internalTenantContext);
            final TenantContext tenantContext = internalCallContextFactory.createTenantContext(internalTenantContext);
            final PaymentModelDao payment = paymentDao.getPayment(rehydratedPaymentTransaction.getPaymentId(), internalTenantContext);
            final PaymentTransactionInfoPlugin undefinedPaymentTransaction = new DefaultNoOpPaymentInfoPlugin(payment.getId(), rehydratedPaymentTransaction.getId(), rehydratedPaymentTransaction.getTransactionType(), rehydratedPaymentTransaction.getAmount(), rehydratedPaymentTransaction.getCurrency(), rehydratedPaymentTransaction.getCreatedDate(), rehydratedPaymentTransaction.getCreatedDate(), PaymentPluginStatus.UNDEFINED, null, null);
            PaymentTransactionInfoPlugin paymentTransactionInfoPlugin;
            try {
                final PaymentPluginApi paymentPluginApi = paymentPluginServiceRegistration.getPaymentPluginApi(payment.getPaymentMethodId(), false, internalTenantContext);
                final List<PaymentTransactionInfoPlugin> result = paymentPluginApi.getPaymentInfo(payment.getAccountId(), payment.getId(), ImmutableList.<PluginProperty>of(), tenantContext);
                paymentTransactionInfoPlugin = Iterables.tryFind(result, new Predicate<PaymentTransactionInfoPlugin>() {

                    @Override
                    public boolean apply(final PaymentTransactionInfoPlugin input) {
                        return input.getKbTransactionPaymentId().equals(rehydratedPaymentTransaction.getId());
                    }
                }).or(new Supplier<PaymentTransactionInfoPlugin>() {

                    @Override
                    public PaymentTransactionInfoPlugin get() {
                        return undefinedPaymentTransaction;
                    }
                });
            } catch (final Exception e) {
                paymentTransactionInfoPlugin = undefinedPaymentTransaction;
            }
            updatePaymentAndTransactionIfNeeded(payment, notificationKey.getAttemptNumber(), userToken, rehydratedPaymentTransaction, paymentTransactionInfoPlugin, internalTenantContext);
            return null;
        }
    }, internalTenantContext);
}
Also used : DefaultNoOpPaymentInfoPlugin(org.killbill.billing.payment.provider.DefaultNoOpPaymentInfoPlugin) PaymentModelDao(org.killbill.billing.payment.dao.PaymentModelDao) InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) TenantContext(org.killbill.billing.util.callcontext.TenantContext) LockFailedException(org.killbill.commons.locker.LockFailedException) IOException(java.io.IOException) Predicate(com.google.common.base.Predicate) PaymentPluginApi(org.killbill.billing.payment.plugin.api.PaymentPluginApi) PluginProperty(org.killbill.billing.payment.api.PluginProperty) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) PaymentTransactionInfoPlugin(org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List)

Example 19 with PaymentModelDao

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

the class PaymentProcessor method performOperation.

private Payment performOperation(final boolean isApiPayment, final boolean runJanitor, @Nullable final UUID attemptId, final TransactionType transactionType, final Account account, @Nullable final UUID paymentMethodId, @Nullable final UUID paymentId, @Nullable final UUID transactionId, @Nullable final BigDecimal amount, @Nullable final Currency currency, @Nullable final String paymentExternalKey, @Nullable final String paymentTransactionExternalKey, @Nullable final UUID paymentIdForNewPayment, @Nullable final UUID paymentTransactionIdForNewPaymentTransaction, final boolean shouldLockAccountAndDispatch, @Nullable final OperationResult overridePluginOperationResult, final Iterable<PluginProperty> properties, final CallContext callContext, final InternalCallContext internalCallContext) throws PaymentApiException {
    final PaymentStateContext paymentStateContext = paymentAutomatonRunner.buildPaymentStateContext(isApiPayment, transactionType, account, attemptId, paymentMethodId != null ? paymentMethodId : account.getPaymentMethodId(), paymentId, transactionId, paymentExternalKey, paymentTransactionExternalKey, amount, currency, paymentIdForNewPayment, paymentTransactionIdForNewPaymentTransaction, shouldLockAccountAndDispatch, overridePluginOperationResult, properties, callContext, internalCallContext);
    final PaymentAutomatonDAOHelper daoHelper = paymentAutomatonRunner.buildDaoHelper(paymentStateContext, internalCallContext);
    String currentStateName = null;
    if (paymentStateContext.getPaymentId() != null) {
        PaymentModelDao paymentModelDao = daoHelper.getPayment();
        // Sanity: verify the payment belongs to the right account (in case it was looked-up by payment or transaction external key)
        if (!paymentModelDao.getAccountRecordId().equals(internalCallContext.getAccountRecordId())) {
            throw new PaymentApiException(ErrorCode.PAYMENT_DIFFERENT_ACCOUNT_ID, paymentStateContext.getPaymentId());
        }
        // Note: the list needs to be modifiable for invokeJanitor
        final Collection<PaymentTransactionModelDao> paymentTransactionsForCurrentPayment = new LinkedList<PaymentTransactionModelDao>(daoHelper.getPaymentDao().getTransactionsForPayment(paymentStateContext.getPaymentId(), paymentStateContext.getInternalCallContext()));
        // prevent disallowed transitions in case the state couldn't be fixed (or if it's already in a final state).
        if (runJanitor) {
            final PaymentPluginApi plugin = getPaymentProviderPlugin(paymentModelDao.getPaymentMethodId(), true, internalCallContext);
            final List<PaymentTransactionInfoPlugin> pluginTransactions = getPaymentTransactionInfoPlugins(plugin, paymentModelDao, properties, callContext);
            paymentModelDao = invokeJanitor(paymentModelDao, paymentTransactionsForCurrentPayment, pluginTransactions, internalCallContext);
        }
        if (paymentStateContext.getPaymentTransactionExternalKey() != null) {
            final List<PaymentTransactionModelDao> allPaymentTransactionsForKey = daoHelper.getPaymentDao().getPaymentTransactionsByExternalKey(paymentStateContext.getPaymentTransactionExternalKey(), internalCallContext);
            runSanityOnTransactionExternalKey(allPaymentTransactionsForKey, paymentStateContext, internalCallContext);
        }
        if (paymentStateContext.getTransactionId() != null || paymentStateContext.getPaymentTransactionExternalKey() != null) {
            // If a transaction id or key is passed, we are maybe completing an existing transaction (unless a new key was provided)
            PaymentTransactionModelDao transactionToComplete = findTransactionToCompleteAndRunSanityChecks(paymentModelDao, paymentTransactionsForCurrentPayment, paymentStateContext, internalCallContext);
            if (transactionToComplete != null) {
                final UUID transactionToCompleteId = transactionToComplete.getId();
                transactionToComplete = Iterables.<PaymentTransactionModelDao>find(paymentTransactionsForCurrentPayment, new Predicate<PaymentTransactionModelDao>() {

                    @Override
                    public boolean apply(final PaymentTransactionModelDao input) {
                        return transactionToCompleteId.equals(input.getId());
                    }
                });
                // We can't tell where we should be in the state machine - bail (cannot be enforced by the state machine unfortunately because UNKNOWN and PLUGIN_FAILURE are both treated as EXCEPTION)
                if (transactionToComplete.getTransactionStatus() == TransactionStatus.UNKNOWN) {
                    throw new PaymentApiException(ErrorCode.PAYMENT_INVALID_OPERATION, paymentStateContext.getTransactionType(), transactionToComplete.getTransactionStatus());
                }
                paymentStateContext.setPaymentTransactionModelDao(transactionToComplete);
            }
        }
        // Use the original payment method id of the payment being completed
        paymentStateContext.setPaymentMethodId(paymentModelDao.getPaymentMethodId());
        // We always take the last successful state name to permit retries on failures
        currentStateName = paymentModelDao.getLastSuccessStateName();
    }
    final UUID nonNullPaymentId = paymentAutomatonRunner.run(paymentStateContext, daoHelper, currentStateName, transactionType);
    return getPayment(nonNullPaymentId, true, false, properties, callContext, internalCallContext);
}
Also used : PaymentModelDao(org.killbill.billing.payment.dao.PaymentModelDao) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) LinkedList(java.util.LinkedList) Predicate(com.google.common.base.Predicate) PaymentPluginApi(org.killbill.billing.payment.plugin.api.PaymentPluginApi) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) PaymentAutomatonDAOHelper(org.killbill.billing.payment.core.sm.PaymentAutomatonDAOHelper) PaymentStateContext(org.killbill.billing.payment.core.sm.PaymentStateContext) PaymentTransactionInfoPlugin(org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin) UUID(java.util.UUID)

Example 20 with PaymentModelDao

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

the class PaymentRefresher method getPaymentByTransactionExternalKey.

public Payment getPaymentByTransactionExternalKey(final String transactionExternalKey, final boolean withPluginInfo, final boolean withAttempts, final boolean isApiPayment, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
    final List<PaymentTransactionModelDao> paymentTransactionDao = paymentDao.getPaymentTransactionsByExternalKey(transactionExternalKey, internalTenantContext);
    if (paymentTransactionDao.isEmpty()) {
        return null;
    }
    // All transactions must be on the same payment (see sanity in buildPaymentStateContext)
    final PaymentModelDao paymentModelDao = paymentDao.getPayment(paymentTransactionDao.get(0).getPaymentId(), internalTenantContext);
    return toPayment(paymentModelDao, withPluginInfo, withAttempts, isApiPayment, properties, tenantContext, internalTenantContext);
}
Also used : PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) PaymentModelDao(org.killbill.billing.payment.dao.PaymentModelDao)

Aggregations

PaymentModelDao (org.killbill.billing.payment.dao.PaymentModelDao)28 PaymentTransactionModelDao (org.killbill.billing.payment.dao.PaymentTransactionModelDao)21 Test (org.testng.annotations.Test)11 UUID (java.util.UUID)10 PaymentApiException (org.killbill.billing.payment.api.PaymentApiException)9 PaymentTransactionInfoPlugin (org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin)9 Predicate (com.google.common.base.Predicate)8 PaymentAttemptModelDao (org.killbill.billing.payment.dao.PaymentAttemptModelDao)6 PluginProperty (org.killbill.billing.payment.api.PluginProperty)5 LinkedList (java.util.LinkedList)4 State (org.killbill.automaton.State)4 PaymentPluginApi (org.killbill.billing.payment.plugin.api.PaymentPluginApi)4 DefaultNoOpPaymentInfoPlugin (org.killbill.billing.payment.provider.DefaultNoOpPaymentInfoPlugin)4 BigDecimal (java.math.BigDecimal)3 ImmutableList (com.google.common.collect.ImmutableList)2 List (java.util.List)2 DateTime (org.joda.time.DateTime)2 Account (org.killbill.billing.account.api.Account)2 AccountApiException (org.killbill.billing.account.api.AccountApiException)2 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)2