Search in sources :

Example 51 with PluginProperty

use of org.killbill.billing.payment.api.PluginProperty in project killbill by killbill.

the class TestEntitlementUtils method testChangePlanIMM.

@Test(groups = "slow", description = "Verify add-ons blocking states are added for IMM change plans")
public void testChangePlanIMM() throws Exception {
    // Approximate check, as the blocking state check (checkBlockingStatesDAO) could be a bit off
    final DateTime changeDateTime = clock.getUTCNow();
    final LocalDate changeDate = clock.getUTCToday();
    // Change plan IMM (upgrade) to Assault-Rifle (Telescopic-Scope is included)
    testListener.pushExpectedEvents(NextEvent.CHANGE, NextEvent.CANCEL, NextEvent.BLOCK);
    final DefaultEntitlement changedBaseEntitlement = (DefaultEntitlement) baseEntitlement.changePlan(new PlanSpecifier("Assault-Rifle", BillingPeriod.MONTHLY, PriceListSet.DEFAULT_PRICELIST_NAME), null, ImmutableList.<PluginProperty>of(), callContext);
    assertListenerStatus();
    // We need to add a 1s delay before invoking the eventsStreamBuilder in the checks below, because
    // the ClockMock truncates milliseconds. Otherwise, utcNow is equal to the changeDateTime, and
    // the change is considered as pending (see DefaultEventsStream#getPendingSubscriptionEvents)
    clock.addDeltaFromReality(1000);
    // Refresh the add-on state
    final DefaultEntitlement cancelledAddOnEntitlement = (DefaultEntitlement) entitlementApi.getEntitlementForId(addOnEntitlement.getId(), callContext);
    // Verify we compute the right blocking states for the "read" path...
    checkFutureBlockingStatesToCancel(changedBaseEntitlement, null, null);
    checkFutureBlockingStatesToCancel(cancelledAddOnEntitlement, null, null);
    checkFutureBlockingStatesToCancel(changedBaseEntitlement, cancelledAddOnEntitlement, null);
    // ...and for the "write" path (which has been exercised in the change call above).
    checkActualBlockingStatesToCancel(changedBaseEntitlement, cancelledAddOnEntitlement, changeDateTime, true);
    // Verify also the blocking states DAO doesn't add too many events (all on disk)
    checkBlockingStatesDAO(changedBaseEntitlement, cancelledAddOnEntitlement, changeDate, false);
    clock.addDays(30);
    // No new event
    assertListenerStatus();
    checkFutureBlockingStatesToCancel(changedBaseEntitlement, null, null);
    checkFutureBlockingStatesToCancel(cancelledAddOnEntitlement, null, null);
    checkFutureBlockingStatesToCancel(changedBaseEntitlement, cancelledAddOnEntitlement, null);
    checkActualBlockingStatesToCancel(changedBaseEntitlement, cancelledAddOnEntitlement, changeDateTime, true);
    checkBlockingStatesDAO(changedBaseEntitlement, cancelledAddOnEntitlement, changeDate, false);
}
Also used : PluginProperty(org.killbill.billing.payment.api.PluginProperty) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime) PlanSpecifier(org.killbill.billing.catalog.api.PlanSpecifier) Test(org.testng.annotations.Test)

Example 52 with PluginProperty

use of org.killbill.billing.payment.api.PluginProperty in project killbill by killbill.

the class TestEntitlementUtils method testCancellationBaseEOTAddOnIMM.

@Test(groups = "slow", description = "Verify add-ons blocking states are not impacted for add-on IMM cancellations")
public void testCancellationBaseEOTAddOnIMM() throws Exception {
    // Cancel the base plan
    final DefaultEntitlement cancelledBaseEntitlement = (DefaultEntitlement) baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.END_OF_TERM, BillingActionPolicy.END_OF_TERM, ImmutableList.<PluginProperty>of(), callContext);
    // No blocking event (EOT)
    assertListenerStatus();
    // Cancel the add-on
    testListener.pushExpectedEvents(NextEvent.CANCEL, NextEvent.BLOCK);
    final DefaultEntitlement cancelledAddOnEntitlement = (DefaultEntitlement) addOnEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.IMMEDIATE, BillingActionPolicy.IMMEDIATE, ImmutableList.<PluginProperty>of(), callContext);
    assertListenerStatus();
    // Verify the blocking states API doesn't mix the dates (all blocking states are on disk)
    checkBlockingStatesDAO(cancelledBaseEntitlement, cancelledAddOnEntitlement, baseEffectiveCancellationOrChangeDate, clock.getUTCToday(), true);
}
Also used : PluginProperty(org.killbill.billing.payment.api.PluginProperty) DefaultEntitlement(org.killbill.billing.entitlement.api.DefaultEntitlement) Test(org.testng.annotations.Test)

