Search in sources :

Example 41 with Payment

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

the class TestJanitor method testCreateSuccessRefundPaymentControlWithItemAdjustments.

@Test(groups = "slow")
public void testCreateSuccessRefundPaymentControlWithItemAdjustments() throws Exception {
    final BigDecimal requestedAmount = BigDecimal.TEN;
    final UUID subscriptionId = UUID.randomUUID();
    final UUID bundleId = UUID.randomUUID();
    final LocalDate now = clock.getUTCToday();
    testListener.pushExpectedEvent(NextEvent.INVOICE);
    final Invoice invoice = testHelper.createTestInvoice(account, now, Currency.USD);
    testListener.assertListenerStatus();
    final String paymentExternalKey = invoice.getId().toString();
    final String transactionExternalKey = "craboom";
    final String transactionExternalKey2 = "qwerty";
    final InvoiceItem invoiceItem = new MockRecurringInvoiceItem(invoice.getId(), account.getId(), subscriptionId, bundleId, "test plan", "test phase", null, now, now.plusMonths(1), requestedAmount, new BigDecimal("1.0"), Currency.USD);
    invoice.addInvoiceItem(invoiceItem);
    testListener.pushExpectedEvent(NextEvent.PAYMENT);
    final Payment payment = paymentApi.createPurchaseWithPaymentControl(account, account.getPaymentMethodId(), null, requestedAmount, Currency.USD, paymentExternalKey, transactionExternalKey, createPropertiesForInvoice(invoice), INVOICE_PAYMENT, callContext);
    testListener.assertListenerStatus();
    final List<PluginProperty> refundProperties = new ArrayList<PluginProperty>();
    final HashMap<UUID, BigDecimal> uuidBigDecimalHashMap = new HashMap<UUID, BigDecimal>();
    uuidBigDecimalHashMap.put(invoiceItem.getId(), new BigDecimal("1.0"));
    final PluginProperty refundIdsProp = new PluginProperty(InvoicePaymentControlPluginApi.PROP_IPCD_REFUND_IDS_WITH_AMOUNT_KEY, uuidBigDecimalHashMap, false);
    refundProperties.add(refundIdsProp);
    testListener.pushExpectedEvent(NextEvent.PAYMENT);
    final Payment payment2 = paymentApi.createRefundWithPaymentControl(account, payment.getId(), null, Currency.USD, transactionExternalKey2, refundProperties, INVOICE_PAYMENT, callContext);
    testListener.assertListenerStatus();
    assertEquals(payment2.getTransactions().size(), 2);
    PaymentTransaction refundTransaction = payment2.getTransactions().get(1);
    assertEquals(refundTransaction.getTransactionType(), TransactionType.REFUND);
    final List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
    assertEquals(attempts.size(), 2);
    final PaymentAttemptModelDao refundAttempt = attempts.get(1);
    assertEquals(refundAttempt.getTransactionType(), TransactionType.REFUND);
    // Ok now the fun part starts... we modify the attempt state to be 'INIT' and wait the the Janitor to do its job.
    paymentDao.updatePaymentAttempt(refundAttempt.getId(), refundAttempt.getTransactionId(), "INIT", internalCallContext);
    final PaymentAttemptModelDao attempt2 = paymentDao.getPaymentAttempt(refundAttempt.getId(), internalCallContext);
    assertEquals(attempt2.getStateName(), "INIT");
    clock.addDays(1);
    await().atMost(TIMEOUT, TimeUnit.SECONDS).until(new Callable<Boolean>() {

        @Override
        public Boolean call() throws Exception {
            final PaymentAttemptModelDao attempt3 = paymentDao.getPaymentAttempt(refundAttempt.getId(), internalCallContext);
            return "SUCCESS".equals(attempt3.getStateName());
        }
    });
}
Also used : PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) Invoice(org.killbill.billing.invoice.api.Invoice) InvoiceItem(org.killbill.billing.invoice.api.InvoiceItem) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) InvoiceApiException(org.killbill.billing.invoice.api.InvoiceApiException) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) EventBusException(org.killbill.bus.api.PersistentBus.EventBusException) PaymentTransaction(org.killbill.billing.payment.api.PaymentTransaction) PluginProperty(org.killbill.billing.payment.api.PluginProperty) Payment(org.killbill.billing.payment.api.Payment) UUID(java.util.UUID) Test(org.testng.annotations.Test)

