use of org.killbill.automaton.State in project killbill by killbill.
the class TestRetryablePayment method testRetryLogicFromRetriedStateWithPaymentApiException.
@Test(groups = "fast")
public void testRetryLogicFromRetriedStateWithPaymentApiException() {
mockRetryProviderPlugin.setAborted(false).setNextRetryDate(null);
mockRetryAuthorizeOperationCallback.setResult(null).setException(new PaymentApiException(ErrorCode.__UNKNOWN_ERROR_CODE, "foo"));
runner.setOperationCallback(mockRetryAuthorizeOperationCallback).setContext(paymentStateContext);
final State state = retrySMHelper.getRetriedState();
final UUID transactionId = UUID.randomUUID();
final UUID paymentId = UUID.randomUUID();
final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow, paymentExternalKey, transactionId, paymentTransactionExternalKey, TransactionType.AUTHORIZE, state.getName(), amount, currency, null, EMPTY_PROPERTIES);
paymentDao.insertPaymentAttemptWithProperties(attempt, internalCallContext);
paymentDao.insertPaymentWithFirstTransaction(new PaymentModelDao(paymentId, utcNow, utcNow, account.getId(), paymentMethodId, -1, paymentExternalKey), new PaymentTransactionModelDao(transactionId, attempt.getId(), paymentTransactionExternalKey, utcNow, utcNow, paymentId, TransactionType.AUTHORIZE, utcNow, TransactionStatus.PAYMENT_FAILURE, amount, currency, "bla", "foo"), internalCallContext);
processor.retryPaymentTransaction(attempt.getId(), ImmutableList.<String>of(MockPaymentControlProviderPlugin.PLUGIN_NAME), internalCallContext);
final List<PaymentAttemptModelDao> pas = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionExternalKey, internalCallContext);
assertEquals(pas.size(), 2);
final PaymentAttemptModelDao failedAttempt = Iterables.tryFind(pas, new Predicate<PaymentAttemptModelDao>() {
@Override
public boolean apply(final PaymentAttemptModelDao input) {
return input.getTransactionType() == TransactionType.AUTHORIZE && input.getStateName().equals("ABORTED");
}
}).orNull();
assertNotNull(failedAttempt);
}
use of org.killbill.automaton.State in project killbill by killbill.
the class TestRetryablePayment method testRetryLogicFromRetriedStateWithLockFailure.
@Test(groups = "fast")
public void testRetryLogicFromRetriedStateWithLockFailure() throws LockFailedException {
GlobalLock lock = null;
try {
// Grab lock so that operation later will fail...
lock = locker.lockWithNumberOfTries(LockerType.ACCNT_INV_PAY.toString(), account.getId().toString(), 1);
mockRetryProviderPlugin.setAborted(false).setNextRetryDate(null);
mockRetryAuthorizeOperationCallback.setResult(OperationResult.SUCCESS).setException(null);
runner.setOperationCallback(mockRetryAuthorizeOperationCallback).setContext(paymentStateContext);
final State state = retrySMHelper.getRetriedState();
final UUID transactionId = UUID.randomUUID();
final UUID paymentId = UUID.randomUUID();
final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow, paymentExternalKey, transactionId, paymentTransactionExternalKey, TransactionType.AUTHORIZE, state.getName(), amount, currency, null, EMPTY_PROPERTIES);
paymentDao.insertPaymentAttemptWithProperties(attempt, internalCallContext);
paymentDao.insertPaymentWithFirstTransaction(new PaymentModelDao(paymentId, utcNow, utcNow, account.getId(), paymentMethodId, -1, paymentExternalKey), new PaymentTransactionModelDao(transactionId, attempt.getId(), paymentTransactionExternalKey, utcNow, utcNow, paymentId, TransactionType.AUTHORIZE, utcNow, TransactionStatus.PAYMENT_FAILURE, amount, currency, "bla", "foo"), internalCallContext);
processor.retryPaymentTransaction(attempt.getId(), ImmutableList.<String>of(MockPaymentControlProviderPlugin.PLUGIN_NAME), internalCallContext);
final List<PaymentAttemptModelDao> pas = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionExternalKey, internalCallContext);
assertEquals(pas.size(), 2);
final PaymentAttemptModelDao failedAttempt = Iterables.tryFind(pas, new Predicate<PaymentAttemptModelDao>() {
@Override
public boolean apply(final PaymentAttemptModelDao input) {
return input.getTransactionType() == TransactionType.AUTHORIZE && input.getStateName().equals("ABORTED");
}
}).orNull();
assertNotNull(failedAttempt);
} finally {
if (lock != null) {
lock.release();
}
}
}
use of org.killbill.automaton.State in project killbill by killbill.
the class TestRetryablePayment method testRetryToSuccessWithPaymentApiExceptionAndRetry.
@Test(groups = "fast")
public void testRetryToSuccessWithPaymentApiExceptionAndRetry() {
mockRetryProviderPlugin.setAborted(false).setNextRetryDate(new DateTime().plusDays(1));
mockRetryAuthorizeOperationCallback.setResult(null).setException(new PaymentApiException(ErrorCode.__UNKNOWN_ERROR_CODE, "bla"));
runner.setOperationCallback(mockRetryAuthorizeOperationCallback).setContext(paymentStateContext);
final State state = retrySMHelper.getRetriedState();
final UUID transactionId = UUID.randomUUID();
paymentDao.insertPaymentAttemptWithProperties(new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow, paymentExternalKey, transactionId, paymentTransactionExternalKey, TransactionType.AUTHORIZE, state.getName(), amount, currency, null, EMPTY_PROPERTIES), internalCallContext);
try {
runner.run(state, false, TransactionType.AUTHORIZE, ControlOperation.AUTHORIZE, account, paymentMethodId, null, paymentExternalKey, paymentTransactionExternalKey, amount, currency, null, emptyProperties, null, callContext, internalCallContext);
fail("Expecting 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);
}
}
use of org.killbill.automaton.State in project killbill by killbill.
the class TestRetryablePayment method testRetryLogicFromRetriedStateWithSuccess.
@Test(groups = "fast")
public void testRetryLogicFromRetriedStateWithSuccess() throws PaymentApiException {
mockRetryProviderPlugin.setAborted(false).setNextRetryDate(null);
mockRetryAuthorizeOperationCallback.setResult(OperationResult.SUCCESS).setException(null);
runner.setOperationCallback(mockRetryAuthorizeOperationCallback).setContext(paymentStateContext);
final State state = retrySMHelper.getRetriedState();
final UUID transactionId = UUID.randomUUID();
final UUID paymentId = UUID.randomUUID();
final PaymentAttemptModelDao attempt = new PaymentAttemptModelDao(account.getId(), paymentMethodId, utcNow, utcNow, paymentExternalKey, transactionId, paymentTransactionExternalKey, TransactionType.AUTHORIZE, state.getName(), amount, currency, null, EMPTY_PROPERTIES);
paymentDao.insertPaymentAttemptWithProperties(attempt, internalCallContext);
paymentDao.insertPaymentWithFirstTransaction(new PaymentModelDao(paymentId, utcNow, utcNow, account.getId(), paymentMethodId, -1, paymentExternalKey), new PaymentTransactionModelDao(transactionId, attempt.getId(), paymentTransactionExternalKey, utcNow, utcNow, paymentId, TransactionType.AUTHORIZE, utcNow, TransactionStatus.PAYMENT_FAILURE, amount, currency, "bla", "foo"), internalCallContext);
processor.retryPaymentTransaction(attempt.getId(), ImmutableList.<String>of(MockPaymentControlProviderPlugin.PLUGIN_NAME), internalCallContext);
final List<PaymentAttemptModelDao> pas = paymentDao.getPaymentAttemptByTransactionExternalKey(paymentTransactionExternalKey, internalCallContext);
assertEquals(pas.size(), 2);
final PaymentAttemptModelDao successfulAttempt = Iterables.tryFind(pas, new Predicate<PaymentAttemptModelDao>() {
@Override
public boolean apply(final PaymentAttemptModelDao input) {
return input.getTransactionType() == TransactionType.AUTHORIZE && input.getStateName().equals("SUCCESS");
}
}).orNull();
assertNotNull(successfulAttempt);
}
use of org.killbill.automaton.State in project killbill by killbill.
the class PluginControlPaymentProcessor method retryPaymentTransaction.
public void retryPaymentTransaction(final UUID attemptId, final List<String> paymentControlPluginNames, final InternalCallContext internalCallContext) {
final PaymentAttemptModelDao attempt = paymentDao.getPaymentAttempt(attemptId, internalCallContext);
log.info("Retrying attemptId='{}', paymentExternalKey='{}', transactionExternalKey='{}'. paymentControlPluginNames='{}'", attemptId, attempt.getPaymentExternalKey(), attempt.getTransactionExternalKey(), paymentControlPluginNames);
final PaymentModelDao paymentModelDao = paymentDao.getPaymentByExternalKey(attempt.getPaymentExternalKey(), internalCallContext);
final UUID paymentId = paymentModelDao != null ? paymentModelDao.getId() : null;
final CallContext callContext = buildCallContext(internalCallContext);
final String transactionType = TransactionType.PURCHASE.name();
Account account = null;
Payment payment = null;
PaymentTransaction paymentTransaction = null;
try {
account = accountInternalApi.getAccountById(attempt.getAccountId(), internalCallContext);
final State state = paymentControlStateMachineHelper.getState(attempt.getStateName());
final Iterable<PluginProperty> pluginProperties = PluginPropertySerializer.deserialize(attempt.getPluginProperties());
logEnterAPICall(log, transactionType, account, attempt.getPaymentMethodId(), paymentId, null, attempt.getAmount(), attempt.getCurrency(), attempt.getPaymentExternalKey(), attempt.getTransactionExternalKey(), null, paymentControlPluginNames);
payment = pluginControlledPaymentAutomatonRunner.run(state, false, attempt.getTransactionType(), ControlOperation.valueOf(attempt.getTransactionType().toString()), account, attempt.getPaymentMethodId(), paymentId, attempt.getPaymentExternalKey(), attempt.getTransactionExternalKey(), // The amount on the payment attempt drives the amount of the new payment transaction
attempt.getAmount(), attempt.getCurrency(), null, pluginProperties, paymentControlPluginNames, callContext, internalCallContext);
log.debug("retryPaymentTransaction result: payment='{}'", payment);
paymentTransaction = Iterables.<PaymentTransaction>find(Lists.<PaymentTransaction>reverse(payment.getTransactions()), new Predicate<PaymentTransaction>() {
@Override
public boolean apply(final PaymentTransaction input) {
return attempt.getTransactionExternalKey().equals(input.getExternalKey());
}
});
} catch (final AccountApiException e) {
log.warn("Failed to retry attemptId='{}', paymentControlPlugins='{}'", attemptId, toPluginNamesOnError(paymentControlPluginNames), e);
} catch (final PaymentApiException e) {
// Log exception unless nothing left to be paid
if (e.getCode() == ErrorCode.PAYMENT_PLUGIN_API_ABORTED.getCode() && paymentControlPluginNames != null && paymentControlPluginNames.size() == 1 && InvoicePaymentControlPluginApi.PLUGIN_NAME.equals(paymentControlPluginNames.get(0))) {
log.warn("Failed to retry attemptId='{}', paymentControlPlugins='{}'", attemptId, toPluginNamesOnError(paymentControlPluginNames));
} else {
log.warn("Failed to retry attemptId='{}', paymentControlPlugins='{}'", attemptId, toPluginNamesOnError(paymentControlPluginNames), e);
}
} catch (final PluginPropertySerializerException e) {
log.warn("Failed to retry attemptId='{}', paymentControlPlugins='{}'", attemptId, toPluginNamesOnError(paymentControlPluginNames), e);
} catch (final MissingEntryException e) {
log.warn("Failed to retry attemptId='{}', paymentControlPlugins='{}'", attemptId, toPluginNamesOnError(paymentControlPluginNames), 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, null);
}
}
Aggregations