Example 53 with PluginProperty

use of org.killbill.billing.payment.api.PluginProperty 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 54 with PluginProperty

use of org.killbill.billing.payment.api.PluginProperty in project killbill by killbill.

the class ControlPluginRunner method executePluginOnSuccessCalls.

public OnSuccessPaymentControlResult executePluginOnSuccessCalls(final Account account, final UUID paymentMethodId, final UUID paymentAttemptId, final UUID paymentId, final String paymentExternalKey, final UUID paymentTransactionId, final String paymentTransactionExternalKey, final PaymentApiType paymentApiType, final TransactionType transactionType, final HPPType hppType, final BigDecimal amount, final Currency currency, final BigDecimal processedAmount, final Currency processedCurrency, final boolean isApiPayment, final List<String> paymentControlPluginNames, final Iterable<PluginProperty> pluginProperties, final CallContext callContext) {
    final PaymentControlContext inputPaymentControlContext = new DefaultPaymentControlContext(account, paymentMethodId, paymentAttemptId, paymentId, paymentExternalKey, paymentTransactionId, paymentTransactionExternalKey, paymentApiType, transactionType, hppType, amount, currency, processedAmount, processedCurrency, isApiPayment, callContext);
    Iterable<PluginProperty> inputPluginProperties = pluginProperties;
    for (final String pluginName : paymentControlPluginNames) {
        final PaymentControlPluginApi plugin = paymentControlPluginRegistry.getServiceForName(pluginName);
        if (plugin != null) {
            try {
                log.debug("Calling onSuccessCall of plugin {}", pluginName);
                final OnSuccessPaymentControlResult result = plugin.onSuccessCall(inputPaymentControlContext, inputPluginProperties);
                log.debug("Successful executed onSuccessCall of plugin {}", pluginName);
                if (result == null) {
                    // Nothing returned by the plugin
                    continue;
                }
                if (result.getAdjustedPluginProperties() != null) {
                    inputPluginProperties = result.getAdjustedPluginProperties();
                }
            // Exceptions from the control plugins are ignored (and logged) because the semantics on what to do are undefined.
            } catch (final PaymentControlApiException e) {
                log.warn("Error during onSuccessCall for plugin='{}', paymentExternalKey='{}'", pluginName, inputPaymentControlContext.getPaymentExternalKey(), e);
            } catch (final RuntimeException e) {
                log.warn("Error during onSuccessCall for plugin='{}', paymentExternalKey='{}'", pluginName, inputPaymentControlContext.getPaymentExternalKey(), e);
            }
        }
    }
    return new DefaultOnSuccessPaymentControlResult(inputPluginProperties);
}
Also used : PluginProperty(org.killbill.billing.payment.api.PluginProperty) DefaultOnSuccessPaymentControlResult(org.killbill.billing.payment.retry.DefaultOnSuccessPaymentControlResult) PaymentControlPluginApi(org.killbill.billing.control.plugin.api.PaymentControlPluginApi) OnSuccessPaymentControlResult(org.killbill.billing.control.plugin.api.OnSuccessPaymentControlResult) DefaultOnSuccessPaymentControlResult(org.killbill.billing.payment.retry.DefaultOnSuccessPaymentControlResult) PaymentControlContext(org.killbill.billing.control.plugin.api.PaymentControlContext) PaymentControlApiException(org.killbill.billing.control.plugin.api.PaymentControlApiException)

Example 55 with PluginProperty

use of org.killbill.billing.payment.api.PluginProperty in project killbill by killbill.

the class PaymentBusEventHandler method processInvoiceEvent.

