Search in sources :

Example 51 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class IncompletePaymentTransactionTask method updatePaymentAndTransactionInternal.

private boolean updatePaymentAndTransactionInternal(final PaymentModelDao payment, @Nullable final Integer attemptNumber, @Nullable final UUID userToken, final PaymentTransactionModelDao paymentTransaction, final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin, final InternalTenantContext internalTenantContext) {
    final CallContext callContext = createCallContext("IncompletePaymentTransactionTask", internalTenantContext);
    // First obtain the new transactionStatus,
    // Then compute the new paymentState; this one is mostly interesting in case of success (to compute the lastSuccessPaymentState below)
    final TransactionStatus transactionStatus = computeNewTransactionStatusFromPaymentTransactionInfoPlugin(paymentTransactionInfoPlugin, paymentTransaction.getTransactionStatus());
    final String newPaymentState;
    switch(transactionStatus) {
        case PENDING:
            newPaymentState = paymentStateMachineHelper.getPendingStateForTransaction(paymentTransaction.getTransactionType());
            break;
        case SUCCESS:
            newPaymentState = paymentStateMachineHelper.getSuccessfulStateForTransaction(paymentTransaction.getTransactionType());
            break;
        case PAYMENT_FAILURE:
            newPaymentState = paymentStateMachineHelper.getFailureStateForTransaction(paymentTransaction.getTransactionType());
            break;
        case PLUGIN_FAILURE:
            newPaymentState = paymentStateMachineHelper.getErroredStateForTransaction(paymentTransaction.getTransactionType());
            break;
        case UNKNOWN:
        default:
            if (transactionStatus != paymentTransaction.getTransactionStatus()) {
                log.info("Unable to repair paymentId='{}', paymentTransactionId='{}', currentTransactionStatus='{}', newTransactionStatus='{}'", payment.getId(), paymentTransaction.getId(), paymentTransaction.getTransactionStatus(), transactionStatus);
            }
            // We can't get anything interesting from the plugin...
            insertNewNotificationForUnresolvedTransactionIfNeeded(paymentTransaction.getId(), attemptNumber, userToken, internalTenantContext.getAccountRecordId(), internalTenantContext.getTenantRecordId());
            return false;
    }
    // Our status did not change, so we just insert a new notification (attemptNumber will be incremented)
    if (transactionStatus == paymentTransaction.getTransactionStatus()) {
        log.debug("Janitor IncompletePaymentTransactionTask repairing payment {}, transaction {}, transitioning transactionStatus from {} -> {}", payment.getId(), paymentTransaction.getId(), paymentTransaction.getTransactionStatus(), transactionStatus);
        insertNewNotificationForUnresolvedTransactionIfNeeded(paymentTransaction.getId(), attemptNumber, userToken, internalTenantContext.getAccountRecordId(), internalTenantContext.getTenantRecordId());
        return false;
    }
    // Recompute new lastSuccessPaymentState. This is important to be able to allow new operations on the state machine (for e.g an AUTH_SUCCESS would now allow a CAPTURE operation)
    final String lastSuccessPaymentState = paymentStateMachineHelper.isSuccessState(newPaymentState) ? newPaymentState : null;
    // Update processedAmount and processedCurrency
    final BigDecimal processedAmount;
    if (TransactionStatus.SUCCESS.equals(transactionStatus) || TransactionStatus.PENDING.equals(transactionStatus)) {
        if (paymentTransactionInfoPlugin == null || paymentTransactionInfoPlugin.getAmount() == null) {
            processedAmount = paymentTransaction.getProcessedAmount();
        } else {
            processedAmount = paymentTransactionInfoPlugin.getAmount();
        }
    } else {
        processedAmount = BigDecimal.ZERO;
    }
    final Currency processedCurrency;
    if (paymentTransactionInfoPlugin == null || paymentTransactionInfoPlugin.getCurrency() == null) {
        processedCurrency = paymentTransaction.getProcessedCurrency();
    } else {
        processedCurrency = paymentTransactionInfoPlugin.getCurrency();
    }
    // Update the gatewayErrorCode, gatewayError if we got a paymentTransactionInfoPlugin
    final String gatewayErrorCode = paymentTransactionInfoPlugin != null ? paymentTransactionInfoPlugin.getGatewayErrorCode() : paymentTransaction.getGatewayErrorCode();
    final String gatewayError = paymentTransactionInfoPlugin != null ? paymentTransactionInfoPlugin.getGatewayError() : paymentTransaction.getGatewayErrorMsg();
    log.info("Repairing paymentId='{}', paymentTransactionId='{}', currentTransactionStatus='{}', newTransactionStatus='{}'", payment.getId(), paymentTransaction.getId(), paymentTransaction.getTransactionStatus(), transactionStatus);
    final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(payment.getAccountId(), callContext);
    paymentDao.updatePaymentAndTransactionOnCompletion(payment.getAccountId(), paymentTransaction.getAttemptId(), payment.getId(), paymentTransaction.getTransactionType(), newPaymentState, lastSuccessPaymentState, paymentTransaction.getId(), transactionStatus, processedAmount, processedCurrency, gatewayErrorCode, gatewayError, internalCallContext);
    return true;
}
Also used : Currency(org.killbill.billing.catalog.api.Currency) TransactionStatus(org.killbill.billing.payment.api.TransactionStatus) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) CallContext(org.killbill.billing.util.callcontext.CallContext) BigDecimal(java.math.BigDecimal)

Example 52 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext 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 53 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class DefaultPaymentApi method createChargebackReversalWithPaymentControl.

