use of org.killbill.billing.payment.dao.PaymentAttemptModelDao in project killbill by killbill.
the class PaymentProcessor method getPaymentAttempts.
private List<PaymentAttempt> getPaymentAttempts(final List<PaymentAttemptModelDao> pastPaymentAttempts, final InternalTenantContext internalTenantContext) {
List<PaymentAttempt> paymentAttempts = new ArrayList<PaymentAttempt>();
// Add Past Payment Attempts
for (PaymentAttemptModelDao pastPaymentAttempt : pastPaymentAttempts) {
DefaultPaymentAttempt paymentAttempt = new DefaultPaymentAttempt(pastPaymentAttempt.getAccountId(), pastPaymentAttempt.getPaymentMethodId(), pastPaymentAttempt.getId(), pastPaymentAttempt.getCreatedDate(), pastPaymentAttempt.getUpdatedDate(), pastPaymentAttempt.getCreatedDate(), pastPaymentAttempt.getPaymentExternalKey(), pastPaymentAttempt.getTransactionId(), pastPaymentAttempt.getTransactionExternalKey(), pastPaymentAttempt.getTransactionType(), pastPaymentAttempt.getStateName(), pastPaymentAttempt.getAmount(), pastPaymentAttempt.getCurrency(), pastPaymentAttempt.getPluginName(), buildPluginProperties(pastPaymentAttempt));
paymentAttempts.add(paymentAttempt);
}
// Get Future Payment Attempts from Notification Queue and add them to the list
try {
final NotificationQueue retryQueue = notificationQueueService.getNotificationQueue(DefaultPaymentService.SERVICE_NAME, DefaultRetryService.QUEUE_NAME);
final Iterable<NotificationEventWithMetadata<NotificationEvent>> notificationEventWithMetadatas = retryQueue.getFutureNotificationForSearchKeys(internalTenantContext.getAccountRecordId(), internalTenantContext.getTenantRecordId());
for (final NotificationEventWithMetadata<NotificationEvent> notificationEvent : notificationEventWithMetadatas) {
// Last Attempt
PaymentAttemptModelDao lastPaymentAttempt = getLastPaymentAttempt(pastPaymentAttempts, ((PaymentRetryNotificationKey) notificationEvent.getEvent()).getAttemptId());
if (lastPaymentAttempt != null) {
DefaultPaymentAttempt futurePaymentAttempt = new DefaultPaymentAttempt(// accountId
lastPaymentAttempt.getAccountId(), // paymentMethodId
lastPaymentAttempt.getPaymentMethodId(), // id
((PaymentRetryNotificationKey) notificationEvent.getEvent()).getAttemptId(), // createdDate
null, // updatedDate
null, // effectiveDate
notificationEvent.getEffectiveDate(), // paymentExternalKey
lastPaymentAttempt.getPaymentExternalKey(), // transactionId
null, // transactionExternalKey
lastPaymentAttempt.getTransactionExternalKey(), // transactionType
lastPaymentAttempt.getTransactionType(), // stateName
SCHEDULED, // amount
lastPaymentAttempt.getAmount(), // currency
lastPaymentAttempt.getCurrency(), // pluginName,
((PaymentRetryNotificationKey) notificationEvent.getEvent()).getPaymentControlPluginNames().get(0), // pluginProperties
buildPluginProperties(lastPaymentAttempt));
paymentAttempts.add(futurePaymentAttempt);
}
}
} catch (NoSuchNotificationQueue noSuchNotificationQueue) {
log.error("ERROR Loading Notification Queue - " + noSuchNotificationQueue.getMessage());
}
return paymentAttempts;
}
use of org.killbill.billing.payment.dao.PaymentAttemptModelDao in project killbill by killbill.
the class TestDefaultAdminPaymentApi method testFixPaymentTransactionState.
@Test(groups = "slow")
public void testFixPaymentTransactionState() throws PaymentApiException {
final PaymentOptions paymentOptions = new PaymentOptions() {
@Override
public boolean isExternalPayment() {
return false;
}
@Override
public List<String> getPaymentControlPluginNames() {
return ImmutableList.<String>of(MockPaymentControlProviderPlugin.PLUGIN_NAME);
}
};
final Payment payment = paymentApi.createAuthorizationWithPaymentControl(account, account.getPaymentMethodId(), null, BigDecimal.TEN, Currency.EUR, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), paymentOptions, callContext);
Assert.assertEquals(payment.getTransactions().size(), 1);
final PaymentModelDao paymentModelDao = paymentDao.getPayment(payment.getId(), internalCallContext);
final PaymentTransactionModelDao paymentTransactionModelDao = paymentDao.getPaymentTransaction(payment.getTransactions().get(0).getId(), internalCallContext);
Assert.assertEquals(paymentModelDao.getStateName(), "AUTH_SUCCESS");
Assert.assertEquals(paymentModelDao.getLastSuccessStateName(), "AUTH_SUCCESS");
Assert.assertEquals(paymentTransactionModelDao.getTransactionStatus(), TransactionStatus.SUCCESS);
Assert.assertEquals(paymentTransactionModelDao.getProcessedAmount().compareTo(BigDecimal.TEN), 0);
Assert.assertEquals(paymentTransactionModelDao.getProcessedCurrency(), Currency.EUR);
Assert.assertEquals(paymentTransactionModelDao.getGatewayErrorCode(), "");
Assert.assertEquals(paymentTransactionModelDao.getGatewayErrorMsg(), "");
final List<PaymentAttemptModelDao> paymentAttemptModelDaos = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionModelDao.getTransactionExternalKey(), internalCallContext);
Assert.assertEquals(paymentAttemptModelDaos.size(), 1);
Assert.assertEquals(paymentAttemptModelDaos.get(0).getStateName(), "SUCCESS");
Assert.assertEquals(paymentAttemptModelDaos.get(0).getAmount().compareTo(BigDecimal.TEN), 0);
Assert.assertEquals(paymentAttemptModelDaos.get(0).getCurrency(), Currency.EUR);
adminPaymentApi.fixPaymentTransactionState(payment, payment.getTransactions().get(0), TransactionStatus.PAYMENT_FAILURE, null, "AUTH_ERRORED", ImmutableList.<PluginProperty>of(), callContext);
Assert.assertEquals(paymentApi.getPayment(payment.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext).getTransactions().size(), 1);
final PaymentModelDao refreshedPaymentModelDao = paymentDao.getPayment(payment.getId(), internalCallContext);
final PaymentTransactionModelDao refreshedPaymentTransactionModelDao = paymentDao.getPaymentTransaction(payment.getTransactions().get(0).getId(), internalCallContext);
Assert.assertEquals(refreshedPaymentModelDao.getStateName(), "AUTH_ERRORED");
Assert.assertNull(refreshedPaymentModelDao.getLastSuccessStateName());
Assert.assertEquals(refreshedPaymentTransactionModelDao.getTransactionStatus(), TransactionStatus.PAYMENT_FAILURE);
Assert.assertEquals(refreshedPaymentTransactionModelDao.getProcessedAmount().compareTo(BigDecimal.ZERO), 0);
Assert.assertEquals(refreshedPaymentTransactionModelDao.getProcessedCurrency(), Currency.EUR);
Assert.assertEquals(refreshedPaymentTransactionModelDao.getGatewayErrorCode(), "");
Assert.assertEquals(refreshedPaymentTransactionModelDao.getGatewayErrorMsg(), "");
final List<PaymentAttemptModelDao> refreshedPaymentAttemptModelDaos = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionModelDao.getTransactionExternalKey(), internalCallContext);
Assert.assertEquals(refreshedPaymentAttemptModelDaos.size(), 1);
Assert.assertEquals(refreshedPaymentAttemptModelDaos.get(0).getStateName(), "ABORTED");
Assert.assertEquals(refreshedPaymentAttemptModelDaos.get(0).getAmount().compareTo(BigDecimal.TEN), 0);
Assert.assertEquals(refreshedPaymentAttemptModelDaos.get(0).getCurrency(), Currency.EUR);
// Advance the clock to make sure the effective date of the new transaction is after the first one
clock.addDays(1);
assertListenerStatus();
// Verify subsequent payment retries work
retryService.retryPaymentTransaction(refreshedPaymentTransactionModelDao.getAttemptId(), ImmutableList.<String>of(MockPaymentControlProviderPlugin.PLUGIN_NAME), internalCallContext);
final Payment retriedPayment = paymentApi.getPayment(payment.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
Assert.assertEquals(retriedPayment.getTransactions().size(), 2);
final PaymentModelDao retriedPaymentModelDao = paymentDao.getPayment(payment.getId(), internalCallContext);
final PaymentTransactionModelDao retriedPaymentTransactionModelDao = paymentDao.getPaymentTransaction(retriedPayment.getTransactions().get(1).getId(), internalCallContext);
Assert.assertEquals(retriedPaymentModelDao.getStateName(), "AUTH_SUCCESS");
Assert.assertEquals(retriedPaymentModelDao.getLastSuccessStateName(), "AUTH_SUCCESS");
Assert.assertEquals(retriedPaymentTransactionModelDao.getTransactionStatus(), TransactionStatus.SUCCESS);
Assert.assertEquals(retriedPaymentTransactionModelDao.getProcessedAmount().compareTo(BigDecimal.TEN), 0);
Assert.assertEquals(retriedPaymentTransactionModelDao.getProcessedCurrency(), Currency.EUR);
Assert.assertEquals(retriedPaymentTransactionModelDao.getGatewayErrorCode(), "");
Assert.assertEquals(retriedPaymentTransactionModelDao.getGatewayErrorMsg(), "");
final List<PaymentAttemptModelDao> retriedPaymentAttemptModelDaos = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionModelDao.getTransactionExternalKey(), internalCallContext);
Assert.assertEquals(retriedPaymentAttemptModelDaos.size(), 2);
Assert.assertEquals(retriedPaymentAttemptModelDaos.get(0).getStateName(), "ABORTED");
Assert.assertEquals(retriedPaymentAttemptModelDaos.get(0).getAmount().compareTo(BigDecimal.TEN), 0);
Assert.assertEquals(retriedPaymentAttemptModelDaos.get(0).getCurrency(), Currency.EUR);
Assert.assertEquals(retriedPaymentAttemptModelDaos.get(1).getStateName(), "SUCCESS");
Assert.assertEquals(retriedPaymentAttemptModelDaos.get(1).getAmount().compareTo(BigDecimal.TEN), 0);
Assert.assertEquals(retriedPaymentAttemptModelDaos.get(1).getCurrency(), Currency.EUR);
}
use of org.killbill.billing.payment.dao.PaymentAttemptModelDao in project killbill by killbill.
the class TestJanitor method testCreateSuccessPurchaseWithPaymentControl.
@Test(groups = "slow")
public void testCreateSuccessPurchaseWithPaymentControl() throws PaymentApiException, InvoiceApiException, EventBusException {
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 = "wouf wouf";
invoice.addInvoiceItem(new MockRecurringInvoiceItem(invoice.getId(), account.getId(), subscriptionId, bundleId, "test plan", "test phase", null, now, now.plusMonths(1), requestedAmount, new BigDecimal("1.0"), Currency.USD));
testListener.pushExpectedEvent(NextEvent.PAYMENT);
invoicePaymentApi.createPurchaseForInvoicePayment(account, invoice.getId(), account.getPaymentMethodId(), null, requestedAmount, Currency.USD, null, paymentExternalKey, transactionExternalKey, ImmutableList.<PluginProperty>of(), INVOICE_PAYMENT, callContext);
final Payment payment = paymentApi.getPaymentByExternalKey(paymentExternalKey, false, false, ImmutableList.<PluginProperty>of(), callContext);
testListener.assertListenerStatus();
assertEquals(payment.getTransactions().size(), 1);
assertEquals(payment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS);
assertEquals(payment.getTransactions().get(0).getTransactionType(), TransactionType.PURCHASE);
final List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
assertEquals(attempts.size(), 1);
final PaymentAttemptModelDao attempt = attempts.get(0);
assertEquals(attempt.getStateName(), "SUCCESS");
assertEquals(attempt.getAmount().compareTo(requestedAmount), 0);
assertEquals(attempt.getCurrency(), Currency.USD);
// Ok now the fun part starts... we modify the attempt state to be 'INIT' and wait the the Janitor to do its job.
paymentDao.updatePaymentAttemptWithProperties(attempt.getId(), attempt.getPaymentMethodId(), attempt.getTransactionId(), "INIT", null, null, null, internalCallContext);
final PaymentAttemptModelDao attempt2 = paymentDao.getPaymentAttempt(attempt.getId(), internalCallContext);
assertEquals(attempt2.getStateName(), "INIT");
assertNull(attempt2.getAmount());
assertNull(attempt2.getCurrency());
clock.addDays(1);
Awaitility.await().atMost(5, TimeUnit.SECONDS).until(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
final PaymentAttemptModelDao attempt3 = paymentDao.getPaymentAttempt(attempt.getId(), internalCallContext);
return "SUCCESS".equals(attempt3.getStateName());
}
});
final PaymentAttemptModelDao attempt3 = paymentDao.getPaymentAttempt(attempt.getId(), internalCallContext);
assertEquals(attempt3.getStateName(), "SUCCESS");
assertEquals(attempt3.getAmount().compareTo(requestedAmount), 0);
assertEquals(attempt3.getCurrency(), Currency.USD);
}
use of org.killbill.billing.payment.dao.PaymentAttemptModelDao in project killbill by killbill.
the class TestRetryService method testAbortedPlugin.
// PLUGIN_EXCEPTION will lead to UNKNOWN row that will not be retried by the plugin
@Test(groups = "fast")
public void testAbortedPlugin() 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.PLUGIN_EXCEPTION);
boolean failed = false;
final String paymentExternalKey = UUID.randomUUID().toString();
final String transactionExternalKey = UUID.randomUUID().toString();
try {
invoicePaymentInternalApi.createPurchaseForInvoicePayment(false, account, invoice.getId(), account.getPaymentMethodId(), null, amount, Currency.USD, null, paymentExternalKey, transactionExternalKey, NO_PROPERTIES, PAYMENT_OPTIONS, internalCallContext);
} catch (final PaymentApiException e) {
failed = true;
}
assertTrue(failed);
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);
attempts = paymentDao.getPaymentAttempts(payment.getExternalKey(), internalCallContext);
final int expectedAttempts = 1;
assertEquals(attempts.size(), expectedAttempts);
assertEquals(attempts.get(0).getStateName(), "ABORTED");
}
use of org.killbill.billing.payment.dao.PaymentAttemptModelDao in project killbill by killbill.
the class TestRetryablePayment method testInitToSuccessWithPaymentExceptionAndRetries.
@Test(groups = "fast")
public void testInitToSuccessWithPaymentExceptionAndRetries() {
mockRetryProviderPlugin.setAborted(false).setNextRetryDate(new DateTime(clock.getUTCNow().plusDays(1)));
mockRetryAuthorizeOperationCallback.setResult(null).setException(new PaymentApiException(ErrorCode.__UNKNOWN_ERROR_CODE, "bla bla"));
runner.setOperationCallback(mockRetryAuthorizeOperationCallback).setContext(paymentStateContext);
try {
runner.run(true, TransactionType.AUTHORIZE, ControlOperation.AUTHORIZE, account, paymentMethodId, null, paymentExternalKey, paymentTransactionExternalKey, amount, currency, null, emptyProperties, null, callContext, internalCallContext);
fail("Expected PaymentApiException...");
} catch (final PaymentApiException e) {
final PaymentAttemptModelDao pa = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionExternalKey, internalCallContext).get(0);
assertEquals(pa.getTransactionExternalKey(), paymentTransactionExternalKey);
assertEquals(pa.getStateName(), "RETRIED");
assertEquals(pa.getTransactionType(), TransactionType.AUTHORIZE);
}
}
Aggregations