Example 42 with Payment

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

the class TestJanitor method testUnknownEntries.

@Test(groups = "slow")
public void testUnknownEntries() throws PaymentApiException, InvoiceApiException, EventBusException {
    final BigDecimal requestedAmount = BigDecimal.TEN;
    final String paymentExternalKey = "qwru";
    final String transactionExternalKey = "lkjdsf";
    testListener.pushExpectedEvent(NextEvent.PAYMENT);
    final Payment payment = paymentApi.createAuthorization(account, account.getPaymentMethodId(), null, requestedAmount, account.getCurrency(), paymentExternalKey, transactionExternalKey, ImmutableList.<PluginProperty>of(), callContext);
    testListener.assertListenerStatus();
    // Artificially move the transaction status to UNKNOWN
    final String paymentStateName = paymentSMHelper.getErroredStateForTransaction(TransactionType.AUTHORIZE).toString();
    testListener.pushExpectedEvent(NextEvent.PAYMENT_PLUGIN_ERROR);
    paymentDao.updatePaymentAndTransactionOnCompletion(account.getId(), null, payment.getId(), TransactionType.AUTHORIZE, paymentStateName, paymentStateName, payment.getTransactions().get(0).getId(), TransactionStatus.UNKNOWN, requestedAmount, account.getCurrency(), "foo", "bar", internalCallContext);
    testListener.assertListenerStatus();
    // Move clock for notification to be processed
    testListener.pushExpectedEvent(NextEvent.PAYMENT);
    clock.addDeltaFromReality(5 * 60 * 1000);
    assertNotificationsCompleted(internalCallContext, 5);
    testListener.assertListenerStatus();
    final Payment updatedPayment = paymentApi.getPayment(payment.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
    assertEquals(updatedPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS);
}
Also used : Payment(org.killbill.billing.payment.api.Payment) BigDecimal(java.math.BigDecimal) Test(org.testng.annotations.Test)

Example 43 with Payment

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

the class TestRetryService method testAbortedPayment.

@Test(groups = "fast")
public void testAbortedPayment() throws Exception {
    final Account account = testHelper.createTestAccount("yiyi.gmail.com", true);
    final Invoice invoice = testHelper.createTestInvoice(account, clock.getUTCToday(), Currency.USD);
    final BigDecimal amount = new BigDecimal("10.00");
    final UUID subscriptionId = UUID.randomUUID();
    final UUID bundleId = UUID.randomUUID();
    final LocalDate startDate = clock.getUTCToday();
    final LocalDate endDate = startDate.plusMonths(1);
    invoice.addInvoiceItem(new MockRecurringInvoiceItem(invoice.getId(), account.getId(), subscriptionId, bundleId, "test plan", "test phase", null, startDate, endDate, amount, new BigDecimal("1.0"), Currency.USD));
    setPaymentFailure(FailureType.PAYMENT_FAILURE);
    final String paymentExternalKey = UUID.randomUUID().toString();
    final String transactionExternalKey = UUID.randomUUID().toString();
    pluginControlPaymentProcessor.createPurchase(false, account, account.getPaymentMethodId(), null, amount, Currency.USD, paymentExternalKey, transactionExternalKey, createPropertiesForInvoice(invoice), ImmutableList.<String>of(InvoicePaymentControlPluginApi.PLUGIN_NAME), callContext, internalCallContext);
    Payment payment = getPaymentForExternalKey(paymentExternalKey);
    List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
    assertEquals(attempts.size(), 1);
    final List<PaymentTransactionModelDao> transactions = paymentDao.getTransactionsForPayment(payment.getId(), internalCallContext);
    assertEquals(transactions.size(), 1);
    int maxTries = paymentConfig.getPaymentFailureRetryDays(internalCallContext).size();
    for (int curFailure = 0; curFailure < maxTries; curFailure++) {
        // Set plugin to fail with specific type unless this is the last attempt and we want a success
        setPaymentFailure(FailureType.PAYMENT_FAILURE);
        moveClockForFailureType(FailureType.PAYMENT_FAILURE, curFailure);
        final int curFailureCondition = curFailure;
        try {
            await().atMost(TIMEOUT, SECONDS).until(new Callable<Boolean>() {

                @Override
                public Boolean call() throws Exception {
                    final List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
                    final List<PaymentAttemptModelDao> filteredAttempts = ImmutableList.copyOf(Iterables.filter(attempts, new Predicate<PaymentAttemptModelDao>() {

                        @Override
                        public boolean apply(final PaymentAttemptModelDao input) {
                            return input.getStateName().equals("SUCCESS") || input.getStateName().equals("RETRIED") || input.getStateName().equals("ABORTED");
                        }
                    }));
                    return filteredAttempts.size() == curFailureCondition + 2;
                }
            });
        } catch (final TimeoutException e) {
            fail("Timeout curFailure = " + curFailureCondition);
        }
    }
    attempts = paymentDao.getPaymentAttempts(payment.getExternalKey(), internalCallContext);
    final int expectedAttempts = maxTries + 1;
    assertEquals(attempts.size(), expectedAttempts);
    Collections.sort(attempts, new Comparator<PaymentAttemptModelDao>() {

        @Override
        public int compare(final PaymentAttemptModelDao o1, final PaymentAttemptModelDao o2) {
            return o1.getCreatedDate().compareTo(o2.getCreatedDate());
        }
    });
    for (int i = 0; i < attempts.size(); i++) {
        final PaymentAttemptModelDao cur = attempts.get(i);
        if (i < attempts.size() - 1) {
            assertEquals(cur.getStateName(), "RETRIED");
        } else {
            assertEquals(cur.getStateName(), "ABORTED");
        }
    }
}
Also used : PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) Account(org.killbill.billing.account.api.Account) Invoice(org.killbill.billing.invoice.api.Invoice) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) TimeoutException(java.util.concurrent.TimeoutException) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) Payment(org.killbill.billing.payment.api.Payment) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) UUID(java.util.UUID) TimeoutException(java.util.concurrent.TimeoutException) Test(org.testng.annotations.Test)

