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());
}
});
}
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);
}
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");
}
}
}
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");
}
}
}
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");
}
}
}
Aggregations