killbill-memoizeit
Changes
payment/src/main/java/org/killbill/billing/payment/provider/ExternalPaymentProviderPlugin.java 61(+54 -7)
payment/src/test/java/org/killbill/billing/payment/provider/TestExternalPaymentProviderPlugin.java 2(+1 -1)
util/src/main/resources/ehcache.xml 8(+4 -4)
Details
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
index 1fb9dda..8c14531 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/InvoicePaymentResource.java
@@ -111,6 +111,7 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
@ApiResponse(code = 404, message = "Payment not found")})
public Response getInvoicePayment(@PathParam("paymentId") final String paymentIdStr,
@QueryParam(QUERY_WITH_PLUGIN_INFO) @DefaultValue("false") final Boolean withPluginInfo,
+ @QueryParam(QUERY_WITH_ATTEMPTS) @DefaultValue("false") final Boolean withAttempts,
@QueryParam(QUERY_PLUGIN_PROPERTY) final List<String> pluginPropertiesString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
@@ -118,7 +119,7 @@ public class InvoicePaymentResource extends JaxRsResourceBase {
final Iterable<PluginProperty> pluginProperties = extractPluginProperties(pluginPropertiesString);
final UUID paymentIdId = UUID.fromString(paymentIdStr);
final TenantContext tenantContext = context.createContext(request);
- final Payment payment = paymentApi.getPayment(paymentIdId, withPluginInfo, false, pluginProperties, tenantContext);
+ final Payment payment = paymentApi.getPayment(paymentIdId, withPluginInfo, withAttempts, pluginProperties, tenantContext);
final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(payment.getAccountId(), auditMode.getLevel(), tenantContext);
final List<InvoicePayment> invoicePayments = invoicePaymentApi.getInvoicePayments(paymentIdId, tenantContext);
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
index a2ef19c..c57de1c 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
@@ -713,7 +713,7 @@ public class PaymentProcessor extends ProcessorBase {
private PaymentAttemptModelDao getLastPaymentAttempt(final List<PaymentAttemptModelDao> pastPaymentAttempts, final UUID attemptId) {
if (!pastPaymentAttempts.isEmpty()) {
- for (int i = pastPaymentAttempts.size() - 1; i == 0; i--) {
+ for (int i = pastPaymentAttempts.size() - 1; i >= 0; i--) {
if (pastPaymentAttempts.get(i).getId().equals(attemptId)) {
return pastPaymentAttempts.get(i);
}
diff --git a/payment/src/main/java/org/killbill/billing/payment/provider/ExternalPaymentProviderPlugin.java b/payment/src/main/java/org/killbill/billing/payment/provider/ExternalPaymentProviderPlugin.java
index 33f1e30..db8a69e 100644
--- a/payment/src/main/java/org/killbill/billing/payment/provider/ExternalPaymentProviderPlugin.java
+++ b/payment/src/main/java/org/killbill/billing/payment/provider/ExternalPaymentProviderPlugin.java
@@ -36,12 +36,15 @@ import org.killbill.billing.payment.plugin.api.PaymentPluginStatus;
import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.TenantContext;
+import org.killbill.billing.util.config.definition.PaymentConfig;
import org.killbill.billing.util.entity.DefaultPagination;
import org.killbill.billing.util.entity.Pagination;
import org.killbill.clock.Clock;
+import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.inject.Inject;
/**
@@ -52,35 +55,37 @@ public class ExternalPaymentProviderPlugin implements PaymentPluginApi {
public static final String PLUGIN_NAME = "__EXTERNAL_PAYMENT__";
private final Clock clock;
+ private final PaymentConfig paymentConfig;
@Inject
- public ExternalPaymentProviderPlugin(final Clock clock) {
+ public ExternalPaymentProviderPlugin(final Clock clock, final PaymentConfig paymentConfig) {
this.clock = clock;
+ this.paymentConfig = paymentConfig;
}
@Override
public PaymentTransactionInfoPlugin authorizePayment(final UUID kbAccountId, final UUID kbPaymentId, final UUID kbTransactionId, final UUID kbPaymentMethodId, final BigDecimal amount, final Currency currency, final Iterable<PluginProperty> properties, final CallContext callContext) throws PaymentPluginApiException {
- return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.AUTHORIZE, amount, currency, clock.getUTCNow(), clock.getUTCNow(), PaymentPluginStatus.PROCESSED, null, null);
+ return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.AUTHORIZE, amount, currency, clock.getUTCNow(), clock.getUTCNow(), getPaymentPluginStatus(properties), null, null);
}
@Override
public PaymentTransactionInfoPlugin capturePayment(final UUID kbAccountId, final UUID kbPaymentId, final UUID kbTransactionId, final UUID kbPaymentMethodId, final BigDecimal amount, final Currency currency, final Iterable<PluginProperty> properties, final CallContext callContext) throws PaymentPluginApiException {
- return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.CAPTURE, amount, currency, clock.getUTCNow(), clock.getUTCNow(), PaymentPluginStatus.PROCESSED, null, null);
+ return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.CAPTURE, amount, currency, clock.getUTCNow(), clock.getUTCNow(), getPaymentPluginStatus(properties), null, null);
}
@Override
public PaymentTransactionInfoPlugin purchasePayment(final UUID kbAccountId, final UUID kbPaymentId, final UUID kbTransactionId, final UUID kbPaymentMethodId, final BigDecimal amount, final Currency currency, final Iterable<PluginProperty> properties, final CallContext context) throws PaymentPluginApiException {
- return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.PURCHASE, amount, currency, clock.getUTCNow(), clock.getUTCNow(), PaymentPluginStatus.PROCESSED, null, null);
+ return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.PURCHASE, amount, currency, clock.getUTCNow(), clock.getUTCNow(), getPaymentPluginStatus(properties), null, null);
}
@Override
public PaymentTransactionInfoPlugin voidPayment(final UUID kbAccountId, final UUID kbPaymentId, final UUID kbTransactionId, final UUID kbPaymentMethodId, final Iterable<PluginProperty> properties, final CallContext callContext) throws PaymentPluginApiException {
- return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.VOID, BigDecimal.ZERO, null, clock.getUTCNow(), clock.getUTCNow(), PaymentPluginStatus.PROCESSED, null, null);
+ return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.VOID, BigDecimal.ZERO, null, clock.getUTCNow(), clock.getUTCNow(), getPaymentPluginStatus(properties), null, null);
}
@Override
public PaymentTransactionInfoPlugin creditPayment(final UUID kbAccountId, final UUID kbPaymentId, final UUID kbTransactionId, final UUID kbPaymentMethodId, final BigDecimal amount, final Currency currency, final Iterable<PluginProperty> properties, final CallContext callContext) throws PaymentPluginApiException {
- return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.CREDIT, amount, currency, clock.getUTCNow(), clock.getUTCNow(), PaymentPluginStatus.PROCESSED, null, null);
+ return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.CREDIT, amount, currency, clock.getUTCNow(), clock.getUTCNow(), getPaymentPluginStatus(properties), null, null);
}
@Override
@@ -95,7 +100,7 @@ public class ExternalPaymentProviderPlugin implements PaymentPluginApi {
@Override
public PaymentTransactionInfoPlugin refundPayment(final UUID kbAccountId, final UUID kbPaymentId, final UUID kbTransactionId, final UUID kbPaymentMethodId, final BigDecimal refundAmount, final Currency currency, final Iterable<PluginProperty> properties, final CallContext context) throws PaymentPluginApiException {
- return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.REFUND, refundAmount, currency, clock.getUTCNow(), clock.getUTCNow(), PaymentPluginStatus.PROCESSED, null, null);
+ return new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, TransactionType.REFUND, refundAmount, currency, clock.getUTCNow(), clock.getUTCNow(), getPaymentPluginStatus(properties), null, null);
}
@Override
@@ -138,4 +143,46 @@ public class ExternalPaymentProviderPlugin implements PaymentPluginApi {
public GatewayNotification processNotification(final String notification, final Iterable<PluginProperty> properties, final CallContext callContext) throws PaymentPluginApiException {
return new DefaultNoOpGatewayNotification();
}
+
+ private PaymentPluginStatus getPaymentPluginStatus(final Iterable<PluginProperty> properties) throws PaymentPluginApiException {
+ if (shouldPaymentFailWithError(properties)) {
+ return PaymentPluginStatus.ERROR;
+ } else if (shouldPaymentFailWithException(properties)) {
+ throw new PaymentPluginApiException("Failed to process payment", "Triggered from killbill.external.payment.fail.cancellation");
+ } else if (shouldPaymentFailWithCancellation(properties)) {
+ return PaymentPluginStatus.CANCELED;
+ } else if (shouldPaymentTimeout(properties)) {
+ try {
+ Thread.sleep(paymentConfig.getPaymentPluginTimeout().getMillis() + 1000);
+ } catch (final InterruptedException ignored) {
+ }
+ }
+ return PaymentPluginStatus.PROCESSED;
+ }
+
+ private boolean shouldPaymentFailWithError(final Iterable<PluginProperty> properties) {
+ return isPropertySet(properties, "killbill.external.payment.fail.error");
+ }
+
+ private boolean shouldPaymentFailWithException(final Iterable<PluginProperty> properties) {
+ return isPropertySet(properties, "killbill.external.payment.fail.exception");
+ }
+
+ private boolean shouldPaymentFailWithCancellation(final Iterable<PluginProperty> properties) {
+ return isPropertySet(properties, "killbill.external.payment.fail.cancellation");
+ }
+
+ private boolean shouldPaymentTimeout(final Iterable<PluginProperty> properties) {
+ return isPropertySet(properties, "killbill.external.payment.fail.timeout");
+ }
+
+ private boolean isPropertySet(final Iterable<PluginProperty> properties, final String targetProperty) {
+ return Iterables.any(properties, new Predicate<PluginProperty>() {
+ @Override
+ public boolean apply(final PluginProperty input) {
+ return input.getKey().equals(targetProperty) && input.getValue().equals("true");
+ }
+ });
+ }
+
}
diff --git a/payment/src/test/java/org/killbill/billing/payment/provider/TestExternalPaymentProviderPlugin.java b/payment/src/test/java/org/killbill/billing/payment/provider/TestExternalPaymentProviderPlugin.java
index 3241ea5..5bd6128 100644
--- a/payment/src/test/java/org/killbill/billing/payment/provider/TestExternalPaymentProviderPlugin.java
+++ b/payment/src/test/java/org/killbill/billing/payment/provider/TestExternalPaymentProviderPlugin.java
@@ -45,7 +45,7 @@ public class TestExternalPaymentProviderPlugin extends PaymentTestSuiteNoDB {
@BeforeMethod(groups = "fast")
public void beforeMethod() throws Exception {
super.beforeMethod();
- plugin = new ExternalPaymentProviderPlugin(clock);
+ plugin = new ExternalPaymentProviderPlugin(clock, paymentConfig);
}
@Test(groups = "fast")
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java
index ae03c75..4acd0cd 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java
@@ -26,6 +26,8 @@ import java.util.Set;
import java.util.UUID;
import org.joda.time.DateTime;
+import org.killbill.billing.catalog.StandaloneCatalog;
+import org.killbill.billing.catalog.VersionedCatalog;
import org.killbill.billing.catalog.api.BillingPeriod;
import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.catalog.api.ProductCategory;
@@ -33,13 +35,13 @@ import org.killbill.billing.catalog.api.TimeUnit;
import org.killbill.billing.client.KillBillClientException;
import org.killbill.billing.client.RequestOptions;
import org.killbill.billing.client.model.Catalog;
-import org.killbill.billing.client.model.Catalogs;
import org.killbill.billing.client.model.Plan;
import org.killbill.billing.client.model.PlanDetail;
import org.killbill.billing.client.model.Product;
import org.killbill.billing.client.model.SimplePlan;
import org.killbill.billing.client.model.Tenant;
import org.killbill.billing.client.model.Usage;
+import org.killbill.xmlloader.XMLLoader;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -48,15 +50,23 @@ import com.google.common.io.Resources;
public class TestCatalog extends TestJaxrsBase {
-
-
- @Test(groups = "slow", description = "Upload and retrieve a per tenant catalog")
+ @Test(groups = "slow", description = "Upload and retrieve a per tenant catalog")
public void testMultiTenantCatalog() throws Exception {
- final String catalogPath = Resources.getResource("SpyCarBasic.xml").getPath();
- killBillClient.uploadXMLCatalog(catalogPath, createdBy, reason, comment);
+ final String versionPath1 = Resources.getResource("versionedCatalog/WeaponsHireSmall-1.xml").getPath();
+ killBillClient.uploadXMLCatalog(versionPath1, createdBy, reason, comment);
+ String catalog = killBillClient.getXMLCatalog();
+ Assert.assertNotNull(catalog);
- final String catalog = killBillClient.getXMLCatalog();
+
+ final String versionPath2 = Resources.getResource("versionedCatalog/WeaponsHireSmall-2.xml").getPath();
+ killBillClient.uploadXMLCatalog(versionPath2, createdBy, reason, comment);
+ catalog = killBillClient.getXMLCatalog();
Assert.assertNotNull(catalog);
+
+ //
+ // We can't deserialize the VersionedCatalog using our JAXB models because it contains several
+ // Standalone catalog and ids (JAXB name) are not unique across the various catalogs so deserialization would fail
+ //
}
@Test(groups = "slow", description = "Can retrieve a json version of the catalog")
util/src/main/resources/ehcache.xml 8(+4 -4)
diff --git a/util/src/main/resources/ehcache.xml b/util/src/main/resources/ehcache.xml
index cd6b114..61d098d 100644
--- a/util/src/main/resources/ehcache.xml
+++ b/util/src/main/resources/ehcache.xml
@@ -22,12 +22,12 @@
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<defaultCache
- maxElementsInMemory="0"
+ maxElementsInMemory="100000"
maxElementsOnDisk="0"
- eternal="false"
- timeToIdleSeconds="0"
- timeToLiveSeconds="0"
+ eternal="true"
overflowToDisk="false"
+ diskPersistent="false"
+ memoryStoreEvictionPolicy="LFU"
statistics="true"
/>