Example 44 with Payment

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

the class TestRetryService method testFailedPaymentWithOneSuccessfulRetry.

@Test(groups = "fast")
public void testFailedPaymentWithOneSuccessfulRetry() throws Exception {
    final Account account = testHelper.createTestAccount("yiyi.gmail.com", true);
    final Invoice invoice = testHelper.createTestInvoice(account, clock.getUTCToday(), Currency.USD);
    final BigDecimal amount = new BigDecimal("10.00");
    final UUID subscriptionId = UUID.randomUUID();
    final UUID bundleId = UUID.randomUUID();
    final LocalDate startDate = clock.getUTCToday();
    final LocalDate endDate = startDate.plusMonths(1);
    invoice.addInvoiceItem(new MockRecurringInvoiceItem(invoice.getId(), account.getId(), subscriptionId, bundleId, "test plan", "test phase", null, startDate, endDate, amount, new BigDecimal("1.0"), Currency.USD));
    setPaymentFailure(FailureType.PAYMENT_FAILURE);
    final String paymentExternalKey = UUID.randomUUID().toString();
    final String transactionExternalKey = UUID.randomUUID().toString();
    pluginControlPaymentProcessor.createPurchase(false, account, account.getPaymentMethodId(), null, amount, Currency.USD, paymentExternalKey, transactionExternalKey, createPropertiesForInvoice(invoice), ImmutableList.<String>of(InvoicePaymentControlPluginApi.PLUGIN_NAME), callContext, internalCallContext);
    Payment payment = getPaymentForExternalKey(paymentExternalKey);
    List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
    assertEquals(attempts.size(), 1);
    final List<PaymentTransactionModelDao> transactions = paymentDao.getTransactionsForPayment(payment.getId(), internalCallContext);
    assertEquals(transactions.size(), 1);
    moveClockForFailureType(FailureType.PAYMENT_FAILURE, 0);
    try {
        await().atMost(TIMEOUT, SECONDS).until(new Callable<Boolean>() {

            @Override
            public Boolean call() throws Exception {
                final List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
                final List<PaymentAttemptModelDao> filteredAttempts = ImmutableList.copyOf(Iterables.filter(attempts, new Predicate<PaymentAttemptModelDao>() {

                    @Override
                    public boolean apply(final PaymentAttemptModelDao input) {
                        return input.getStateName().equals("SUCCESS") || input.getStateName().equals("RETRIED") || input.getStateName().equals("ABORTED");
                    }
                }));
                return filteredAttempts.size() == 2;
            }
        });
    } catch (final TimeoutException e) {
        fail("Timeout ");
    }
    attempts = paymentDao.getPaymentAttempts(payment.getExternalKey(), internalCallContext);
    final int expectedAttempts = 2;
    assertEquals(attempts.size(), expectedAttempts);
    Collections.sort(attempts, new Comparator<PaymentAttemptModelDao>() {

        @Override
        public int compare(final PaymentAttemptModelDao o1, final PaymentAttemptModelDao o2) {
            return o1.getCreatedDate().compareTo(o2.getCreatedDate());
        }
    });
    for (int i = 0; i < attempts.size(); i++) {
        final PaymentAttemptModelDao cur = attempts.get(i);
        if (i < attempts.size() - 1) {
            assertEquals(cur.getStateName(), "RETRIED");
        } else {
            assertEquals(cur.getStateName(), "SUCCESS");
        }
    }
}
Also used : PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) Account(org.killbill.billing.account.api.Account) Invoice(org.killbill.billing.invoice.api.Invoice) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) TimeoutException(java.util.concurrent.TimeoutException) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) Payment(org.killbill.billing.payment.api.Payment) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) UUID(java.util.UUID) TimeoutException(java.util.concurrent.TimeoutException) Test(org.testng.annotations.Test)

