use of org.killbill.billing.payment.dao.PaymentModelDao in project killbill by killbill.
the class PaymentProcessor method invokeJanitor.
private PaymentModelDao invokeJanitor(final PaymentModelDao curPaymentModelDao, final Collection<PaymentTransactionModelDao> curTransactionsModelDao, @Nullable final Iterable<PaymentTransactionInfoPlugin> pluginTransactions, final InternalTenantContext internalTenantContext) {
// Need to filter for optimized codepaths looking up by account_record_id
final Iterable<PaymentTransactionModelDao> filteredTransactions = Iterables.filter(curTransactionsModelDao, new Predicate<PaymentTransactionModelDao>() {
@Override
public boolean apply(final PaymentTransactionModelDao curPaymentTransactionModelDao) {
return curPaymentTransactionModelDao.getPaymentId().equals(curPaymentModelDao.getId());
}
});
PaymentModelDao newPaymentModelDao = curPaymentModelDao;
final Collection<PaymentTransactionModelDao> transactionsModelDao = new LinkedList<PaymentTransactionModelDao>();
for (final PaymentTransactionModelDao curPaymentTransactionModelDao : filteredTransactions) {
PaymentTransactionModelDao newPaymentTransactionModelDao = curPaymentTransactionModelDao;
final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin = findPaymentTransactionInfoPlugin(newPaymentTransactionModelDao, pluginTransactions);
if (paymentTransactionInfoPlugin != null) {
// Make sure to invoke the Janitor task in case the plugin fixes its state on the fly
// See https://github.com/killbill/killbill/issues/341
final boolean hasChanged = incompletePaymentTransactionTask.updatePaymentAndTransactionIfNeededWithAccountLock(newPaymentModelDao, newPaymentTransactionModelDao, paymentTransactionInfoPlugin, internalTenantContext);
if (hasChanged) {
newPaymentModelDao = paymentDao.getPayment(newPaymentModelDao.getId(), internalTenantContext);
newPaymentTransactionModelDao = paymentDao.getPaymentTransaction(newPaymentTransactionModelDao.getId(), internalTenantContext);
}
}
transactionsModelDao.add(newPaymentTransactionModelDao);
}
curTransactionsModelDao.clear();
curTransactionsModelDao.addAll(transactionsModelDao);
return newPaymentModelDao;
}
use of org.killbill.billing.payment.dao.PaymentModelDao in project killbill by killbill.
the class InvoicePaymentControlPluginApi method getPluginRefundResult.
private PriorPaymentControlResult getPluginRefundResult(final PaymentControlContext paymentControlPluginContext, final Iterable<PluginProperty> pluginProperties, final InternalCallContext internalContext) throws PaymentControlApiException {
final Map<UUID, BigDecimal> idWithAmount = extractIdsWithAmountFromProperties(pluginProperties);
if ((paymentControlPluginContext.getAmount() == null || paymentControlPluginContext.getAmount().compareTo(BigDecimal.ZERO) == 0) && idWithAmount.size() == 0) {
throw new PaymentControlApiException("Abort refund call: ", new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_EXCEPTION, String.format("Refund for payment, key = %s, aborted: requested refund amount is = %s", paymentControlPluginContext.getPaymentExternalKey(), paymentControlPluginContext.getAmount())));
}
final PaymentModelDao payment = paymentDao.getPayment(paymentControlPluginContext.getPaymentId(), internalContext);
if (payment == null) {
throw new PaymentControlApiException("Unexpected null payment");
}
// This will calculate the upper bound on the refund amount based on the invoice items associated with that payment.
// Note that we are not checking that other (partial) refund occurred, but if the refund ends up being greater than what is allowed
// the call to the gateway would fail; it would need noce to validate on our side though...
final BigDecimal amountToBeRefunded = computeRefundAmount(payment.getId(), paymentControlPluginContext.getAmount(), idWithAmount, internalContext);
final boolean isAborted = amountToBeRefunded.compareTo(BigDecimal.ZERO) == 0;
if (paymentControlPluginContext.isApiPayment() && isAborted) {
throw new PaymentControlApiException("Abort refund call: ", new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_EXCEPTION, String.format("Refund for payment %s aborted : invoice item sum amount is %s, requested refund amount is = %s", payment.getId(), amountToBeRefunded, paymentControlPluginContext.getAmount())));
}
final PluginProperty prop = getPluginProperty(pluginProperties, PROP_IPCD_REFUND_WITH_ADJUSTMENTS);
final boolean isAdjusted = prop != null && prop.getValue() != null ? Boolean.valueOf(prop.getValue().toString()) : false;
if (isAdjusted) {
try {
invoiceApi.validateInvoiceItemAdjustments(paymentControlPluginContext.getPaymentId(), idWithAmount, internalContext);
} catch (InvoiceApiException e) {
throw new PaymentControlApiException(String.format("Refund for payment %s aborted", payment.getId()), new PaymentApiException(ErrorCode.PAYMENT_PLUGIN_EXCEPTION, e.getMessage()));
}
}
return new DefaultPriorPaymentControlResult(isAborted, amountToBeRefunded);
}
use of org.killbill.billing.payment.dao.PaymentModelDao 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.PaymentModelDao in project killbill by killbill.
the class TestDefaultAdminPaymentApi method testFixPaymentTransactionStateRefundFailedToRefundSuccess.
@Test(groups = "slow", description = "https://github.com/killbill/killbill-adyen-plugin/pull/60")
public void testFixPaymentTransactionStateRefundFailedToRefundSuccess() throws PaymentApiException {
final Payment payment = paymentApi.createPurchase(account, account.getPaymentMethodId(), null, BigDecimal.TEN, Currency.EUR, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), callContext);
final PaymentModelDao paymentModelDao = paymentDao.getPayment(payment.getId(), internalCallContext);
final PaymentTransactionModelDao paymentTransactionModelDao = paymentDao.getPaymentTransaction(payment.getTransactions().get(0).getId(), internalCallContext);
Assert.assertEquals(paymentModelDao.getStateName(), "PURCHASE_SUCCESS");
Assert.assertEquals(paymentModelDao.getLastSuccessStateName(), "PURCHASE_SUCCESS");
Assert.assertEquals(paymentTransactionModelDao.getTransactionStatus(), TransactionStatus.SUCCESS);
final Payment refund = paymentApi.createRefund(account, payment.getId(), payment.getPurchasedAmount(), payment.getCurrency(), null, UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(new PluginProperty(MockPaymentProviderPlugin.PLUGIN_PROPERTY_PAYMENT_PLUGIN_STATUS_OVERRIDE, PaymentPluginStatus.ERROR.toString(), false)), callContext);
final PaymentModelDao paymentModelDao2 = paymentDao.getPayment(payment.getId(), internalCallContext);
final PaymentTransactionModelDao paymentTransactionModelDao2 = paymentDao.getPaymentTransaction(refund.getTransactions().get(1).getId(), internalCallContext);
Assert.assertEquals(paymentModelDao2.getStateName(), "REFUND_FAILED");
Assert.assertEquals(paymentModelDao2.getLastSuccessStateName(), "PURCHASE_SUCCESS");
Assert.assertEquals(paymentTransactionModelDao2.getTransactionStatus(), TransactionStatus.PAYMENT_FAILURE);
adminPaymentApi.fixPaymentTransactionState(refund, refund.getTransactions().get(1), TransactionStatus.SUCCESS, null, /* Let Kill Bill figure it out */
null, /* Let Kill Bill figure it out */
ImmutableList.<PluginProperty>of(), callContext);
final PaymentModelDao paymentModelDao3 = paymentDao.getPayment(payment.getId(), internalCallContext);
final PaymentTransactionModelDao paymentTransactionModelDao3 = paymentDao.getPaymentTransaction(refund.getTransactions().get(1).getId(), internalCallContext);
Assert.assertEquals(paymentModelDao3.getStateName(), "REFUND_SUCCESS");
Assert.assertEquals(paymentModelDao3.getLastSuccessStateName(), "REFUND_SUCCESS");
Assert.assertEquals(paymentTransactionModelDao3.getTransactionStatus(), TransactionStatus.SUCCESS);
}
use of org.killbill.billing.payment.dao.PaymentModelDao in project killbill by killbill.
the class TestDefaultAdminPaymentApi method testFixPaymentTransactionStateRefundSuccessToRefundFailed.
@Test(groups = "slow", description = "https://github.com/killbill/killbill-adyen-plugin/pull/60")
public void testFixPaymentTransactionStateRefundSuccessToRefundFailed() throws PaymentApiException {
final Payment payment = paymentApi.createPurchase(account, account.getPaymentMethodId(), null, BigDecimal.TEN, Currency.EUR, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), callContext);
final PaymentModelDao paymentModelDao = paymentDao.getPayment(payment.getId(), internalCallContext);
final PaymentTransactionModelDao paymentTransactionModelDao = paymentDao.getPaymentTransaction(payment.getTransactions().get(0).getId(), internalCallContext);
Assert.assertEquals(paymentModelDao.getStateName(), "PURCHASE_SUCCESS");
Assert.assertEquals(paymentModelDao.getLastSuccessStateName(), "PURCHASE_SUCCESS");
Assert.assertEquals(paymentTransactionModelDao.getTransactionStatus(), TransactionStatus.SUCCESS);
final Payment refund = paymentApi.createRefund(account, payment.getId(), payment.getPurchasedAmount(), payment.getCurrency(), null, UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), callContext);
final PaymentModelDao paymentModelDao2 = paymentDao.getPayment(payment.getId(), internalCallContext);
final PaymentTransactionModelDao paymentTransactionModelDao2 = paymentDao.getPaymentTransaction(refund.getTransactions().get(1).getId(), internalCallContext);
Assert.assertEquals(paymentModelDao2.getStateName(), "REFUND_SUCCESS");
Assert.assertEquals(paymentModelDao2.getLastSuccessStateName(), "REFUND_SUCCESS");
Assert.assertEquals(paymentTransactionModelDao2.getTransactionStatus(), TransactionStatus.SUCCESS);
adminPaymentApi.fixPaymentTransactionState(refund, refund.getTransactions().get(1), TransactionStatus.PAYMENT_FAILURE, null, /* Let Kill Bill figure it out */
null, /* Let Kill Bill figure it out */
ImmutableList.<PluginProperty>of(), callContext);
final PaymentModelDao paymentModelDao3 = paymentDao.getPayment(payment.getId(), internalCallContext);
final PaymentTransactionModelDao paymentTransactionModelDao3 = paymentDao.getPaymentTransaction(refund.getTransactions().get(1).getId(), internalCallContext);
Assert.assertEquals(paymentModelDao3.getStateName(), "REFUND_FAILED");
Assert.assertEquals(paymentModelDao3.getLastSuccessStateName(), "PURCHASE_SUCCESS");
Assert.assertEquals(paymentTransactionModelDao3.getTransactionStatus(), TransactionStatus.PAYMENT_FAILURE);
}
Aggregations