killbill-memoizeit
Changes
payment/src/main/java/org/killbill/billing/payment/core/sm/control/CompletionControlOperation.java 1(+0 -1)
payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java 123(+70 -53)
Details
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CompletionControlOperation.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CompletionControlOperation.java
index 09b1231..d6369e7 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CompletionControlOperation.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/CompletionControlOperation.java
@@ -59,7 +59,6 @@ public class CompletionControlOperation extends OperationControlCallback {
transaction.getCurrency(),
transaction.getProcessedAmount(),
transaction.getProcessedCurrency(),
- paymentStateContext.getProperties(),
paymentStateControlContext.isApiPayment(),
paymentStateContext.getCallContext());
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java
index d6ec560..1c2f87c 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/sm/control/OperationControlCallback.java
@@ -32,6 +32,7 @@ import org.killbill.automaton.OperationResult;
import org.killbill.billing.account.api.Account;
import org.killbill.billing.callcontext.DefaultCallContext;
import org.killbill.billing.catalog.api.Currency;
+import org.killbill.billing.control.plugin.api.OnSuccessPaymentControlResult;
import org.killbill.billing.osgi.api.OSGIServiceRegistration;
import org.killbill.billing.payment.api.Payment;
import org.killbill.billing.payment.api.PaymentApiException;
@@ -50,6 +51,7 @@ 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.payment.retry.DefaultPriorPaymentControlResult;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.commons.locker.GlobalLocker;
import org.killbill.commons.locker.LockFailedException;
@@ -92,7 +94,6 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
paymentStateContext.getTransactionType(),
paymentStateContext.getAmount(),
paymentStateContext.getCurrency(),
- paymentStateContext.getProperties(),
paymentStateControlContext.isApiPayment(),
paymentStateContext.getCallContext());
@@ -110,9 +111,6 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
final boolean success;
try {
- // Adjust amount with value returned by plugin if necessary
- adjustStateContextValues(paymentStateContext, pluginResult);
-
final Payment result = doCallSpecificOperationCallback();
((PaymentStateControlContext) paymentStateContext).setResult(result);
final PaymentTransaction transaction = ((PaymentStateControlContext) paymentStateContext).getCurrentTransaction();
@@ -131,7 +129,6 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
transaction.getCurrency(),
transaction.getProcessedAmount(),
transaction.getProcessedCurrency(),
- paymentStateContext.getProperties(),
paymentStateControlContext.isApiPayment(),
paymentStateContext.getCallContext());
@@ -173,40 +170,6 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
return new OperationException(e, getOperationResultOnException(paymentStateContext));
}
-
- protected void executePluginOnSuccessCalls(final List<String> paymentControlPluginNames, final PaymentControlContext paymentControlContext) {
- for (final String pluginName : paymentControlPluginNames) {
- final PaymentControlPluginApi plugin = paymentControlPluginRegistry.getServiceForName(pluginName);
- if (plugin != null) {
- try {
- plugin.onSuccessCall(paymentControlContext, paymentStateContext.getProperties());
- } catch (final PaymentControlApiException e) {
- logger.warn("Plugin " + pluginName + " failed to complete executePluginOnSuccessCalls call for " + paymentControlContext.getPaymentExternalKey(), e);
- }
- }
- }
- }
-
- private void adjustStateContextValues(final PaymentStateContext inputContext, @Nullable final PriorPaymentControlResult pluginResult) {
- if (pluginResult == null) {
- return;
- }
-
- final PaymentStateControlContext input = (PaymentStateControlContext) inputContext;
- if (pluginResult.getAdjustedAmount() != null) {
- input.setAmount(pluginResult.getAdjustedAmount());
- }
- if (pluginResult.getAdjustedCurrency() != null) {
- input.setCurrency(pluginResult.getAdjustedCurrency());
- }
- if (pluginResult.getAdjustedPaymentMethodId() != null) {
- input.setPaymentMethodId(pluginResult.getAdjustedPaymentMethodId());
- }
- if (pluginResult.getAdjustedPluginProperties() != null) {
- input.setProperties(pluginResult.getAdjustedPluginProperties());
- }
- }
-
private OperationResult getOperationResultOnException(final PaymentStateContext paymentStateContext) {
final PaymentStateControlContext paymentStateControlContext = (PaymentStateControlContext) paymentStateContext;
final OperationResult operationResult = paymentStateControlContext.getRetryDate() != null ? OperationResult.FAILURE : OperationResult.EXCEPTION;
@@ -217,7 +180,9 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
// Return as soon as the first plugin aborts, or the last result for the last plugin
PriorPaymentControlResult prevResult = null;
+ // Those values are adjusted prior each call with the result of what previous call to plugin returned
PaymentControlContext inputPaymentControlContext = paymentControlContextArg;
+ Iterable<PluginProperty> inputPluginProperties = paymentStateContext.getProperties();
for (final String pluginName : paymentControlPluginNames) {
final PaymentControlPluginApi plugin = paymentControlPluginRegistry.getServiceForName(pluginName);
@@ -226,7 +191,10 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
logger.warn("Skipping unknown payment control plugin {} when fetching results", pluginName);
continue;
}
- prevResult = plugin.priorCall(inputPaymentControlContext, paymentStateContext.getProperties());
+ prevResult = plugin.priorCall(inputPaymentControlContext, inputPluginProperties);
+ if (prevResult.getAdjustedPluginProperties() != null) {
+ inputPluginProperties = prevResult.getAdjustedPluginProperties();
+ }
if (prevResult.isAborted()) {
break;
}
@@ -239,14 +207,36 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
paymentStateContext.getTransactionType(),
prevResult.getAdjustedAmount() != null ? prevResult.getAdjustedAmount() : inputPaymentControlContext.getAmount(),
prevResult.getAdjustedCurrency() != null ? prevResult.getAdjustedCurrency() : inputPaymentControlContext.getCurrency(),
- prevResult.getAdjustedPluginProperties() != null ? prevResult.getAdjustedPluginProperties() : inputPaymentControlContext.getPluginProperties(),
paymentStateControlContext.isApiPayment(),
paymentStateContext.getCallContext());
}
+ // Rebuild latest result to include inputPluginProperties
+ prevResult = new DefaultPriorPaymentControlResult(prevResult, inputPluginProperties);
+ // Adjust context with all values if necessary
+ adjustStateContextForPriorCall(paymentStateContext, prevResult);
return prevResult;
}
+ protected void executePluginOnSuccessCalls(final List<String> paymentControlPluginNames, final PaymentControlContext paymentControlContext) {
+
+ Iterable<PluginProperty> inputPluginProperties = paymentStateContext.getProperties();
+ for (final String pluginName : paymentControlPluginNames) {
+ final PaymentControlPluginApi plugin = paymentControlPluginRegistry.getServiceForName(pluginName);
+ if (plugin != null) {
+ try {
+ final OnSuccessPaymentControlResult result = plugin.onSuccessCall(paymentControlContext, inputPluginProperties);
+ if (result.getAdjustedPluginProperties() != null) {
+ inputPluginProperties = result.getAdjustedPluginProperties();
+ }
+ } catch (final PaymentControlApiException e) {
+ logger.warn("Plugin " + pluginName + " failed to complete executePluginOnSuccessCalls call for " + paymentControlContext.getPaymentExternalKey(), e);
+ }
+ }
+ }
+ adjustStateContextPluginProperties(paymentStateContext, inputPluginProperties);
+ }
+
private OperationResult executePluginOnFailureCallsAndSetRetryDate(final PaymentStateControlContext paymentStateControlContext, final PaymentControlContext paymentControlContext) {
final DateTime retryDate = executePluginOnFailureCalls(paymentStateControlContext.getPaymentControlPluginNames(), paymentControlContext);
if (retryDate != null) {
@@ -256,26 +246,61 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
}
private DateTime executePluginOnFailureCalls(final List<String> paymentControlPluginNames, final PaymentControlContext paymentControlContext) {
+
DateTime candidate = null;
+ Iterable<PluginProperty> inputPluginProperties = paymentStateContext.getProperties();
+
for (final String pluginName : paymentControlPluginNames) {
final PaymentControlPluginApi plugin = paymentControlPluginRegistry.getServiceForName(pluginName);
if (plugin != null) {
try {
- final OnFailurePaymentControlResult result = plugin.onFailureCall(paymentControlContext, paymentStateContext.getProperties());
+ final OnFailurePaymentControlResult result = plugin.onFailureCall(paymentControlContext, inputPluginProperties);
if (candidate == null) {
candidate = result.getNextRetryDate();
} else if (result.getNextRetryDate() != null) {
candidate = candidate.compareTo(result.getNextRetryDate()) > 0 ? result.getNextRetryDate() : candidate;
}
+
+ if (result.getAdjustedPluginProperties() != null) {
+ inputPluginProperties = result.getAdjustedPluginProperties();
+ }
+
} catch (final PaymentControlApiException e) {
logger.warn("Plugin " + pluginName + " failed to return next retryDate for payment " + paymentControlContext.getPaymentExternalKey(), e);
return candidate;
}
}
}
+ adjustStateContextPluginProperties(paymentStateContext, inputPluginProperties);
return candidate;
}
+ private void adjustStateContextForPriorCall(final PaymentStateContext inputContext, @Nullable final PriorPaymentControlResult pluginResult) {
+ if (pluginResult == null) {
+ return;
+ }
+
+ final PaymentStateControlContext input = (PaymentStateControlContext) inputContext;
+ if (pluginResult.getAdjustedAmount() != null) {
+ input.setAmount(pluginResult.getAdjustedAmount());
+ }
+ if (pluginResult.getAdjustedCurrency() != null) {
+ input.setCurrency(pluginResult.getAdjustedCurrency());
+ }
+ if (pluginResult.getAdjustedPaymentMethodId() != null) {
+ input.setPaymentMethodId(pluginResult.getAdjustedPaymentMethodId());
+ }
+ adjustStateContextPluginProperties(inputContext, pluginResult.getAdjustedPluginProperties());
+ }
+
+ private void adjustStateContextPluginProperties(final PaymentStateContext inputContext, @Nullable Iterable<PluginProperty> pluginProperties) {
+ if (pluginProperties == null) {
+ return;
+ }
+ final PaymentStateControlContext input = (PaymentStateControlContext) inputContext;
+ input.setProperties(pluginProperties);
+ }
+
public static class DefaultPaymentControlContext extends DefaultCallContext implements PaymentControlContext {
private final Account account;
@@ -291,15 +316,14 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
private final BigDecimal processedAmount;
private final Currency processedCurrency;
private final boolean isApiPayment;
- private final Iterable<PluginProperty> properties;
public DefaultPaymentControlContext(final Account account, final UUID paymentMethodId, final UUID attemptId, @Nullable final UUID paymentId, final String paymentExternalKey, final String transactionExternalKey, final TransactionType transactionType, final BigDecimal amount, final Currency currency,
- final Iterable<PluginProperty> properties, final boolean isApiPayment, final CallContext callContext) {
- this(account, paymentMethodId, attemptId, paymentId, paymentExternalKey, null, transactionExternalKey, transactionType, amount, currency, null, null, properties, isApiPayment, callContext);
+ final boolean isApiPayment, final CallContext callContext) {
+ this(account, paymentMethodId, attemptId, paymentId, paymentExternalKey, null, transactionExternalKey, transactionType, amount, currency, null, null, isApiPayment, callContext);
}
public DefaultPaymentControlContext(final Account account, final UUID paymentMethodId, final UUID attemptId, @Nullable final UUID paymentId, final String paymentExternalKey, @Nullable final UUID transactionId, final String transactionExternalKey, final TransactionType transactionType,
- final BigDecimal amount, final Currency currency, @Nullable final BigDecimal processedAmount, @Nullable final Currency processedCurrency, final Iterable<PluginProperty> properties, final boolean isApiPayment, final CallContext callContext) {
+ final BigDecimal amount, final Currency currency, @Nullable final BigDecimal processedAmount, @Nullable final Currency processedCurrency, final boolean isApiPayment, final CallContext callContext) {
super(callContext.getTenantId(), callContext.getUserName(), callContext.getCallOrigin(), callContext.getUserType(), callContext.getReasonCode(), callContext.getComments(), callContext.getUserToken(), callContext.getCreatedDate(), callContext.getUpdatedDate());
this.account = account;
this.paymentMethodId = paymentMethodId;
@@ -313,7 +337,6 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
this.currency = currency;
this.processedAmount = processedAmount;
this.processedCurrency = processedCurrency;
- this.properties = properties;
this.isApiPayment = isApiPayment;
}
@@ -382,11 +405,6 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
}
@Override
- public Iterable<PluginProperty> getPluginProperties() {
- return properties;
- }
-
- @Override
public String toString() {
return "DefaultPaymentControlContext{" +
"account=" + account +
@@ -402,7 +420,6 @@ public abstract class OperationControlCallback extends OperationCallbackBase<Pay
", processedAmount=" + processedAmount +
", processedCurrency=" + processedCurrency +
", isApiPayment=" + isApiPayment +
- ", properties=" + properties +
'}';
}
}
diff --git a/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java b/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java
index 848d7e2..760b2c9 100644
--- a/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java
+++ b/payment/src/main/java/org/killbill/billing/payment/invoice/InvoicePaymentControlPluginApi.java
@@ -112,7 +112,7 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
}
@Override
- public PriorPaymentControlResult priorCall(final PaymentControlContext paymentControlContext, final Iterable<PluginProperty> properties) throws PaymentControlApiException {
+ public PriorPaymentControlResult priorCall(final PaymentControlContext paymentControlContext, final Iterable<PluginProperty> pluginProperties) throws PaymentControlApiException {
final TransactionType transactionType = paymentControlContext.getTransactionType();
Preconditions.checkArgument(transactionType == TransactionType.PURCHASE ||
transactionType == TransactionType.REFUND ||
@@ -121,9 +121,9 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
final InternalCallContext internalContext = internalCallContextFactory.createInternalCallContext(paymentControlContext.getAccountId(), paymentControlContext);
switch (transactionType) {
case PURCHASE:
- return getPluginPurchaseResult(paymentControlContext, internalContext);
+ return getPluginPurchaseResult(paymentControlContext, pluginProperties, internalContext);
case REFUND:
- return getPluginRefundResult(paymentControlContext, internalContext);
+ return getPluginRefundResult(paymentControlContext, pluginProperties, internalContext);
case CHARGEBACK:
return new DefaultPriorPaymentControlResult(false, paymentControlContext.getAmount());
default:
@@ -132,7 +132,7 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
}
@Override
- public OnSuccessPaymentControlResult onSuccessCall(final PaymentControlContext paymentControlContext, final Iterable<PluginProperty> properties) throws PaymentControlApiException {
+ public OnSuccessPaymentControlResult onSuccessCall(final PaymentControlContext paymentControlContext, final Iterable<PluginProperty> pluginProperties) throws PaymentControlApiException {
final TransactionType transactionType = paymentControlContext.getTransactionType();
Preconditions.checkArgument(transactionType == TransactionType.PURCHASE ||
transactionType == TransactionType.REFUND ||
@@ -143,7 +143,7 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
final InvoicePayment existingInvoicePayment;
switch (transactionType) {
case PURCHASE:
- final UUID invoiceId = getInvoiceId(paymentControlContext);
+ final UUID invoiceId = getInvoiceId(pluginProperties);
existingInvoicePayment = invoiceApi.getInvoicePaymentForAttempt(paymentControlContext.getPaymentId(), internalContext);
if (existingInvoicePayment != null) {
log.info("onSuccessCall was already completed for payment purchase :" + paymentControlContext.getPaymentId());
@@ -163,8 +163,8 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
if (existingInvoicePayment != null) {
log.info("onSuccessCall was already completed for payment refund :" + paymentControlContext.getPaymentId());
} else {
- final Map<UUID, BigDecimal> idWithAmount = extractIdsWithAmountFromProperties(paymentControlContext.getPluginProperties());
- final PluginProperty prop = getPluginProperty(paymentControlContext.getPluginProperties(), PROP_IPCD_REFUND_WITH_ADJUSTMENTS);
+ final Map<UUID, BigDecimal> idWithAmount = extractIdsWithAmountFromProperties(pluginProperties);
+ final PluginProperty prop = getPluginProperty(pluginProperties, PROP_IPCD_REFUND_WITH_ADJUSTMENTS);
final boolean isAdjusted = prop != null ? Boolean.valueOf((String) prop.getValue()) : false;
invoiceApi.createRefund(paymentControlContext.getPaymentId(), paymentControlContext.getAmount(), isAdjusted, idWithAmount, paymentControlContext.getTransactionExternalKey(), internalContext);
}
@@ -214,8 +214,8 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
controlDao.removeAutoPayOffEntry(account.getId());
}
- private UUID getInvoiceId(final PaymentControlContext paymentControlContext) throws PaymentControlApiException {
- final PluginProperty invoiceProp = getPluginProperty(paymentControlContext.getPluginProperties(), PROP_IPCD_INVOICE_ID);
+ private UUID getInvoiceId(final Iterable<PluginProperty> pluginProperties) throws PaymentControlApiException {
+ final PluginProperty invoiceProp = getPluginProperty(pluginProperties, PROP_IPCD_INVOICE_ID);
if (invoiceProp == null ||
!(invoiceProp.getValue() instanceof String)) {
throw new PaymentControlApiException("Need to specify a valid invoiceId in property " + PROP_IPCD_INVOICE_ID);
@@ -223,9 +223,9 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
return UUID.fromString((String) invoiceProp.getValue());
}
- private PriorPaymentControlResult getPluginPurchaseResult(final PaymentControlContext paymentControlPluginContext, final InternalCallContext internalContext) throws PaymentControlApiException {
+ private PriorPaymentControlResult getPluginPurchaseResult(final PaymentControlContext paymentControlPluginContext, final Iterable<PluginProperty> pluginProperties, final InternalCallContext internalContext) throws PaymentControlApiException {
try {
- final UUID invoiceId = getInvoiceId(paymentControlPluginContext);
+ final UUID invoiceId = getInvoiceId(pluginProperties);
final Invoice invoice = rebalanceAndGetInvoice(invoiceId, internalContext);
final BigDecimal requestedAmount = validateAndComputePaymentAmount(invoice, paymentControlPluginContext.getAmount(), paymentControlPluginContext.isApiPayment());
@@ -248,8 +248,8 @@ public final class InvoicePaymentControlPluginApi implements PaymentControlPlugi
}
}
- private PriorPaymentControlResult getPluginRefundResult(final PaymentControlContext paymentControlPluginContext, final InternalCallContext internalContext) throws PaymentControlApiException {
- final Map<UUID, BigDecimal> idWithAmount = extractIdsWithAmountFromProperties(paymentControlPluginContext.getPluginProperties());
+ private PriorPaymentControlResult getPluginRefundResult(final PaymentControlContext paymentControlPluginContext, final Iterable<PluginProperty> pluginProperties, final InternalCallContext internalContext) throws PaymentControlApiException {
+ final Map<UUID, BigDecimal> idWithAmount = extractIdsWithAmountFromProperties(pluginProperties);
if ((paymentControlPluginContext.getAmount() == null || paymentControlPluginContext.getAmount().compareTo(BigDecimal.ZERO) == 0) &&
idWithAmount.size() == 0) {
throw new PaymentControlApiException("Refund for payment, key = " + paymentControlPluginContext.getPaymentExternalKey() +
diff --git a/payment/src/main/java/org/killbill/billing/payment/retry/DefaultPriorPaymentControlResult.java b/payment/src/main/java/org/killbill/billing/payment/retry/DefaultPriorPaymentControlResult.java
index 1cb5f14..df030b0 100644
--- a/payment/src/main/java/org/killbill/billing/payment/retry/DefaultPriorPaymentControlResult.java
+++ b/payment/src/main/java/org/killbill/billing/payment/retry/DefaultPriorPaymentControlResult.java
@@ -52,6 +52,11 @@ public class DefaultPriorPaymentControlResult implements PriorPaymentControlResu
this(isAborted, null);
}
+
+ public DefaultPriorPaymentControlResult(final PriorPaymentControlResult input, final Iterable<PluginProperty> adjustedPluginProperties) {
+ this(input.isAborted(), input.getAdjustedAmount(), input.getAdjustedCurrency(), input.getAdjustedPaymentMethodId(), adjustedPluginProperties);
+ }
+
@Override
public boolean isAborted() {
return isAborted;