Example 45 with Payment

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

the class TestRetryService method testFailedPaymentWithLastRetrySuccess.

@Test(groups = "fast")
public void testFailedPaymentWithLastRetrySuccess() throws Exception {
    final Account account = testHelper.createTestAccount("yiyi.gmail.com", true);
    final Invoice invoice = testHelper.createTestInvoice(account, clock.getUTCToday(), Currency.USD);
    final BigDecimal amount = new BigDecimal("10.00");
    final UUID subscriptionId = UUID.randomUUID();
    final UUID bundleId = UUID.randomUUID();
    final LocalDate startDate = clock.getUTCToday();
    final LocalDate endDate = startDate.plusMonths(1);
    invoice.addInvoiceItem(new MockRecurringInvoiceItem(invoice.getId(), account.getId(), subscriptionId, bundleId, "test plan", "test phase", null, startDate, endDate, amount, new BigDecimal("1.0"), Currency.USD));
    setPaymentFailure(FailureType.PAYMENT_FAILURE);
    final String paymentExternalKey = UUID.randomUUID().toString();
    final String transactionExternalKey = UUID.randomUUID().toString();
    pluginControlPaymentProcessor.createPurchase(false, account, account.getPaymentMethodId(), null, amount, Currency.USD, paymentExternalKey, transactionExternalKey, createPropertiesForInvoice(invoice), ImmutableList.<String>of(InvoicePaymentControlPluginApi.PLUGIN_NAME), callContext, internalCallContext);
    Payment payment = getPaymentForExternalKey(paymentExternalKey);
    List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
    assertEquals(attempts.size(), 1);
    final List<PaymentTransactionModelDao> transactions = paymentDao.getTransactionsForPayment(payment.getId(), internalCallContext);
    assertEquals(transactions.size(), 1);
    int maxTries = paymentConfig.getPaymentFailureRetryDays(internalCallContext).size();
    for (int curFailure = 0; curFailure < maxTries; curFailure++) {
        // Set plugin to fail with specific type unless this is the last attempt and we want a success
        if (curFailure < (maxTries - 1)) {
            setPaymentFailure(FailureType.PAYMENT_FAILURE);
        }
        moveClockForFailureType(FailureType.PAYMENT_FAILURE, curFailure);
        final int curFailureCondition = curFailure;
        try {
            await().atMost(TIMEOUT, SECONDS).until(new Callable<Boolean>() {

                @Override
                public Boolean call() throws Exception {
                    final List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
                    final List<PaymentAttemptModelDao> filteredAttempts = ImmutableList.copyOf(Iterables.filter(attempts, new Predicate<PaymentAttemptModelDao>() {

                        @Override
                        public boolean apply(final PaymentAttemptModelDao input) {
                            return input.getStateName().equals("SUCCESS") || input.getStateName().equals("RETRIED") || input.getStateName().equals("ABORTED");
                        }
                    }));
                    return filteredAttempts.size() == curFailureCondition + 2;
                }
            });
        } catch (final TimeoutException e) {
            fail("Timeout curFailure = " + curFailureCondition);
        }
    }
    attempts = paymentDao.getPaymentAttempts(payment.getExternalKey(), internalCallContext);
    final int expectedAttempts = maxTries + 1;
    assertEquals(attempts.size(), expectedAttempts);
    Collections.sort(attempts, new Comparator<PaymentAttemptModelDao>() {

        @Override
        public int compare(final PaymentAttemptModelDao o1, final PaymentAttemptModelDao o2) {
            return o1.getCreatedDate().compareTo(o2.getCreatedDate());
        }
    });
    for (int i = 0; i < attempts.size(); i++) {
        final PaymentAttemptModelDao cur = attempts.get(i);
        if (i < attempts.size() - 1) {
            assertEquals(cur.getStateName(), "RETRIED");
        } else {
            assertEquals(cur.getStateName(), "SUCCESS");
        }
    }
}
Also used : PaymentAttemptModelDao(org.killbill.billing.payment.dao.PaymentAttemptModelDao) Account(org.killbill.billing.account.api.Account) Invoice(org.killbill.billing.invoice.api.Invoice) LocalDate(org.joda.time.LocalDate) BigDecimal(java.math.BigDecimal) TimeoutException(java.util.concurrent.TimeoutException) PaymentApiException(org.killbill.billing.payment.api.PaymentApiException) Payment(org.killbill.billing.payment.api.Payment) PaymentTransactionModelDao(org.killbill.billing.payment.dao.PaymentTransactionModelDao) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) UUID(java.util.UUID) TimeoutException(java.util.concurrent.TimeoutException) Test(org.testng.annotations.Test)

Aggregations

Payment (org.killbill.billing.payment.api.Payment)75 Test (org.testng.annotations.Test)42 Account (org.killbill.billing.account.api.Account)40 UUID (java.util.UUID)39 BigDecimal (java.math.BigDecimal)32 PluginProperty (org.killbill.billing.payment.api.PluginProperty)30 Invoice (org.killbill.billing.invoice.api.Invoice)27 LocalDate (org.joda.time.LocalDate)24 ApiOperation (io.swagger.annotations.ApiOperation)20 ApiResponses (io.swagger.annotations.ApiResponses)20 Produces (javax.ws.rs.Produces)20 Path (javax.ws.rs.Path)19 TimedResource (org.killbill.commons.metrics.TimedResource)19 DefaultEntitlement (org.killbill.billing.entitlement.api.DefaultEntitlement)17 InvoicePayment (org.killbill.billing.invoice.api.InvoicePayment)15 CallContext (org.killbill.billing.util.callcontext.CallContext)15 AccountData (org.killbill.billing.account.api.AccountData)14 GET (javax.ws.rs.GET)13 DateTime (org.joda.time.DateTime)13 PaymentApiException (org.killbill.billing.payment.api.PaymentApiException)13