@AllowConcurrentEvents
@Subscribe
public void processInvoiceEvent(final InvoiceCreationInternalEvent event) {
    log.info("Received invoice creation notification for accountId='{}', invoiceId='{}'", event.getAccountId(), event.getInvoiceId());
    final Collection<PluginProperty> properties = new ArrayList<PluginProperty>();
    final PluginProperty propertyInvoiceId = new PluginProperty(InvoicePaymentControlPluginApi.PROP_IPCD_INVOICE_ID, event.getInvoiceId().toString(), false);
    properties.add(propertyInvoiceId);
    final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContext(event.getSearchKey2(), event.getSearchKey1(), "PaymentRequestProcessor", CallOrigin.INTERNAL, UserType.SYSTEM, event.getUserToken());
    final CallContext callContext = internalCallContextFactory.createCallContext(internalContext);
    // We let the plugin compute how much should be paid
    final BigDecimal amountToBePaid = null;
    final List<String> paymentControlPluginNames = paymentConfig.getPaymentControlPluginNames(internalContext) != null ? new LinkedList<String>(paymentConfig.getPaymentControlPluginNames(internalContext)) : new LinkedList<String>();
    paymentControlPluginNames.add(InvoicePaymentControlPluginApi.PLUGIN_NAME);
    final String transactionType = TransactionType.PURCHASE.name();
    Account account = null;
    Payment payment = null;
    PaymentTransaction paymentTransaction = null;
    try {
        account = accountApi.getAccountById(event.getAccountId(), internalContext);
        logEnterAPICall(log, transactionType, account, account.getPaymentMethodId(), null, null, amountToBePaid, account.getCurrency(), null, null, null, paymentControlPluginNames);
        payment = pluginControlPaymentProcessor.createPurchase(false, account, account.getPaymentMethodId(), null, amountToBePaid, account.getCurrency(), null, null, properties, paymentControlPluginNames, callContext, internalContext);
        paymentTransaction = payment.getTransactions().get(payment.getTransactions().size() - 1);
    } catch (final AccountApiException e) {
        log.warn("Failed to process invoice payment", e);
    } catch (final PaymentApiException e) {
        // Log as warn unless nothing left to be paid
        if (e.getCode() != ErrorCode.PAYMENT_PLUGIN_API_ABORTED.getCode()) {
            log.warn("Failed to process invoice payment {}", e.toString());
        }
    } 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 : Account(org.killbill.billing.account.api.Account) ArrayList(java.util.ArrayList) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) CallContext(org.killbill.billing.util.callcontext.CallContext) BigDecimal(java.math.BigDecimal) PaymentTransaction(org.killbill.billing.payment.api.PaymentTransaction) PluginProperty(org.killbill.billing.payment.api.PluginProperty) Payment(org.killbill.billing.payment.api.Payment) AccountApiException(org.killbill.billing.account.api.AccountApiException) AllowConcurrentEvents(com.google.common.eventbus.AllowConcurrentEvents) Subscribe(com.google.common.eventbus.Subscribe)

Aggregations

PluginProperty (org.killbill.billing.payment.api.PluginProperty)105 UUID (java.util.UUID)45 Account (org.killbill.billing.account.api.Account)42 ApiOperation (io.swagger.annotations.ApiOperation)35 ApiResponses (io.swagger.annotations.ApiResponses)35 Produces (javax.ws.rs.Produces)35 TimedResource (org.killbill.commons.metrics.TimedResource)35 Test (org.testng.annotations.Test)33 Path (javax.ws.rs.Path)32 Payment (org.killbill.billing.payment.api.Payment)30 CallContext (org.killbill.billing.util.callcontext.CallContext)29 ArrayList (java.util.ArrayList)19 LocalDate (org.joda.time.LocalDate)19 Consumes (javax.ws.rs.Consumes)17 BigDecimal (java.math.BigDecimal)16 TenantContext (org.killbill.billing.util.callcontext.TenantContext)15 GET (javax.ws.rs.GET)14 POST (javax.ws.rs.POST)13 DefaultEntitlement (org.killbill.billing.entitlement.api.DefaultEntitlement)13 AccountAuditLogs (org.killbill.billing.util.audit.AccountAuditLogs)13