@Override
public Payment createChargebackReversalWithPaymentControl(final Account account, final UUID paymentId, final String paymentTransactionExternalKey, final PaymentOptions paymentOptions, final CallContext callContext) throws PaymentApiException {
    final List<String> paymentControlPluginNames = toPaymentControlPluginNames(paymentOptions, callContext);
    if (paymentControlPluginNames.isEmpty()) {
        return createChargebackReversal(account, paymentId, paymentTransactionExternalKey, callContext);
    }
    checkNotNullParameter(account, "account");
    checkNotNullParameter(paymentId, "paymentId");
    checkExternalKeyLength(paymentTransactionExternalKey);
    final String transactionType = TransactionType.CHARGEBACK.name();
    Payment payment = null;
    PaymentTransaction paymentTransaction = null;
    PaymentApiException exception = null;
    try {
        logEnterAPICall(log, transactionType, account, null, paymentId, null, null, null, null, paymentTransactionExternalKey, null, paymentControlPluginNames);
        final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
        payment = pluginControlPaymentProcessor.createChargebackReversal(IS_API_PAYMENT, account, paymentId, paymentTransactionExternalKey, paymentControlPluginNames, callContext, internalCallContext);
        // See https://github.com/killbill/killbill/issues/552
        paymentTransaction = Iterables.<PaymentTransaction>find(Lists.<PaymentTransaction>reverse(payment.getTransactions()), new Predicate<PaymentTransaction>() {

            @Override
            public boolean apply(final PaymentTransaction input) {
                return paymentTransactionExternalKey.equals(input.getExternalKey());
            }
        });
        return payment;
    } catch (PaymentApiException e) {
        exception = e;
        throw 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, exception);
    }
}
Also used : InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) Predicate(com.google.common.base.Predicate)

Example 54 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class DefaultPaymentApi method refreshPaymentMethods.

@Override
public List<PaymentMethod> refreshPaymentMethods(final Account account, final Iterable<PluginProperty> properties, final CallContext context) throws PaymentApiException {
    final InternalCallContext callContext = internalCallContextFactory.createInternalCallContext(account.getId(), context);
    final List<PaymentMethod> paymentMethods = new LinkedList<PaymentMethod>();
    for (final String pluginName : paymentMethodProcessor.getAvailablePlugins()) {
        paymentMethods.addAll(paymentMethodProcessor.refreshPaymentMethods(pluginName, account, properties, context, callContext));
    }
    return paymentMethods;
}
Also used : InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) LinkedList(java.util.LinkedList)

Example 55 with InternalCallContext

use of org.killbill.billing.callcontext.InternalCallContext in project killbill by killbill.

the class DefaultPaymentApi method createCaptureWithPaymentControl.

@Override
public Payment createCaptureWithPaymentControl(final Account account, final UUID paymentId, final BigDecimal amount, final Currency currency, @Nullable final String paymentTransactionExternalKey, final Iterable<PluginProperty> properties, final PaymentOptions paymentOptions, final CallContext callContext) throws PaymentApiException {
    final List<String> paymentControlPluginNames = toPaymentControlPluginNames(paymentOptions, callContext);
    if (paymentControlPluginNames.isEmpty()) {
        return createCapture(account, paymentId, amount, currency, paymentTransactionExternalKey, properties, callContext);
    }
    checkNotNullParameter(account, "account");
    checkNotNullParameter(paymentId, "paymentId");
    checkNotNullParameter(amount, "amount");
    checkNotNullParameter(currency, "currency");
    checkNotNullParameter(properties, "plugin properties");
    checkExternalKeyLength(paymentTransactionExternalKey);
    final String transactionType = TransactionType.CAPTURE.name();
    Payment payment = null;
    PaymentTransaction paymentTransaction = null;
    PaymentApiException exception = null;
    try {
        logEnterAPICall(log, transactionType, account, null, paymentId, null, amount, currency, null, paymentTransactionExternalKey, null, paymentControlPluginNames);
        final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
        payment = pluginControlPaymentProcessor.createCapture(IS_API_PAYMENT, account, paymentId, amount, currency, paymentTransactionExternalKey, properties, paymentControlPluginNames, callContext, internalCallContext);
        paymentTransaction = findPaymentTransaction(payment, paymentTransactionExternalKey);
        return payment;
    } catch (PaymentApiException e) {
        exception = e;
        throw 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, exception);
    }
}
Also used : InternalCallContext(org.killbill.billing.callcontext.InternalCallContext)

Aggregations

InternalCallContext (org.killbill.billing.callcontext.InternalCallContext)110 PlanPhasePriceOverride (org.killbill.billing.catalog.api.PlanPhasePriceOverride)26 DateTime (org.joda.time.DateTime)25 UUID (java.util.UUID)24 ArrayList (java.util.ArrayList)21 SubscriptionBaseApiException (org.killbill.billing.subscription.api.user.SubscriptionBaseApiException)17 InvoiceApiException (org.killbill.billing.invoice.api.InvoiceApiException)14 CallContext (org.killbill.billing.util.callcontext.CallContext)14 CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)13 WithEntitlementPlugin (org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin)13 EntitlementContext (org.killbill.billing.entitlement.plugin.api.EntitlementContext)13 AccountApiException (org.killbill.billing.account.api.AccountApiException)12 DefaultBlockingState (org.killbill.billing.junction.DefaultBlockingState)12 NotificationEvent (org.killbill.notificationq.api.NotificationEvent)9 BigDecimal (java.math.BigDecimal)8 LinkedList (java.util.LinkedList)8 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)8 Invoice (org.killbill.billing.invoice.api.Invoice)8 AllowConcurrentEvents (com.google.common.eventbus.AllowConcurrentEvents)7 Subscribe (com.google.common.eventbus.Subscribe)7