@Override public Void answer(final InvocationOnMock invocation) throws Throwable { final PaymentTransaction paymentTransaction = (PaymentTransaction) invocation.getArguments()[1]; final TransactionStatus transactionStatus = (TransactionStatus) invocation.getArguments()[2]; Mockito.when(paymentTransaction.getTransactionStatus()).thenReturn(transactionStatus); return null; } }).when(adminPaymentApi).fixPaymentTransactionState(Mockito.<Payment>any(),
@Override public Payment answer(final InvocationOnMock invocation) throws Throwable { final UUID kbPaymentId = (UUID) invocation.getArguments()[1]; final Payment payment = paymentApi.getPayment(kbPaymentId, false, false, ImmutableList.<PluginProperty>of(), (TenantContext) invocation.getArguments()[4]); Assert.assertNotNull(payment); final String kbPaymentTransactionExternalKey = (String) invocation.getArguments()[3]; PaymentTransaction paymentTransaction = null; for (final PaymentTransaction t : payment.getTransactions()) { if (kbPaymentTransactionExternalKey.equals(t.getExternalKey())) { paymentTransaction = t; break; } } Assert.assertNotNull(paymentTransaction); Assert.assertEquals(paymentTransaction.getTransactionStatus(), TransactionStatus.SUCCESS); Mockito.when(paymentTransaction.getTransactionStatus()).thenReturn(TransactionStatus.PAYMENT_FAILURE); return payment; } });
public static void updatePaymentTransaction(final PaymentTransaction paymentTransaction, final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin) { Mockito.when(paymentTransaction.getPaymentInfoPlugin()).thenReturn(paymentTransactionInfoPlugin); Mockito.when(paymentTransaction.getTransactionType()).thenReturn(paymentTransactionInfoPlugin.getTransactionType()); Mockito.when(paymentTransaction.getTransactionStatus()).thenReturn(toTransactionStatus(paymentTransactionInfoPlugin)); }
@Override public Payment answer(final InvocationOnMock invocation) throws Throwable { final List<Payment> payments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), (TenantContext) invocation.getArguments()[6]); final Payment payment; if (payments == null || payments.isEmpty()) { payment = buildPayment(account.getId(), account.getPaymentMethodId(), (Currency) invocation.getArguments()[3], killbillApi); } else { payment = payments.get(payments.size() - 1); } final PaymentTransaction chargeback = buildPaymentTransaction(payment, TransactionType.CHARGEBACK, (Currency) invocation.getArguments()[3]); Mockito.when(chargeback.getTransactionStatus()).thenReturn(TransactionStatus.SUCCESS); return payment; } });
public Payment checkPayment(final UUID accountId, final int paymentOrderingNumber, final CallContext context, final ExpectedPaymentCheck expected) throws PaymentApiException { final List<Payment> payments = paymentApi.getAccountPayments(accountId, false, false, ImmutableList.<PluginProperty>of(), context); Assert.assertEquals(payments.size(), paymentOrderingNumber); final Payment payment = payments.get(paymentOrderingNumber - 1); final PaymentTransaction transaction = getPurchaseTransaction(payment); if (transaction.getTransactionStatus() == TransactionStatus.UNKNOWN) { checkPaymentNoAuditForRuntimeException(accountId, payment, expected); } else { checkPayment(accountId, payment, context, expected); } return payment; }
public static PaymentTransaction buildPaymentTransaction(final Payment payment, final String transactionExternalKey, final TransactionType transactionType, final TransactionStatus transactionStatus, final BigDecimal amount, final Currency currency) { final PaymentTransaction paymentTransaction = Mockito.mock(PaymentTransaction.class); Mockito.when(paymentTransaction.getId()).thenReturn(UUID.randomUUID()); final UUID paymentId = payment.getId(); Mockito.when(paymentTransaction.getPaymentId()).thenReturn(paymentId); Mockito.when(paymentTransaction.getTransactionType()).thenReturn(transactionType); Mockito.when(paymentTransaction.getAmount()).thenReturn(amount); Mockito.when(paymentTransaction.getCurrency()).thenReturn(currency); Mockito.when(paymentTransaction.getEffectiveDate()).thenReturn(new DateTime(2016, 1, 22, 10, 56, 56, DateTimeZone.UTC)); Mockito.when(paymentTransaction.getExternalKey()).thenReturn(transactionExternalKey); Mockito.when(paymentTransaction.getTransactionStatus()).thenReturn(transactionStatus); final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin = Mockito.mock(PaymentTransactionInfoPlugin.class); final PaymentPluginStatus paymentPluginStatus = toPaymentPluginStatus(paymentTransaction.getTransactionStatus()); Mockito.when(paymentTransactionInfoPlugin.getStatus()).thenReturn(paymentPluginStatus); Mockito.when(paymentTransaction.getPaymentInfoPlugin()).thenReturn(paymentTransactionInfoPlugin); payment.getTransactions().add(paymentTransaction); return paymentTransaction; }
@Test(groups = "slow") public void testCompletionOfUnknownAuthorization() throws Exception { final String paymentExternalKey = UUID.randomUUID().toString(); final String paymentTransactionExternalKey = UUID.randomUUID().toString(); final BigDecimal requestedAmount = BigDecimal.TEN; final Payment pendingPayment = createPayment(TransactionType.AUTHORIZE, null, paymentExternalKey, paymentTransactionExternalKey, requestedAmount, PaymentPluginStatus.UNDEFINED); assertNotNull(pendingPayment); Assert.assertEquals(pendingPayment.getTransactions().size(), 1); Assert.assertEquals(pendingPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.UNKNOWN); try { // Attempt to complete the payment createPayment(TransactionType.AUTHORIZE, pendingPayment.getId(), paymentExternalKey, paymentTransactionExternalKey, requestedAmount, PaymentPluginStatus.PROCESSED); Assert.fail(); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INVALID_OPERATION.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 testFailedInitialTransactionToSameTransactionWithSameKey() throws Exception { final BigDecimal requestedAmount = BigDecimal.TEN; for (final TransactionType transactionType : ImmutableList.<TransactionType>of(TransactionType.AUTHORIZE, TransactionType.PURCHASE, TransactionType.CREDIT)) { final String paymentExternalKey = UUID.randomUUID().toString(); final String keyA = UUID.randomUUID().toString(); final Payment errorPayment = createPayment(transactionType, null, paymentExternalKey, keyA, requestedAmount, PaymentPluginStatus.ERROR); assertNotNull(errorPayment); Assert.assertEquals(errorPayment.getTransactions().size(), 1); Assert.assertEquals(errorPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.PAYMENT_FAILURE); // Attempt to create another {AUTH, PURCHASE, CREDIT} with same key => That should work because we are completing the payment final Payment successfulPayment = createPayment(transactionType, errorPayment.getId(), paymentExternalKey, keyA, requestedAmount, PaymentPluginStatus.PROCESSED); assertNotNull(successfulPayment); Assert.assertEquals(successfulPayment.getId(), errorPayment.getId()); Assert.assertEquals(successfulPayment.getTransactions().size(), 2); } }
@Test(groups = "slow") public void testFailedInitialTransactionToSameTransactionWithDifferentKey() throws Exception { final BigDecimal requestedAmount = BigDecimal.TEN; for (final TransactionType transactionType : ImmutableList.<TransactionType>of(TransactionType.AUTHORIZE, TransactionType.PURCHASE, TransactionType.CREDIT)) { final String paymentExternalKey = UUID.randomUUID().toString(); final String keyA = UUID.randomUUID().toString(); final Payment errorPayment = createPayment(transactionType, null, paymentExternalKey, keyA, requestedAmount, PaymentPluginStatus.ERROR); assertNotNull(errorPayment); Assert.assertEquals(errorPayment.getTransactions().size(), 1); Assert.assertEquals(errorPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.PAYMENT_FAILURE); // Attempt to create another {AUTH, PURCHASE, CREDIT} with different key => KB state machine should make the request fail as we don't allow // multiple SUCCESS {AUTH, PURCHASE, CREDIT} final String keyB = UUID.randomUUID().toString(); final Payment successfulPayment = createPayment(transactionType, errorPayment.getId(), paymentExternalKey, keyB, requestedAmount, PaymentPluginStatus.PROCESSED); assertNotNull(successfulPayment); Assert.assertEquals(successfulPayment.getId(), errorPayment.getId()); Assert.assertEquals(successfulPayment.getTransactions().size(), 2); } }
private void verifyRefund(final Payment refund, final String paymentExternalKey, final String paymentTransactionExternalKey, final String refundTransactionExternalKey, final BigDecimal requestedAmount, final BigDecimal refundAmount, final TransactionStatus transactionStatus) { Assert.assertEquals(refund.getExternalKey(), paymentExternalKey); Assert.assertEquals(refund.getTransactions().size(), 2); Assert.assertEquals(refund.getTransactions().get(0).getAmount().compareTo(requestedAmount), 0); Assert.assertEquals(refund.getTransactions().get(0).getProcessedAmount().compareTo(requestedAmount), 0); Assert.assertEquals(refund.getTransactions().get(0).getCurrency(), account.getCurrency()); Assert.assertEquals(refund.getTransactions().get(0).getExternalKey(), paymentTransactionExternalKey); Assert.assertEquals(refund.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS); Assert.assertEquals(refund.getTransactions().get(1).getAmount().compareTo(requestedAmount), 0); Assert.assertEquals(refund.getTransactions().get(1).getProcessedAmount().compareTo(refundAmount), 0); Assert.assertEquals(refund.getTransactions().get(1).getCurrency(), account.getCurrency()); Assert.assertEquals(refund.getTransactions().get(1).getExternalKey(), refundTransactionExternalKey); Assert.assertEquals(refund.getTransactions().get(1).getTransactionStatus(), transactionStatus); }
private void checkPaymentNoAuditForRuntimeException(final UUID accountId, final Payment payment, final ExpectedPaymentCheck expected) { Assert.assertEquals(payment.getAccountId(), accountId); final PaymentTransaction transaction = getPurchaseTransaction(payment); Assert.assertTrue(transaction.getAmount().compareTo(expected.getAmount()) == 0); Assert.assertEquals(transaction.getTransactionStatus(), expected.getStatus()); Assert.assertEquals(payment.getCurrency(), expected.getCurrency()); }
@Test(groups = "slow") public void testNotifyPendingPaymentOfStateChanged() throws Exception { final String paymentExternalKey = UUID.randomUUID().toString(); final Iterable<PluginProperty> pluginPropertiesToDriveTransationToPending = ImmutableList.<PluginProperty>of(new PluginProperty(MockPaymentProviderPlugin.PLUGIN_PROPERTY_PAYMENT_PLUGIN_STATUS_OVERRIDE, PaymentPluginStatus.PENDING, false)); // Create Pending AUTH final String authorizationKey = UUID.randomUUID().toString(); final Payment authorization = paymentProcessor.createAuthorization(true, null, account, null, null, TEN, CURRENCY, null,paymentExternalKey, authorizationKey, null, null, SHOULD_LOCK_ACCOUNT, pluginPropertiesToDriveTransationToPending, callContext, internalCallContext); final PaymentTransaction pendingTransaction = authorization.getTransactions().get(0); Assert.assertEquals(pendingTransaction.getTransactionStatus(), TransactionStatus.PENDING); final UUID transactionId = pendingTransaction.getId(); // Override plugin status of payment mockPaymentProviderPlugin.overridePaymentPluginStatus(authorization.getId(), transactionId, PaymentPluginStatus.PROCESSED); // Notify that state has changed, after changing the state in the plugin final Payment updatedPayment = paymentProcessor.notifyPendingPaymentOfStateChanged(account, transactionId, true, callContext, internalCallContext); verifyPayment(updatedPayment, paymentExternalKey, TEN, ZERO, ZERO, 1); final PaymentTransaction updatedTransaction = updatedPayment.getTransactions().get(0); Assert.assertEquals(updatedTransaction.getTransactionStatus(), TransactionStatus.SUCCESS); }
@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()); } }
@Override public boolean apply(final PaymentTransaction input) { return TransactionType.CHARGEBACK.equals(input.getTransactionType()) && TransactionStatus.SUCCESS.equals(input.getTransactionStatus()); } });
@Test(groups = "slow") public void testSanityAcrossTransactionTypes() throws PaymentApiException { final BigDecimal requestedAmount = BigDecimal.TEN; final String paymentExternalKey = "ahhhhhhhh"; final String transactionExternalKey = "okkkkkkk"; final Payment pendingPayment = createPayment(TransactionType.AUTHORIZE, null, paymentExternalKey, transactionExternalKey, requestedAmount, PaymentPluginStatus.PENDING); assertNotNull(pendingPayment); Assert.assertEquals(pendingPayment.getExternalKey(), paymentExternalKey); Assert.assertEquals(pendingPayment.getTransactions().size(), 1); Assert.assertEquals(pendingPayment.getTransactions().get(0).getAmount().compareTo(requestedAmount), 0); Assert.assertEquals(pendingPayment.getTransactions().get(0).getProcessedAmount().compareTo(requestedAmount), 0); Assert.assertEquals(pendingPayment.getTransactions().get(0).getCurrency(), account.getCurrency()); Assert.assertEquals(pendingPayment.getTransactions().get(0).getExternalKey(), transactionExternalKey); Assert.assertEquals(pendingPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.PENDING); try { createPayment(TransactionType.PURCHASE, null, paymentExternalKey, transactionExternalKey, requestedAmount, PaymentPluginStatus.PENDING); Assert.fail("PURCHASE transaction with same key should have failed"); } catch (final PaymentApiException expected) { Assert.assertEquals(expected.getCode(), ErrorCode.PAYMENT_INVALID_PARAMETER.getCode()); } }
private void verifyPaymentViaGetPath(final Payment payment) throws PaymentApiException { // We can't use Assert.assertEquals because the updateDate may have been updated by the Janitor final Payment refreshedPayment = paymentApi.getPayment(payment.getId(), true, false, ImmutableList.<PluginProperty>of(), callContext); Assert.assertEquals(refreshedPayment.getAccountId(), payment.getAccountId()); Assert.assertEquals(refreshedPayment.getTransactions().size(), payment.getTransactions().size()); Assert.assertEquals(refreshedPayment.getExternalKey(), payment.getExternalKey()); Assert.assertEquals(refreshedPayment.getPaymentMethodId(), payment.getPaymentMethodId()); Assert.assertEquals(refreshedPayment.getAccountId(), payment.getAccountId()); Assert.assertEquals(refreshedPayment.getAuthAmount().compareTo(payment.getAuthAmount()), 0); Assert.assertEquals(refreshedPayment.getCapturedAmount().compareTo(payment.getCapturedAmount()), 0); Assert.assertEquals(refreshedPayment.getPurchasedAmount().compareTo(payment.getPurchasedAmount()), 0); Assert.assertEquals(refreshedPayment.getRefundedAmount().compareTo(payment.getRefundedAmount()), 0); Assert.assertEquals(refreshedPayment.getCurrency(), payment.getCurrency()); for (int i = 0; i < refreshedPayment.getTransactions().size(); i++) { final PaymentTransaction refreshedPaymentTransaction = refreshedPayment.getTransactions().get(i); final PaymentTransaction paymentTransaction = payment.getTransactions().get(i); Assert.assertEquals(refreshedPaymentTransaction.getAmount().compareTo(paymentTransaction.getAmount()), 0); Assert.assertEquals(refreshedPaymentTransaction.getProcessedAmount().compareTo(paymentTransaction.getProcessedAmount()), 0); Assert.assertEquals(refreshedPaymentTransaction.getCurrency(), paymentTransaction.getCurrency()); Assert.assertEquals(refreshedPaymentTransaction.getExternalKey(), paymentTransaction.getExternalKey()); Assert.assertEquals(refreshedPaymentTransaction.getTransactionStatus(), paymentTransaction.getTransactionStatus()); } }
public PaymentTransactionJson(final PaymentTransaction transaction, final String paymentExternalKey, @Nullable final List<AuditLog> transactionLogs) { this(transaction.getId(), transaction.getExternalKey(), transaction.getPaymentId(), paymentExternalKey, transaction.getTransactionType(), transaction.getAmount(), transaction.getCurrency() != null ? transaction.getCurrency() : null, transaction.getEffectiveDate(), transaction.getProcessedAmount(), transaction.getProcessedCurrency() != null ? transaction.getProcessedCurrency() : null, transaction.getTransactionStatus() != null ? transaction.getTransactionStatus().toString() : null, transaction.getGatewayErrorCode(), transaction.getGatewayErrorMsg(), transaction.getPaymentInfoPlugin() == null ? null : transaction.getPaymentInfoPlugin().getFirstPaymentReferenceId(), transaction.getPaymentInfoPlugin() == null ? null : transaction.getPaymentInfoPlugin().getSecondPaymentReferenceId(), transaction.getPaymentInfoPlugin() == null ? null : toPluginPropertyJson(transaction.getPaymentInfoPlugin().getProperties()), toAuditLogJson(transactionLogs)); }
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); }