@Test(groups = "slow") public void testUnknownEntriesWithExceptions() throws PaymentApiException, EventBusException { final BigDecimal requestedAmount = BigDecimal.TEN; final String paymentExternalKey = "minus"; final String transactionExternalKey = "plus"; // Make sure the state as seen by the plugin will be in PaymentPluginStatus.ERROR, which will be // returned later to Janitor mockPaymentProviderPlugin.makeNextPaymentFailWithException(); try { paymentApi.createAuthorization( account, account.getPaymentMethodId(), null, requestedAmount, account.getCurrency(), paymentExternalKey, transactionExternalKey, ImmutableList.<PluginProperty>of(), callContext); } catch (PaymentApiException ignore) { } final Payment payment = paymentApi.getPaymentByExternalKey( paymentExternalKey, false, ImmutableList.<PluginProperty>of(), callContext); // Artificially move the transaction status to UNKNOWN final String paymentStateName = paymentSMHelper.getErroredStateForTransaction(TransactionType.AUTHORIZE).toString(); paymentDao.updatePaymentAndTransactionOnCompletion( account.getId(), payment.getId(), TransactionType.AUTHORIZE, paymentStateName, paymentStateName, payment.getTransactions().get(0).getId(), TransactionStatus.UNKNOWN, requestedAmount, account.getCurrency(), "foo", "bar", internalCallContext); final List<PaymentTransactionModelDao> paymentTransactionHistoryBeforeJanitor = getPaymentTransactionHistory(transactionExternalKey); Assert.assertEquals(paymentTransactionHistoryBeforeJanitor.size(), 3); clock.addDays(1); try { Thread.sleep(1500); } catch (InterruptedException e) { } // Nothing new happened final List<PaymentTransactionModelDao> paymentTransactionHistoryAfterJanitor = getPaymentTransactionHistory(transactionExternalKey); Assert.assertEquals(paymentTransactionHistoryAfterJanitor.size(), 3); }
@Test(groups = "slow") public void testFailedPaymentWithPerTenantRetryConfig() throws Exception { // Create the tenant final String apiKeyTenant1 = "tenantSuperTuned"; final String apiSecretTenant1 = "2367$$ffr79"; loginTenant(apiKeyTenant1, apiSecretTenant1); final Tenant tenant1 = new Tenant(); tenant1.setApiKey(apiKeyTenant1); tenant1.setApiSecret(apiSecretTenant1); killBillClient.createTenant(tenant1, createdBy, reason, comment); // Configure our plugin to fail mockPaymentProviderPlugin.makeAllInvoicesFailWithError(true); // Upload the config final ObjectMapper mapper = new ObjectMapper(); final HashMap<String, String> perTenantProperties = new HashMap<String, String>(); perTenantProperties.put("org.killbill.payment.retry.days", "1,1,1"); final String perTenantConfig = mapper.writeValueAsString(perTenantProperties); final TenantKey tenantKey = killBillClient.postConfigurationPropertiesForTenant(perTenantConfig, basicRequestOptions()); final Account accountJson = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice(); final Payments payments = killBillClient.getPaymentsForAccount(accountJson.getAccountId()); Assert.assertEquals(payments.size(), 1); Assert.assertEquals(payments.get(0).getTransactions().size(), 1); // // Because we have specified a retry interval of one day we should see the new attempt after // moving clock 1 day (and not 8 days which is default) // // // Now unregister special per tenant config and we the first retry occurs one day after (and // still fails), it now sets a retry date of 8 days // killBillClient.unregisterConfigurationForTenant(basicRequestOptions()); // org.killbill.tenant.broadcast.rate has been set to 1s crappyWaitForLackOfProperSynchonization(2000); clock.addDays(1); Awaitility.await() .atMost(4, TimeUnit.SECONDS) .pollInterval(Duration.ONE_SECOND) .until( new Callable<Boolean>() { @Override public Boolean call() throws Exception { return killBillClient .getPaymentsForAccount(accountJson.getAccountId()) .get(0) .getTransactions() .size() == 2; } }); final Payments payments2 = killBillClient.getPaymentsForAccount(accountJson.getAccountId()); Assert.assertEquals(payments2.size(), 1); Assert.assertEquals(payments2.get(0).getTransactions().size(), 2); Assert.assertEquals( payments2.get(0).getTransactions().get(0).getStatus(), TransactionStatus.PAYMENT_FAILURE.name()); Assert.assertEquals( payments2.get(0).getTransactions().get(1).getStatus(), TransactionStatus.PAYMENT_FAILURE.name()); clock.addDays(1); crappyWaitForLackOfProperSynchonization(3000); // No retry with default config final Payments payments3 = killBillClient.getPaymentsForAccount(accountJson.getAccountId()); Assert.assertEquals(payments3.size(), 1); Assert.assertEquals(payments3.get(0).getTransactions().size(), 2); mockPaymentProviderPlugin.makeAllInvoicesFailWithError(false); clock.addDays(7); Awaitility.await() .atMost(4, TimeUnit.SECONDS) .pollInterval(Duration.ONE_SECOND) .until( new Callable<Boolean>() { @Override public Boolean call() throws Exception { return killBillClient .getPaymentsForAccount(accountJson.getAccountId()) .get(0) .getTransactions() .size() == 3; } }); final Payments payments4 = killBillClient.getPaymentsForAccount(accountJson.getAccountId()); Assert.assertEquals(payments4.size(), 1); Assert.assertEquals(payments4.get(0).getTransactions().size(), 3); Assert.assertEquals( payments4.get(0).getTransactions().get(0).getStatus(), TransactionStatus.PAYMENT_FAILURE.name()); Assert.assertEquals( payments4.get(0).getTransactions().get(1).getStatus(), TransactionStatus.PAYMENT_FAILURE.name()); Assert.assertEquals( payments4.get(0).getTransactions().get(2).getStatus(), TransactionStatus.SUCCESS.name()); }
@AfterMethod(groups = "slow") public void tearDown() throws Exception { mockPaymentProviderPlugin.clear(); }
@BeforeMethod(groups = "slow") public void beforeMethod() throws Exception { super.beforeMethod(); mockPaymentProviderPlugin.clear(); account = testHelper.createTestAccount("*****@*****.**", true); }