protected Map<UUID, List<InvoicePayment>> getAccountInvoicePayments(final Iterable<Payment> payments, final TenantContext context) throws OSGIServiceNotAvailable { final InvoicePaymentApi invoicePaymentApi = getInvoicePaymentUserApi(); final Map<UUID, List<InvoicePayment>> allInvoicePaymentsByPaymentId = new HashMap<UUID, List<InvoicePayment>>(); for (final Payment payment : payments) { // Retrieve all invoice payment types (including refunds and chargebacks) for that payment allInvoicePaymentsByPaymentId.put(payment.getId(), invoicePaymentApi.getInvoicePayments(payment.getId(), context)); } return allInvoicePaymentsByPaymentId; }
@Override public boolean apply(final InvoicePayment input) { return input.getPaymentId().equals(payment.getId()) && input.getType() == InvoicePaymentType.ATTEMPT; } }).orNull();
@Override public Payment apply(@Nullable final Void input) { try { return paymentApi.createRefundWithPaymentControl(account, payment.getId(), amount, currency, null, UUID.randomUUID().toString(), PLUGIN_PROPERTIES, PAYMENT_OPTIONS, callContext); } catch (final PaymentApiException e) { fail(e.toString()); return null; } } }, events);
@Override public Payment apply(@Nullable final Void input) { try { return paymentApi.createChargebackWithPaymentControl(account, payment.getId(), amount, currency, null, UUID.randomUUID().toString(), PAYMENT_OPTIONS, callContext); } catch (final PaymentApiException e) { fail(e.toString()); return null; } } }, events);
@Override public Payment apply(@Nullable final Void input) { try { return paymentApi.createChargebackReversalWithPaymentControl(account, payment.getId(), null, chargebackTransactionExternalKey, PAYMENT_OPTIONS, callContext); } catch (final PaymentApiException e) { fail(e.toString()); return null; } } }, events);
@Test(groups = "slow") public void testSimpleAuthCaptureWithInvalidCurrency() throws Exception { final BigDecimal requestedAmount = new BigDecimal("80.0091"); final Payment initialPayment = paymentApi.createAuthorization(account, account.getPaymentMethodId(), null, requestedAmount, account.getCurrency(), null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), callContext); try { paymentApi.createCapture(account, initialPayment.getId(), requestedAmount, Currency.AMD, null, UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), callContext); Assert.fail("Expected capture to fail..."); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INVALID_PARAMETER.getCode()); final Payment latestPayment = paymentApi.getPayment(initialPayment.getId(), true, false, ImmutableList.<PluginProperty>of(), callContext); assertEquals(latestPayment, initialPayment); } }
@Test(groups = "slow", description = "Verify we can make a refund on payment whose original payment method was deleted. See 694") public void testRefundAfterDeletedPaymentMethod() throws PaymentApiException { final BigDecimal requestedAmount = BigDecimal.TEN; final Payment payment = paymentApi.createPurchase(account, account.getPaymentMethodId(), null, requestedAmount, Currency.EUR, null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), callContext); paymentApi.deletePaymentMethod(account, account.getPaymentMethodId(), false, true, ImmutableList.<PluginProperty>of(), callContext); final Payment newPayment = paymentApi.createRefund(account, payment.getId(),requestedAmount, Currency.EUR, null, UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), callContext); Assert.assertEquals(newPayment.getTransactions().size(), 2); }
@Override public Payment apply(@Nullable final Void input) { try { final InvoicePayment invoicePayment = invoicePaymentApi.createRefundForInvoicePayment(true, iias, account, payment.getId(), amount, currency, null, UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), PAYMENT_OPTIONS, callContext); return paymentApi.getPayment(invoicePayment.getPaymentId(), false, false, ImmutableList.<PluginProperty>of(), callContext); } catch (final PaymentApiException e) { fail(e.toString()); return null; } } }, events);
@Test(groups = "slow") public void testRefundWithInvoiceItemAdjustemts() throws Exception { final Map<UUID, BigDecimal> iias = new HashMap<UUID, BigDecimal>(); iias.put(invoice.getInvoiceItems().get(0).getId(), null); refundPaymentWithInvoiceItemAdjAndCheckForCompletion(account, payment, iias, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT, NextEvent.INVOICE_ADJUSTMENT); refundChecker.checkRefund(payment.getId(), callContext, new ExpectedRefundCheck(payment.getId(), true, new BigDecimal("233.82"), Currency.USD, initialCreationDate.toLocalDate())); invoice = invoiceChecker.checkInvoice(account.getId(), invoiceItemCount++, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 3, 2), new LocalDate(2012, 3, 31), InvoiceItemType.RECURRING, new BigDecimal("233.82")), new ExpectedInvoiceItemCheck(InvoiceItemType.ITEM_ADJ, new BigDecimal("-233.82")) ); }
@Test(groups = "slow") public void testPurchase() throws Exception { final String paymentExternalKey = UUID.randomUUID().toString(); // PURCHASE final String purchaseKey = UUID.randomUUID().toString(); final Payment purchase = paymentProcessor.createPurchase(true, null, account, null, null, TEN, CURRENCY, null,paymentExternalKey, purchaseKey, null, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext); verifyPayment(purchase, paymentExternalKey, ZERO, ZERO, ZERO, 1); final UUID paymentId = purchase.getId(); verifyPaymentTransaction(purchase.getTransactions().get(0), purchaseKey, TransactionType.PURCHASE, TEN, paymentId); paymentBusListener.verify(1, account.getId(), paymentId, TEN, TransactionStatus.SUCCESS); }
@Test(groups = "slow") public void testSimpleAuthCaptureWithInvalidPaymentId() throws Exception { final BigDecimal requestedAmount = new BigDecimal("80.0091"); final Payment initialPayment = paymentApi.createAuthorization(account, account.getPaymentMethodId(), null, requestedAmount, account.getCurrency(), null, UUID.randomUUID().toString(), UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), callContext); try { paymentApi.createCapture(account, UUID.randomUUID(), requestedAmount, account.getCurrency(), null, UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), callContext); Assert.fail("Expected capture to fail..."); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_NO_SUCH_PAYMENT.getCode()); final Payment latestPayment = paymentApi.getPayment(initialPayment.getId(), true, false, ImmutableList.<PluginProperty>of(), callContext); assertEquals(latestPayment, initialPayment); } }
@Test(groups = "slow") public void testCredit() throws Exception { final String paymentExternalKey = UUID.randomUUID().toString(); // CREDIT final String creditKey = UUID.randomUUID().toString(); final Payment purchase = paymentProcessor.createCredit(true, null, account, null, null, TEN, CURRENCY, null,paymentExternalKey, creditKey, null, null, SHOULD_LOCK_ACCOUNT, PLUGIN_PROPERTIES, callContext, internalCallContext); verifyPayment(purchase, paymentExternalKey, ZERO, ZERO, ZERO, 1); final UUID paymentId = purchase.getId(); verifyPaymentTransaction(purchase.getTransactions().get(0), creditKey, TransactionType.CREDIT, TEN, paymentId); paymentBusListener.verify(1, account.getId(), paymentId, TEN, TransactionStatus.SUCCESS); }
@Test(groups = "slow") public void testRefundWithNoAdjustments() throws Exception { // Although we don't adjust the invoice, the invoicing system sends an event because invoice balance changes and overdue system-- in particular-- needs to know about it. refundPaymentAndCheckForCompletion(account, payment, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT); refundChecker.checkRefund(payment.getId(), callContext, new ExpectedRefundCheck(payment.getId(), false, new BigDecimal("233.82"), Currency.USD, initialCreationDate.toLocalDate())); final Invoice invoiceRefreshed = invoiceUserApi.getInvoice(invoice.getId(), callContext); assertTrue(invoiceRefreshed.getBalance().compareTo(new BigDecimal("233.82")) == 0); final BigDecimal accountBalance = invoiceUserApi.getAccountBalance(account.getId(), callContext); assertTrue(accountBalance.compareTo(new BigDecimal("233.82")) == 0); }
@Test(groups = "slow") public void testFailedRefundWithInvoiceAdjustment() throws Exception { try { invoicePaymentApi.createRefundForInvoicePayment(true, null, account, payment.getId(), payment.getPurchasedAmount(), payment.getCurrency(), null, UUID.randomUUID().toString(), ImmutableList.<PluginProperty>of(), PAYMENT_OPTIONS, callContext); fail("Refund with invoice adjustment should now throw an Exception"); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCause(), null); // Unfortunately we lose the original error code : INVOICE_ITEMS_ADJUSTMENT_MISSING Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_PLUGIN_EXCEPTION.getCode()); } }
@Override public Object execute() throws Throwable { assertEquals(DBRouterUntyped.getCurrentState(), THREAD_STATE.RO_ALLOWED); final Payment retrievedPayment2 = paymentApi.getPayment(payment.getId(), true, false, ImmutableList.<PluginProperty>of(), callContext); Assert.assertEquals(retrievedPayment2.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS); // No thread switch, RO as well assertEquals(mockPaymentProviderPlugin.getLastThreadState(), THREAD_STATE.RO_ALLOWED); assertEquals(DBRouterUntyped.getCurrentState(), THREAD_STATE.RO_ALLOWED); return null; } });
@Test(groups = "slow") public void testVerifyJanitorFromPendingDuringCompletionFlow() throws PaymentApiException { final BigDecimal authAmount = BigDecimal.TEN; final String transactionExternalKey = UUID.randomUUID().toString(); final Payment initialPayment = createPayment(TransactionType.AUTHORIZE, null, UUID.randomUUID().toString(), transactionExternalKey, authAmount, PaymentPluginStatus.PENDING); Assert.assertEquals(initialPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.PENDING); mockPaymentProviderPlugin.overridePaymentPluginStatus(initialPayment.getId(), initialPayment.getTransactions().get(0).getId(), PaymentPluginStatus.PROCESSED); try { final Payment completedPayment = createPayment(TransactionType.AUTHORIZE, initialPayment.getId(), initialPayment.getExternalKey(), transactionExternalKey, authAmount, PaymentPluginStatus.PROCESSED); Assert.fail(); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_ACTIVE_TRANSACTION_KEY_EXISTS.getCode()); } }
@Test(groups = "slow") public void testVerifyJanitorFromUnknownDuringCompletionFlow() throws PaymentApiException { final BigDecimal authAmount = BigDecimal.TEN; final String transactionExternalKey = UUID.randomUUID().toString(); final Payment initialPayment = createPayment(TransactionType.AUTHORIZE, null, UUID.randomUUID().toString(), transactionExternalKey, authAmount, PaymentPluginStatus.UNDEFINED); Assert.assertEquals(initialPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.UNKNOWN); mockPaymentProviderPlugin.overridePaymentPluginStatus(initialPayment.getId(), initialPayment.getTransactions().get(0).getId(), PaymentPluginStatus.PROCESSED); try { final Payment completedPayment = createPayment(TransactionType.AUTHORIZE, initialPayment.getId(), initialPayment.getExternalKey(), transactionExternalKey, authAmount, PaymentPluginStatus.PROCESSED); Assert.fail(); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_ACTIVE_TRANSACTION_KEY_EXISTS.getCode()); } }
private List<AuditLog> getAuditLogForPayment(final Payment payment, final TenantContext context) { return auditUserApi.getAccountAuditLogs(payment.getAccountId(), AuditLevel.FULL, context).getAuditLogsForPayment(payment.getId()); }
@Test(groups = "slow", description = "https://github.com/killbill/killbill/issues/255") public void testRefundWithDeletedPaymentMethod() throws Exception { // delete payment method busHandler.pushExpectedEvent(NextEvent.TAG); paymentApi.deletePaymentMethod(account, account.getPaymentMethodId(), true, true, new ArrayList<PluginProperty>(), callContext); assertListenerStatus(); // try to create a refund for a payment with its payment method deleted busHandler.pushExpectedEvent(NextEvent.PAYMENT); paymentApi.createRefund(account, payment.getId(), payment.getPurchasedAmount(), payment.getCurrency(), null, UUID.randomUUID().toString(), PLUGIN_PROPERTIES, callContext); assertListenerStatus(); }
private void checkPayment(final UUID accountId, final Payment payment, final CallContext context, final ExpectedPaymentCheck expected) { Assert.assertEquals(payment.getAccountId(), accountId); Assert.assertEquals(payment.getCurrency(), expected.getCurrency()); if (expected.getInvoiceId() != null) { for (final InvoicePayment invoicePayment : invoicePaymentApi.getInvoicePayments(payment.getId(), context)) { Assert.assertEquals(invoicePayment.getInvoiceId(), expected.getInvoiceId()); } } final PaymentTransaction transaction = getPurchaseTransaction(payment); Assert.assertTrue(transaction.getAmount().compareTo(expected.getAmount()) == 0, "Actual amount " + transaction.getAmount() + ", expected amount " + expected.getAmount()); Assert.assertEquals(transaction.getTransactionStatus(), expected.getStatus()); Assert.assertEquals(transaction.getEffectiveDate().toLocalDate().compareTo(expected.getPaymentDate()), 0, "Actual date " + transaction.getEffectiveDate() + ", expected date " + expected.getPaymentDate()); auditChecker.checkPaymentCreated(payment, context); }