@Test(groups = "fast") public void testBuildFormDescriptorWithPaymentControlAbortedPayment() throws PaymentApiException { plugin.setAborted(true); // Set a random UUID to verify the plugin will successfully override it try { paymentGatewayApi.buildFormDescriptorWithPaymentControl(account, UUID.randomUUID(), ImmutableList.<PluginProperty>of(), ImmutableList.<PluginProperty>of(), paymentOptions, callContext); Assert.fail(); } catch (PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_PLUGIN_API_ABORTED.getCode()); } }
@Test(groups = "slow") public void testUniqueExternalPaymentMethod() throws PaymentApiException { paymentApi.addPaymentMethod(account, "thisonewillwork", ExternalPaymentProviderPlugin.PLUGIN_NAME, true, null, ImmutableList.<PluginProperty>of(), callContext); try { paymentApi.addPaymentMethod(account, "thisonewillnotwork", ExternalPaymentProviderPlugin.PLUGIN_NAME, true, null, ImmutableList.<PluginProperty>of(), callContext); } catch (PaymentApiException e) { assertEquals(e.getCode(), ErrorCode.PAYMENT_EXTERNAL_PAYMENT_METHOD_ALREADY_EXISTS.getCode()); } }
@Test(groups = "slow") public void testNoPaymentMethod() throws Exception { final PaymentAutomatonDAOHelper daoHelper = createDAOHelper(UUID.randomUUID(), paymentExternalKey, paymentTransactionExternalKey, amount, currency); try { daoHelper.getPaymentPluginApi(); Assert.fail(); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_NO_SUCH_PAYMENT_METHOD.getCode()); } }
@Test(groups = "slow") public void testFailToRetrievePayment() throws Exception { // Verify a dummy payment doesn't exist final PaymentAutomatonDAOHelper daoHelper = createDAOHelper(UUID.randomUUID(), paymentExternalKey, paymentTransactionExternalKey, amount, currency); try { daoHelper.getPayment(); Assert.fail(); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_NO_SUCH_PAYMENT.getCode()); } }
@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()); } }
@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 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") public void testAddRemovePaymentMethodWithoutForcedDeletion() throws Exception { final Long baseNbRecords = paymentApi.getPaymentMethods(0L, 1000L, false, ImmutableList.<PluginProperty>of(), callContext).getMaxNbRecords(); Assert.assertEquals(baseNbRecords, (Long) 1L); final Account account = testHelper.createTestAccount(UUID.randomUUID().toString(), true); final UUID paymentMethodId = account.getPaymentMethodId(); try { paymentApi.deletePaymentMethod(account, paymentMethodId, false, false, ImmutableList.<PluginProperty>of(), callContext); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INTERNAL_ERROR.getCode()); } checkPaymentMethodPagination(paymentMethodId, baseNbRecords + 1, false); }
@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()); } }
@Test(groups = "slow") public void testSuccessfulInitialTransactionToSameTransaction() 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 processedPayment = createPayment(transactionType, null, paymentExternalKey, keyA, requestedAmount, PaymentPluginStatus.PROCESSED); assertNotNull(processedPayment); Assert.assertEquals(processedPayment.getTransactions().size(), 1); Assert.assertEquals(processedPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS); // 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(); try { createPayment(transactionType, processedPayment.getId(), paymentExternalKey, keyB, requestedAmount, PaymentPluginStatus.PROCESSED); Assert.fail("Retrying initial successful transaction (AUTHORIZE, PURCHASE, CREDIT) with same different key should fail"); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INVALID_OPERATION.getCode()); } // Attempt to create another {AUTH, PURCHASE, CREDIT} with same key => key constraint should make the request fail try { createPayment(transactionType, processedPayment.getId(), paymentExternalKey, keyA, requestedAmount, PaymentPluginStatus.PROCESSED); Assert.fail("Retrying initial successful transaction (AUTHORIZE, PURCHASE, CREDIT) with same transaction key should fail"); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_ACTIVE_TRANSACTION_KEY_EXISTS.getCode()); } } }
@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()); } }
@Test(groups = "slow") public void testCompletionOfUnknownCapture() throws Exception { final String paymentExternalKey = UUID.randomUUID().toString(); final BigDecimal requestedAmount = BigDecimal.TEN; final Payment authorization = createPayment(TransactionType.AUTHORIZE, null, paymentExternalKey, UUID.randomUUID().toString(), requestedAmount, PaymentPluginStatus.PROCESSED); assertNotNull(authorization); Assert.assertEquals(authorization.getTransactions().size(), 1); Assert.assertEquals(authorization.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS); final String paymentTransactionExternalKey = UUID.randomUUID().toString(); Payment pendingPayment = createPayment(TransactionType.CAPTURE, authorization.getId(), paymentExternalKey, paymentTransactionExternalKey, requestedAmount, PaymentPluginStatus.UNDEFINED); Assert.assertEquals(pendingPayment.getTransactions().size(), 2); Assert.assertEquals(pendingPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS); Assert.assertEquals(pendingPayment.getTransactions().get(1).getTransactionStatus(), TransactionStatus.UNKNOWN); try { // Attempt to complete the payment pendingPayment = createPayment(TransactionType.CAPTURE, authorization.getId(), paymentExternalKey, paymentTransactionExternalKey, requestedAmount, PaymentPluginStatus.PROCESSED); Assert.assertEquals(pendingPayment.getTransactions().size(), 2); Assert.fail(); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INVALID_OPERATION.getCode()); } }
@Test(groups = "slow") public void testCreatePurchaseWithTimeout() throws Exception { final BigDecimal requestedAmount = BigDecimal.TEN; final String paymentExternalKey = "ohhhh"; final String transactionExternalKey = "naaahhh"; mockPaymentProviderPlugin.makePluginWaitSomeMilliseconds((int) (paymentConfig.getPaymentPluginTimeout().getMillis() + 100)); try { paymentApi.createPurchase(account, account.getPaymentMethodId(), null, requestedAmount, Currency.AED, null, paymentExternalKey, transactionExternalKey, ImmutableList.<PluginProperty>of(), callContext); fail(); } catch (PaymentApiException e) { assertEquals(e.getCode(), ErrorCode.PAYMENT_PLUGIN_TIMEOUT.getCode()); } }
@Test(groups = "slow") public void testPendingInitialTransactionToSameTransaction() 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 pendingPayment = createPayment(transactionType, null, paymentExternalKey, keyA, requestedAmount, PaymentPluginStatus.PENDING); assertNotNull(pendingPayment); Assert.assertEquals(pendingPayment.getTransactions().size(), 1); Assert.assertEquals(pendingPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.PENDING); // 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(); try { createPayment(transactionType, pendingPayment.getId(), paymentExternalKey, keyB, requestedAmount, PaymentPluginStatus.PROCESSED); Assert.fail("Retrying initial successful transaction (AUTHORIZE, PURCHASE, CREDIT) with same different key should fail"); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INVALID_OPERATION.getCode()); } // Attempt to create another {AUTH, PURCHASE, CREDIT} with same key => That should work because we are completing the payment final Payment completedPayment = createPayment(transactionType, pendingPayment.getId(), paymentExternalKey, keyA, requestedAmount, PaymentPluginStatus.PROCESSED); assertNotNull(completedPayment); Assert.assertEquals(completedPayment.getId(), pendingPayment.getId()); Assert.assertEquals(completedPayment.getTransactions().size(), 1); } }
@Override public void run() { threadRunning.set(true); try { if (shouldFailBecauseOfLockFailure) { try { pluginOperation.dispatchWithAccountLockAndTimeout(PLUGIN_NAME_PLACEHOLDER, callback); Assert.fail(); } catch (final OperationException e) { Assert.assertTrue(e.getCause() instanceof PaymentApiException); // No better error code for lock failures... Assert.assertEquals(((PaymentApiException) e.getCause()).getCode(), ErrorCode.PAYMENT_INTERNAL_ERROR.getCode()); } } else { try { pluginOperation.dispatchWithAccountLockAndTimeout(PLUGIN_NAME_PLACEHOLDER, callback); } catch (final OperationException e) { Assert.fail(e.getMessage()); } } } finally { threadHasRun.set(true); } } });
@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()); } }
@Test(groups = "slow") public void testCreatePurchaseWithControlTimeout() throws Exception { final BigDecimal requestedAmount = BigDecimal.ONE; final String paymentExternalKey = "111111"; final String transactionExternalKey = "11111"; mockPaymentProviderPlugin.makePluginWaitSomeMilliseconds((int) (paymentConfig.getPaymentPluginTimeout().getMillis() + 100)); try { paymentApi.createPurchaseWithPaymentControl( account, account.getPaymentMethodId(), null, requestedAmount, Currency.AED, null, paymentExternalKey, transactionExternalKey, ImmutableList.<PluginProperty>of(), CONTROL_PLUGIN_OPTIONS, callContext); fail(); } catch (PaymentApiException e) { assertEquals(e.getCode(), ErrorCode.PAYMENT_PLUGIN_TIMEOUT.getCode()); } }
@Test(groups = "slow") public void testDoubleCaptureOnAPotentiallySuccessfulCapture() throws Exception { final String paymentExternalKey = UUID.randomUUID().toString(); final BigDecimal requestedAmount = BigDecimal.TEN; final Payment authorization = createPayment(TransactionType.AUTHORIZE, null, paymentExternalKey, UUID.randomUUID().toString(), requestedAmount, PaymentPluginStatus.PROCESSED); assertNotNull(authorization); Assert.assertEquals(authorization.getTransactions().size(), 1); Assert.assertEquals(authorization.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS); final String paymentTransactionExternalKey = UUID.randomUUID().toString(); // 1st capture with UNDEFINED Payment pendingPayment = createPayment(TransactionType.CAPTURE, authorization.getId(), paymentExternalKey, paymentTransactionExternalKey, requestedAmount, PaymentPluginStatus.UNDEFINED); Assert.assertEquals(pendingPayment.getTransactions().size(), 2); Assert.assertEquals(pendingPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS); Assert.assertEquals(pendingPayment.getTransactions().get(1).getTransactionStatus(), TransactionStatus.UNKNOWN); // but actually successful mockPaymentProviderPlugin.overridePaymentPluginStatus(pendingPayment.getId(), pendingPayment.getTransactions().get(1).getId(), PaymentPluginStatus.PROCESSED); // 2nd capture request with identical transaction external key try { createPayment(TransactionType.CAPTURE, authorization.getId(), paymentExternalKey, paymentTransactionExternalKey, requestedAmount, PaymentPluginStatus.PROCESSED); Assert.fail(); } catch (final PaymentApiException e) { final Payment refreshedPayment = paymentApi.getPayment(pendingPayment.getId(), true, false, ImmutableList.<PluginProperty>of(), callContext); Assert.assertEquals(refreshedPayment.getTransactions().size(), 2); Assert.assertEquals(refreshedPayment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS); Assert.assertEquals(refreshedPayment.getTransactions().get(1).getTransactionStatus(), TransactionStatus.SUCCESS); Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_ACTIVE_TRANSACTION_KEY_EXISTS.getCode()); } }
@Test(groups = "slow") public void testInvalidTransitionAfterFailure() throws PaymentApiException { final BigDecimal requestedAmount = BigDecimal.TEN; final String paymentExternalKey = "krapo"; final String transactionExternalKey = "grenouye"; final Payment payment = paymentApi.createAuthorization(account, account.getPaymentMethodId(), null, requestedAmount, Currency.EUR, null,paymentExternalKey, transactionExternalKey, ImmutableList.<PluginProperty>of(), callContext); // Hack the Database to make it look like it was a failure paymentDao.updatePaymentAndTransactionOnCompletion(account.getId(), null, payment.getId(), TransactionType.AUTHORIZE, "AUTH_ERRORED", null, payment.getTransactions().get(0).getId(), TransactionStatus.PLUGIN_FAILURE, null, null, null, null, internalCallContext); final PaymentSqlDao paymentSqlDao = dbi.onDemand(PaymentSqlDao.class); paymentSqlDao.updateLastSuccessPaymentStateName(payment.getId().toString(), "AUTH_ERRORED", null, internalCallContext); try { paymentApi.createCapture(account, payment.getId(), requestedAmount, Currency.EUR, null, "tetard", ImmutableList.<PluginProperty>of(), callContext); Assert.fail("Unexpected success"); } catch (final PaymentApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INVALID_OPERATION.getCode()); } }