diff --git a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentGatewayApi.java b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentGatewayApi.java
index ae10edb..b4eb5c2 100644
--- a/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentGatewayApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/api/DefaultPaymentGatewayApi.java
@@ -55,7 +55,7 @@ public class DefaultPaymentGatewayApi extends DefaultApiBase implements PaymentG
}
@Override
- public HostedPaymentPageFormDescriptor buildFormDescriptor(final Account account, @Nullable final UUID paymentMethodId, final Iterable<PluginProperty> customFields, final Iterable<PluginProperty> properties, final CallContext callContext) throws PaymentApiException {
+ public HostedPaymentPageFormDescriptor buildFormDescriptor(final Account account, final UUID paymentMethodId, final Iterable<PluginProperty> customFields, final Iterable<PluginProperty> properties, final CallContext callContext) throws PaymentApiException {
final UUID paymentMethodIdToUse = paymentMethodId != null ? paymentMethodId : account.getPaymentMethodId();
if (paymentMethodId == null) {
@@ -66,7 +66,7 @@ public class DefaultPaymentGatewayApi extends DefaultApiBase implements PaymentG
}
@Override
- public HostedPaymentPageFormDescriptor buildFormDescriptorWithPaymentControl(final Account account, @Nullable final UUID paymentMethodId, final Iterable<PluginProperty> customFields, final Iterable<PluginProperty> properties, final PaymentOptions paymentOptions, final CallContext callContext) throws PaymentApiException {
+ public HostedPaymentPageFormDescriptor buildFormDescriptorWithPaymentControl(final Account account, final UUID paymentMethodId, final Iterable<PluginProperty> customFields, final Iterable<PluginProperty> properties, final PaymentOptions paymentOptions, final CallContext callContext) throws PaymentApiException {
return executeWithPaymentControl(account, paymentMethodId, properties, paymentOptions, callContext, new WithPaymentControlCallback<HostedPaymentPageFormDescriptor>() {
@Override
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApiWithControl.java b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApiWithControl.java
index 5d528a1..34f146d 100644
--- a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApiWithControl.java
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApiWithControl.java
@@ -46,7 +46,7 @@ import com.google.inject.Inject;
public class TestPaymentApiWithControl extends PaymentTestSuiteWithEmbeddedDB {
@Inject
- private OSGIServiceRegistration<PaymentControlPluginApi> retryPluginRegistry;
+ private OSGIServiceRegistration<PaymentControlPluginApi> controlPluginRegistry;
private Account account;
private UUID newPaymentMethodId;
@@ -58,7 +58,7 @@ public class TestPaymentApiWithControl extends PaymentTestSuiteWithEmbeddedDB {
final PaymentMethodPlugin paymentMethodInfo = new DefaultNoOpPaymentMethodPlugin(UUID.randomUUID().toString(), false, null);
newPaymentMethodId = paymentApi.addPaymentMethod(account, paymentMethodInfo.getExternalPaymentMethodId(), MockPaymentProviderPlugin.PLUGIN_NAME, false, paymentMethodInfo, ImmutableList.<PluginProperty>of(), callContext);
- retryPluginRegistry.registerService(new OSGIServiceDescriptor() {
+ controlPluginRegistry.registerService(new OSGIServiceDescriptor() {
@Override
public String getPluginSymbolicName() {
return null;
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentGatewayApiWithPaymentControl.java b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentGatewayApiWithPaymentControl.java
new file mode 100644
index 0000000..fb29bff
--- /dev/null
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentGatewayApiWithPaymentControl.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.payment.api;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.killbill.billing.account.api.Account;
+import org.killbill.billing.control.plugin.api.OnFailurePaymentControlResult;
+import org.killbill.billing.control.plugin.api.OnSuccessPaymentControlResult;
+import org.killbill.billing.control.plugin.api.PaymentControlApiException;
+import org.killbill.billing.control.plugin.api.PaymentControlContext;
+import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
+import org.killbill.billing.control.plugin.api.PriorPaymentControlResult;
+import org.killbill.billing.osgi.api.OSGIServiceDescriptor;
+import org.killbill.billing.osgi.api.OSGIServiceRegistration;
+import org.killbill.billing.payment.PaymentTestSuiteNoDB;
+import org.killbill.billing.payment.retry.DefaultFailureCallResult;
+import org.killbill.billing.payment.retry.DefaultOnSuccessPaymentControlResult;
+import org.killbill.billing.payment.retry.DefaultPriorPaymentControlResult;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.inject.Inject;
+
+public class TestPaymentGatewayApiWithPaymentControl extends PaymentTestSuiteNoDB {
+
+ @Inject
+ private OSGIServiceRegistration<PaymentControlPluginApi> controlPluginRegistry;
+
+ private Account account;
+
+ private PaymentOptions paymentOptions;
+
+ private TestPaymentGatewayApiControlPlugin plugin;
+ private TestPaymentGatewayApiValidationPlugin validationPlugin;
+
+ @BeforeMethod(groups = "fast")
+ public void beforeMethod() throws Exception {
+
+ super.beforeMethod();
+
+ account = testHelper.createTestAccount("arthur@gmail.com", true);
+
+ paymentOptions = new PaymentOptions() {
+ @Override
+ public boolean isExternalPayment() {
+ return false;
+ }
+
+ @Override
+ public List<String> getPaymentControlPluginNames() {
+ return ImmutableList.of(TestPaymentGatewayApiControlPlugin.PLUGIN_NAME, TestPaymentGatewayApiValidationPlugin.VALIDATION_PLUGIN_NAME);
+ }
+ };
+
+ plugin = new TestPaymentGatewayApiControlPlugin();
+
+ controlPluginRegistry.registerService(new OSGIServiceDescriptor() {
+ @Override
+ public String getPluginSymbolicName() {
+ return null;
+ }
+
+ @Override
+ public String getRegistrationName() {
+ return TestPaymentGatewayApiControlPlugin.PLUGIN_NAME;
+ }
+ }, plugin);
+
+ validationPlugin = new TestPaymentGatewayApiValidationPlugin();
+ controlPluginRegistry.registerService(new OSGIServiceDescriptor() {
+ @Override
+ public String getPluginSymbolicName() {
+ return null;
+ }
+
+ @Override
+ public String getRegistrationName() {
+ return TestPaymentGatewayApiValidationPlugin.VALIDATION_PLUGIN_NAME;
+ }
+ }, validationPlugin);
+
+ }
+
+ @Test(groups = "fast")
+ public void testBuildFormDescriptorWithPaymentControl() throws PaymentApiException {
+
+ final List<PluginProperty> initialProperties = new ArrayList<PluginProperty>();
+ initialProperties.add(new PluginProperty("keyA", "valueA", true));
+ initialProperties.add(new PluginProperty("keyB", "valueB", true));
+ initialProperties.add(new PluginProperty("keyC", "valueC", true));
+
+ final List<PluginProperty> priorNewProperties = new ArrayList<PluginProperty>();
+ priorNewProperties.add(new PluginProperty("keyD", "valueD", true));
+ final List<PluginProperty> priorRemovedProperties = new ArrayList<PluginProperty>();
+ priorRemovedProperties.add(new PluginProperty("keyA", "valueA", true));
+ plugin.setPriorCallProperties(priorNewProperties, priorRemovedProperties);
+
+ final List<PluginProperty> onResultNewProperties = new ArrayList<PluginProperty>();
+ onResultNewProperties.add(new PluginProperty("keyE", "valueE", true));
+ final List<PluginProperty> onResultRemovedProperties = new ArrayList<PluginProperty>();
+ onResultRemovedProperties.add(new PluginProperty("keyB", "valueB", true));
+ plugin.setOnResultProperties(onResultNewProperties, onResultRemovedProperties);
+
+ final List<PluginProperty> expectedPriorCallProperties = new ArrayList<PluginProperty>();
+ expectedPriorCallProperties.add(new PluginProperty("keyB", "valueB", true));
+ expectedPriorCallProperties.add(new PluginProperty("keyC", "valueC", true));
+ expectedPriorCallProperties.add(new PluginProperty("keyD", "valueD", true));
+
+ validationPlugin.setExpectedPriorCallProperties(expectedPriorCallProperties);
+
+ final List<PluginProperty> expectedProperties = new ArrayList<PluginProperty>();
+ expectedProperties.add(new PluginProperty("keyC", "valueC", true));
+ expectedProperties.add(new PluginProperty("keyD", "valueD", true));
+ expectedProperties.add(new PluginProperty("keyE", "valueE", true));
+
+ validationPlugin.setExpectedProperties(expectedProperties);
+
+ paymentGatewayApi.buildFormDescriptorWithPaymentControl(account, account.getPaymentMethodId(), ImmutableList.<PluginProperty>of(), initialProperties, paymentOptions, callContext);
+
+ }
+
+ public static class TestPaymentGatewayApiValidationPlugin implements PaymentControlPluginApi {
+
+ public static final String VALIDATION_PLUGIN_NAME = "TestPaymentGatewayApiValidationPlugin";
+
+ private Iterable<PluginProperty> expectedPriorCallProperties;
+ private Iterable<PluginProperty> expectedProperties;
+
+ public TestPaymentGatewayApiValidationPlugin() {
+ this.expectedPriorCallProperties = ImmutableList.of();
+ this.expectedProperties = ImmutableList.of();
+ }
+
+ public void setExpectedProperties(final Iterable<PluginProperty> expectedProperties) {
+ this.expectedProperties = expectedProperties;
+ }
+
+ public void setExpectedPriorCallProperties(final List<PluginProperty> expectedPriorCallProperties) {
+ this.expectedPriorCallProperties = expectedPriorCallProperties;
+ }
+
+ @Override
+ public PriorPaymentControlResult priorCall(final PaymentControlContext paymentControlContext, final Iterable<PluginProperty> properties) throws PaymentControlApiException {
+ validate(properties, expectedPriorCallProperties);
+ return new DefaultPriorPaymentControlResult(false);
+ }
+
+ @Override
+ public OnSuccessPaymentControlResult onSuccessCall(final PaymentControlContext paymentControlContext, final Iterable<PluginProperty> properties) throws PaymentControlApiException {
+ validate(properties, expectedProperties);
+ return new DefaultOnSuccessPaymentControlResult();
+ }
+
+ @Override
+ public OnFailurePaymentControlResult onFailureCall(final PaymentControlContext paymentControlContext, final Iterable<PluginProperty> properties) throws PaymentControlApiException {
+ validate(properties, expectedProperties);
+ return new DefaultFailureCallResult();
+ }
+
+ private static void validate(final Iterable<PluginProperty> properties, final Iterable<PluginProperty> expected) {
+ Assert.assertEquals(Iterables.size(properties), Iterables.size(expected), "Got " + Iterables.size(properties) + "properties" + ", expected " + Iterables.size(expected));
+
+ for (final PluginProperty curExpected : expected) {
+ Assert.assertTrue(Iterables.any(properties, new Predicate<PluginProperty>() {
+ @Override
+ public boolean apply(final PluginProperty input) {
+ return input.getKey().equals(curExpected.getKey()) && input.getValue().equals(curExpected.getValue());
+
+ }
+ }), "Cannot find expected property" + curExpected.getKey());
+ }
+ }
+
+ }
+
+ public static class TestPaymentGatewayApiControlPlugin implements PaymentControlPluginApi {
+
+ public static final String PLUGIN_NAME = "TestPaymentGatewayApiControlPlugin";
+
+ private Iterable<PluginProperty> newPriorCallProperties;
+ private Iterable<PluginProperty> removedPriorCallProperties;
+
+ private Iterable<PluginProperty> newOnResultProperties;
+ private Iterable<PluginProperty> removedOnResultProperties;
+
+ public TestPaymentGatewayApiControlPlugin() {
+ this.newPriorCallProperties = ImmutableList.of();
+ this.removedPriorCallProperties = ImmutableList.of();
+ this.newOnResultProperties = ImmutableList.of();
+ this.removedOnResultProperties = ImmutableList.of();
+ }
+
+ public void setPriorCallProperties(final Iterable<PluginProperty> newPriorCallProperties, final Iterable<PluginProperty> removedPriorCallProperties) {
+ this.newPriorCallProperties = newPriorCallProperties;
+ this.removedPriorCallProperties = removedPriorCallProperties;
+ }
+
+ public void setOnResultProperties(final Iterable<PluginProperty> newOnResultProperties, final Iterable<PluginProperty> removedOnResultProperties) {
+ this.newOnResultProperties = newOnResultProperties;
+ this.removedOnResultProperties = removedOnResultProperties;
+ }
+
+ @Override
+ public PriorPaymentControlResult priorCall(final PaymentControlContext paymentControlContext, final Iterable<PluginProperty> properties) throws PaymentControlApiException {
+ return new DefaultPriorPaymentControlResult(false, null, null, null, getAdjustedProperties(properties, newPriorCallProperties, removedPriorCallProperties));
+ }
+
+ @Override
+ public OnSuccessPaymentControlResult onSuccessCall(final PaymentControlContext paymentControlContext, final Iterable<PluginProperty> properties) throws PaymentControlApiException {
+ return new DefaultOnSuccessPaymentControlResult(getAdjustedProperties(properties, newOnResultProperties, removedOnResultProperties));
+ }
+
+ @Override
+ public OnFailurePaymentControlResult onFailureCall(final PaymentControlContext paymentControlContext, final Iterable<PluginProperty> properties) throws PaymentControlApiException {
+ return new DefaultFailureCallResult(null, getAdjustedProperties(properties, newOnResultProperties, removedOnResultProperties));
+ }
+
+ private static Iterable<PluginProperty> getAdjustedProperties(final Iterable<PluginProperty> input, final Iterable<PluginProperty> newProperties, final Iterable<PluginProperty> removedProperties) {
+ final Iterable<PluginProperty> filtered = Iterables.filter(input, new Predicate<PluginProperty>() {
+ @Override
+ public boolean apply(final PluginProperty p) {
+ final boolean toBeRemoved = Iterables.any(removedProperties, new Predicate<PluginProperty>() {
+ @Override
+ public boolean apply(final PluginProperty a) {
+ return a.getKey().equals(p.getKey()) && a.getValue().equals(p.getValue());
+ }
+ });
+ return !toBeRemoved;
+ }
+ });
+ return Iterables.concat(filtered, newProperties);
+ }
+ }
+
+}