diff --git a/payment/src/main/resources/org/killbill/billing/payment/PaymentStates.xml b/payment/src/main/resources/org/killbill/billing/payment/PaymentStates.xml
index da851a2..9031c87 100644
--- a/payment/src/main/resources/org/killbill/billing/payment/PaymentStates.xml
+++ b/payment/src/main/resources/org/killbill/billing/payment/PaymentStates.xml
@@ -441,30 +441,6 @@
<finalState>VOID_INIT</finalState>
</linkStateMachine>
<linkStateMachine>
- <initialStateMachine>VOID</initialStateMachine>
- <initialState>VOID_SUCCESS</initialState>
- <finalStateMachine>VOID</finalStateMachine>
- <finalState>VOID_INIT</finalState>
- </linkStateMachine>
- <linkStateMachine>
- <initialStateMachine>VOID</initialStateMachine>
- <initialState>VOID_SUCCESS</initialState>
- <finalStateMachine>CAPTURE</finalStateMachine>
- <finalState>CAPTURE_INIT</finalState>
- </linkStateMachine>
- <linkStateMachine>
- <initialStateMachine>VOID</initialStateMachine>
- <initialState>VOID_SUCCESS</initialState>
- <finalStateMachine>REFUND</finalStateMachine>
- <finalState>REFUND_INIT</finalState>
- </linkStateMachine>
- <linkStateMachine>
- <initialStateMachine>VOID</initialStateMachine>
- <initialState>VOID_SUCCESS</initialState>
- <finalStateMachine>CREDIT</finalStateMachine>
- <finalState>CREDIT_INIT</finalState>
- </linkStateMachine>
- <linkStateMachine>
<initialStateMachine>CAPTURE</initialStateMachine>
<initialState>CAPTURE_SUCCESS</initialState>
<finalStateMachine>REFUND</finalStateMachine>
@@ -483,12 +459,6 @@
<finalState>CHARGEBACK_INIT</finalState>
</linkStateMachine>
<linkStateMachine>
- <initialStateMachine>CAPTURE</initialStateMachine>
- <initialState>CAPTURE_SUCCESS</initialState>
- <finalStateMachine>VOID</finalStateMachine>
- <finalState>VOID_INIT</finalState>
- </linkStateMachine>
- <linkStateMachine>
<initialStateMachine>REFUND</initialStateMachine>
<initialState>REFUND_SUCCESS</initialState>
<finalStateMachine>REFUND</finalStateMachine>
@@ -501,12 +471,6 @@
<finalState>CHARGEBACK_INIT</finalState>
</linkStateMachine>
<linkStateMachine>
- <initialStateMachine>REFUND</initialStateMachine>
- <initialState>REFUND_SUCCESS</initialState>
- <finalStateMachine>VOID</finalStateMachine>
- <finalState>VOID_INIT</finalState>
- </linkStateMachine>
- <linkStateMachine>
<initialStateMachine>PURCHASE</initialStateMachine>
<initialState>PURCHASE_SUCCESS</initialState>
<finalStateMachine>REFUND</finalStateMachine>
@@ -519,12 +483,6 @@
<finalState>CHARGEBACK_INIT</finalState>
</linkStateMachine>
<linkStateMachine>
- <initialStateMachine>CREDIT</initialStateMachine>
- <initialState>CREDIT_SUCCESS</initialState>
- <finalStateMachine>VOID</finalStateMachine>
- <finalState>VOID_INIT</finalState>
- </linkStateMachine>
- <linkStateMachine>
<initialStateMachine>CHARGEBACK</initialStateMachine>
<initialState>CHARGEBACK_SUCCESS</initialState>
<finalStateMachine>CHARGEBACK</finalStateMachine>
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
index e7a1756..f95e0db 100644
--- a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
@@ -416,6 +416,9 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
@Test(groups = "slow")
public void testCreateSuccessAuthCaptureVoidCapture() throws PaymentApiException {
+ // Overwrite the default state machine to allow void on captures
+ stateMachineConfigCache.loadDefaultPaymentStateMachineConfig("org/killbill/billing/payment/PermissivePaymentStates.xml");
+
final BigDecimal authAmount = BigDecimal.TEN;
final BigDecimal captureAmount = BigDecimal.ONE;
@@ -533,7 +536,82 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
}
@Test(groups = "slow")
+ public void testCreateSuccessAuthCaptureVoidFailed() throws PaymentApiException {
+ final BigDecimal authAmount = BigDecimal.TEN;
+ final BigDecimal captureAmount = BigDecimal.ONE;
+
+ final String paymentExternalKey = UUID.randomUUID().toString();
+ final String transactionExternalKey = UUID.randomUUID().toString();
+ final String transactionExternalKey2 = UUID.randomUUID().toString();
+ final String transactionExternalKey3 = UUID.randomUUID().toString();
+
+ final Payment payment = paymentApi.createAuthorization(account, account.getPaymentMethodId(), null, authAmount, Currency.AED,
+ paymentExternalKey, transactionExternalKey,
+ ImmutableList.<PluginProperty>of(), callContext);
+
+ assertEquals(payment.getExternalKey(), paymentExternalKey);
+ assertEquals(payment.getPaymentMethodId(), account.getPaymentMethodId());
+ assertEquals(payment.getAccountId(), account.getId());
+ assertEquals(payment.getAuthAmount().compareTo(authAmount), 0);
+ assertEquals(payment.getCapturedAmount().compareTo(BigDecimal.ZERO), 0);
+ assertEquals(payment.getPurchasedAmount().compareTo(BigDecimal.ZERO), 0);
+ assertEquals(payment.getRefundedAmount().compareTo(BigDecimal.ZERO), 0);
+ assertEquals(payment.getCurrency(), Currency.AED);
+ assertFalse(payment.isAuthVoided());
+
+ assertEquals(payment.getTransactions().size(), 1);
+ assertEquals(payment.getTransactions().get(0).getExternalKey(), transactionExternalKey);
+ assertEquals(payment.getTransactions().get(0).getPaymentId(), payment.getId());
+ assertEquals(payment.getTransactions().get(0).getAmount().compareTo(authAmount), 0);
+ assertEquals(payment.getTransactions().get(0).getCurrency(), Currency.AED);
+ assertEquals(payment.getTransactions().get(0).getProcessedAmount().compareTo(authAmount), 0);
+ assertEquals(payment.getTransactions().get(0).getProcessedCurrency(), Currency.AED);
+
+ assertEquals(payment.getTransactions().get(0).getTransactionStatus(), TransactionStatus.SUCCESS);
+ assertEquals(payment.getTransactions().get(0).getTransactionType(), TransactionType.AUTHORIZE);
+ assertNotNull(payment.getTransactions().get(0).getGatewayErrorMsg());
+ assertNotNull(payment.getTransactions().get(0).getGatewayErrorCode());
+
+ final Payment payment2 = paymentApi.createCapture(account, payment.getId(), captureAmount, Currency.AED, transactionExternalKey2,
+ ImmutableList.<PluginProperty>of(), callContext);
+
+ assertEquals(payment2.getExternalKey(), paymentExternalKey);
+ assertEquals(payment2.getPaymentMethodId(), account.getPaymentMethodId());
+ assertEquals(payment2.getAccountId(), account.getId());
+ assertEquals(payment2.getAuthAmount().compareTo(authAmount), 0);
+ assertEquals(payment2.getCapturedAmount().compareTo(captureAmount), 0);
+ assertEquals(payment2.getPurchasedAmount().compareTo(BigDecimal.ZERO), 0);
+ assertEquals(payment2.getRefundedAmount().compareTo(BigDecimal.ZERO), 0);
+ assertEquals(payment2.getCurrency(), Currency.AED);
+ assertFalse(payment2.isAuthVoided());
+
+ assertEquals(payment2.getTransactions().size(), 2);
+ assertEquals(payment2.getTransactions().get(1).getExternalKey(), transactionExternalKey2);
+ assertEquals(payment2.getTransactions().get(1).getPaymentId(), payment.getId());
+ assertEquals(payment2.getTransactions().get(1).getAmount().compareTo(captureAmount), 0);
+ assertEquals(payment2.getTransactions().get(1).getCurrency(), Currency.AED);
+ assertEquals(payment2.getTransactions().get(1).getProcessedAmount().compareTo(captureAmount), 0);
+ assertEquals(payment2.getTransactions().get(1).getProcessedCurrency(), Currency.AED);
+
+ assertEquals(payment2.getTransactions().get(1).getTransactionStatus(), TransactionStatus.SUCCESS);
+ assertEquals(payment2.getTransactions().get(1).getTransactionType(), TransactionType.CAPTURE);
+ assertNotNull(payment2.getTransactions().get(1).getGatewayErrorMsg());
+ assertNotNull(payment2.getTransactions().get(1).getGatewayErrorCode());
+
+ try {
+ // Voiding a capture is prohibited by default
+ paymentApi.createVoid(account, payment.getId(), transactionExternalKey3, ImmutableList.<PluginProperty>of(), callContext);
+ Assert.fail();
+ } catch (final PaymentApiException e) {
+ Assert.assertEquals(e.getCode(), ErrorCode.PAYMENT_INVALID_OPERATION.getCode());
+ }
+ }
+
+ @Test(groups = "slow")
public void testCreateSuccessAuthCaptureVoidVoid() throws PaymentApiException {
+ // Overwrite the default state machine to allow void on captures
+ stateMachineConfigCache.loadDefaultPaymentStateMachineConfig("org/killbill/billing/payment/PermissivePaymentStates.xml");
+
final BigDecimal authAmount = BigDecimal.TEN;
final BigDecimal captureAmount = BigDecimal.ONE;
diff --git a/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteNoDB.java b/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteNoDB.java
index 74f2237..713219a 100644
--- a/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteNoDB.java
+++ b/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteNoDB.java
@@ -56,6 +56,8 @@ import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
+import static org.killbill.billing.payment.provider.MockPaymentControlProviderPlugin.PLUGIN_NAME;
+
public abstract class PaymentTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
@Inject
@@ -112,12 +114,13 @@ public abstract class PaymentTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
protected void beforeClass() throws Exception {
final Injector injector = Guice.createInjector(new TestPaymentModuleNoDB(configSource, getClock()));
injector.injectMembers(this);
-
- stateMachineConfigCache.loadDefaultPaymentStateMachineConfig(PaymentModule.DEFAULT_STATE_MACHINE_PAYMENT_XML);
}
@BeforeMethod(groups = "fast")
public void beforeMethod() throws Exception {
+ stateMachineConfigCache.clearPaymentStateMachineConfig(PLUGIN_NAME, internalCallContext);
+ stateMachineConfigCache.loadDefaultPaymentStateMachineConfig(PaymentModule.DEFAULT_STATE_MACHINE_PAYMENT_XML);
+
eventBus.start();
paymentExecutors.initialize();
((MockPaymentDao) paymentDao).reset();
diff --git a/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteWithEmbeddedDB.java b/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteWithEmbeddedDB.java
index d32f6ce..f0f7e09 100644
--- a/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteWithEmbeddedDB.java
+++ b/payment/src/test/java/org/killbill/billing/payment/PaymentTestSuiteWithEmbeddedDB.java
@@ -28,8 +28,8 @@ import org.killbill.billing.payment.api.PaymentApi;
import org.killbill.billing.payment.api.PaymentGatewayApi;
import org.killbill.billing.payment.caching.StateMachineConfigCache;
import org.killbill.billing.payment.core.PaymentExecutors;
-import org.killbill.billing.payment.core.PaymentProcessor;
import org.killbill.billing.payment.core.PaymentMethodProcessor;
+import org.killbill.billing.payment.core.PaymentProcessor;
import org.killbill.billing.payment.core.sm.PaymentStateMachineHelper;
import org.killbill.billing.payment.dao.PaymentDao;
import org.killbill.billing.payment.glue.PaymentModule;
@@ -50,6 +50,8 @@ import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
+import static org.killbill.billing.payment.provider.MockPaymentControlProviderPlugin.PLUGIN_NAME;
+
public abstract class PaymentTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuiteWithEmbeddedDB {
@Inject
@@ -98,18 +100,19 @@ public abstract class PaymentTestSuiteWithEmbeddedDB extends GuicyKillbillTestSu
protected void beforeClass() throws Exception {
final Injector injector = Guice.createInjector(new TestPaymentModuleWithEmbeddedDB(configSource, getClock()));
injector.injectMembers(this);
-
- stateMachineConfigCache.loadDefaultPaymentStateMachineConfig(PaymentModule.DEFAULT_STATE_MACHINE_PAYMENT_XML);
}
@BeforeMethod(groups = "slow")
public void beforeMethod() throws Exception {
super.beforeMethod();
+
+ stateMachineConfigCache.clearPaymentStateMachineConfig(PLUGIN_NAME, internalCallContext);
+ stateMachineConfigCache.loadDefaultPaymentStateMachineConfig(PaymentModule.DEFAULT_STATE_MACHINE_PAYMENT_XML);
+
paymentExecutors.initialize();
eventBus.start();
Profiling.resetPerThreadProfilingData();
clock.resetDeltaFromReality();
-
}
@AfterMethod(groups = "slow")
diff --git a/payment/src/test/resources/org/killbill/billing/payment/PermissivePaymentStates.xml b/payment/src/test/resources/org/killbill/billing/payment/PermissivePaymentStates.xml
new file mode 100644
index 0000000..99d4bb9
--- /dev/null
+++ b/payment/src/test/resources/org/killbill/billing/payment/PermissivePaymentStates.xml
@@ -0,0 +1,541 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2014-2016 Groupon, Inc
+ ~ Copyright 2014-2016 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.
+ -->
+
+<stateMachineConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="StateMachineConfig.xsd">
+
+ <stateMachines>
+ <stateMachine name="BIG_BANG">
+ <states>
+ <state name="BIG_BANG_INIT"/>
+ </states>
+ <transitions>
+ <transition>
+ <initialState>BIG_BANG_INIT</initialState>
+ <operation>OP_DUMMY</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>BIG_BANG_INIT</finalState>
+ </transition>
+ </transitions>
+ <operations>
+ <operation name="OP_DUMMY"/>
+ </operations>
+ </stateMachine>
+ <stateMachine name="AUTHORIZE">
+ <states>
+ <state name="AUTH_INIT"/>
+ <state name="AUTH_PENDING"/>
+ <state name="AUTH_SUCCESS"/>
+ <state name="AUTH_FAILED"/>
+ <state name="AUTH_ERRORED"/>
+ </states>
+ <transitions>
+ <transition>
+ <initialState>AUTH_INIT</initialState>
+ <operation>OP_AUTHORIZE</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>AUTH_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>AUTH_INIT</initialState>
+ <operation>OP_AUTHORIZE</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>AUTH_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>AUTH_INIT</initialState>
+ <operation>OP_AUTHORIZE</operation>
+ <operationResult>PENDING</operationResult>
+ <finalState>AUTH_PENDING</finalState>
+ </transition>
+ <transition>
+ <initialState>AUTH_PENDING</initialState>
+ <operation>OP_AUTHORIZE</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>AUTH_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>AUTH_PENDING</initialState>
+ <operation>OP_AUTHORIZE</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>AUTH_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>AUTH_PENDING</initialState>
+ <operation>OP_AUTHORIZE</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>AUTH_ERRORED</finalState>
+ </transition>
+ <transition>
+ <initialState>AUTH_INIT</initialState>
+ <operation>OP_AUTHORIZE</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>AUTH_ERRORED</finalState>
+ </transition>
+ </transitions>
+ <operations>
+ <operation name="OP_AUTHORIZE"/>
+ </operations>
+ </stateMachine>
+
+ <stateMachine name="CAPTURE">
+ <states>
+ <state name="CAPTURE_INIT"/>
+ <state name="CAPTURE_PENDING"/>
+ <state name="CAPTURE_SUCCESS"/>
+ <state name="CAPTURE_FAILED"/>
+ <state name="CAPTURE_ERRORED"/>
+ </states>
+ <transitions>
+ <transition>
+ <initialState>CAPTURE_INIT</initialState>
+ <operation>OP_CAPTURE</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>CAPTURE_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>CAPTURE_INIT</initialState>
+ <operation>OP_CAPTURE</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>CAPTURE_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>CAPTURE_INIT</initialState>
+ <operation>OP_CAPTURE</operation>
+ <operationResult>PENDING</operationResult>
+ <finalState>CAPTURE_PENDING</finalState>
+ </transition>
+ <transition>
+ <initialState>CAPTURE_PENDING</initialState>
+ <operation>OP_CAPTURE</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>CAPTURE_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>CAPTURE_PENDING</initialState>
+ <operation>OP_CAPTURE</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>CAPTURE_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>CAPTURE_PENDING</initialState>
+ <operation>OP_CAPTURE</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>CAPTURE_ERRORED</finalState>
+ </transition>
+ <transition>
+ <initialState>CAPTURE_INIT</initialState>
+ <operation>OP_CAPTURE</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>CAPTURE_ERRORED</finalState>
+ </transition>
+ </transitions>
+ <operations>
+ <operation name="OP_CAPTURE"/>
+ </operations>
+ </stateMachine>
+
+ <stateMachine name="PURCHASE">
+ <states>
+ <state name="PURCHASE_INIT"/>
+ <state name="PURCHASE_PENDING"/>
+ <state name="PURCHASE_SUCCESS"/>
+ <state name="PURCHASE_FAILED"/>
+ <state name="PURCHASE_ERRORED"/>
+ </states>
+ <transitions>
+ <transition>
+ <initialState>PURCHASE_INIT</initialState>
+ <operation>OP_PURCHASE</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>PURCHASE_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>PURCHASE_INIT</initialState>
+ <operation>OP_PURCHASE</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>PURCHASE_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>PURCHASE_INIT</initialState>
+ <operation>OP_PURCHASE</operation>
+ <operationResult>PENDING</operationResult>
+ <finalState>PURCHASE_PENDING</finalState>
+ </transition>
+ <transition>
+ <initialState>PURCHASE_PENDING</initialState>
+ <operation>OP_PURCHASE</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>PURCHASE_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>PURCHASE_PENDING</initialState>
+ <operation>OP_PURCHASE</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>PURCHASE_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>PURCHASE_PENDING</initialState>
+ <operation>OP_PURCHASE</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>PURCHASE_ERRORED</finalState>
+ </transition>
+ <transition>
+ <initialState>PURCHASE_INIT</initialState>
+ <operation>OP_PURCHASE</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>PURCHASE_ERRORED</finalState>
+ </transition>
+ </transitions>
+ <operations>
+ <operation name="OP_PURCHASE"/>
+ </operations>
+ </stateMachine>
+
+ <stateMachine name="REFUND">
+ <states>
+ <state name="REFUND_INIT"/>
+ <state name="REFUND_PENDING"/>
+ <state name="REFUND_SUCCESS"/>
+ <state name="REFUND_FAILED"/>
+ <state name="REFUND_ERRORED"/>
+ </states>
+ <transitions>
+ <transition>
+ <initialState>REFUND_INIT</initialState>
+ <operation>OP_REFUND</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>REFUND_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>REFUND_INIT</initialState>
+ <operation>OP_REFUND</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>REFUND_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>REFUND_INIT</initialState>
+ <operation>OP_REFUND</operation>
+ <operationResult>PENDING</operationResult>
+ <finalState>REFUND_PENDING</finalState>
+ </transition>
+ <transition>
+ <initialState>REFUND_PENDING</initialState>
+ <operation>OP_REFUND</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>REFUND_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>REFUND_PENDING</initialState>
+ <operation>OP_REFUND</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>REFUND_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>REFUND_PENDING</initialState>
+ <operation>OP_REFUND</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>REFUND_ERRORED</finalState>
+ </transition>
+ <transition>
+ <initialState>REFUND_INIT</initialState>
+ <operation>OP_REFUND</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>REFUND_ERRORED</finalState>
+ </transition>
+ </transitions>
+ <operations>
+ <operation name="OP_REFUND"/>
+ </operations>
+ </stateMachine>
+
+ <stateMachine name="CREDIT">
+ <states>
+ <state name="CREDIT_INIT"/>
+ <state name="CREDIT_PENDING"/>
+ <state name="CREDIT_SUCCESS"/>
+ <state name="CREDIT_FAILED"/>
+ <state name="CREDIT_ERRORED"/>
+ </states>
+ <transitions>
+ <transition>
+ <initialState>CREDIT_INIT</initialState>
+ <operation>OP_CREDIT</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>CREDIT_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>CREDIT_INIT</initialState>
+ <operation>OP_CREDIT</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>CREDIT_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>CREDIT_INIT</initialState>
+ <operation>OP_CREDIT</operation>
+ <operationResult>PENDING</operationResult>
+ <finalState>CREDIT_PENDING</finalState>
+ </transition>
+ <transition>
+ <initialState>CREDIT_PENDING</initialState>
+ <operation>OP_CREDIT</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>CREDIT_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>CREDIT_PENDING</initialState>
+ <operation>OP_CREDIT</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>CREDIT_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>CREDIT_PENDING</initialState>
+ <operation>OP_CREDIT</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>CREDIT_ERRORED</finalState>
+ </transition>
+ <transition>
+ <initialState>CREDIT_INIT</initialState>
+ <operation>OP_CREDIT</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>CREDIT_ERRORED</finalState>
+ </transition>
+ </transitions>
+ <operations>
+ <operation name="OP_CREDIT"/>
+ </operations>
+ </stateMachine>
+
+ <stateMachine name="VOID">
+ <states>
+ <state name="VOID_INIT"/>
+ <state name="VOID_PENDING"/>
+ <state name="VOID_SUCCESS"/>
+ <state name="VOID_FAILED"/>
+ <state name="VOID_ERRORED"/>
+ </states>
+ <transitions>
+ <transition>
+ <initialState>VOID_INIT</initialState>
+ <operation>OP_VOID</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>VOID_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>VOID_INIT</initialState>
+ <operation>OP_VOID</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>VOID_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>VOID_INIT</initialState>
+ <operation>OP_VOID</operation>
+ <operationResult>PENDING</operationResult>
+ <finalState>VOID_PENDING</finalState>
+ </transition>
+ <transition>
+ <initialState>VOID_PENDING</initialState>
+ <operation>OP_VOID</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>VOID_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>VOID_PENDING</initialState>
+ <operation>OP_VOID</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>VOID_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>VOID_PENDING</initialState>
+ <operation>OP_VOID</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>VOID_ERRORED</finalState>
+ </transition>
+ <transition>
+ <initialState>VOID_INIT</initialState>
+ <operation>OP_VOID</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>VOID_ERRORED</finalState>
+ </transition>
+ </transitions>
+ <operations>
+ <operation name="OP_VOID"/>
+ </operations>
+ </stateMachine>
+ <stateMachine name="CHARGEBACK">
+ <states>
+ <state name="CHARGEBACK_INIT"/>
+ <state name="CHARGEBACK_SUCCESS"/>
+ <state name="CHARGEBACK_FAILED"/>
+ <state name="CHARGEBACK_ERRORED"/>
+ </states>
+ <transitions>
+ <transition>
+ <initialState>CHARGEBACK_INIT</initialState>
+ <operation>OP_CHARGEBACK</operation>
+ <operationResult>SUCCESS</operationResult>
+ <finalState>CHARGEBACK_SUCCESS</finalState>
+ </transition>
+ <transition>
+ <initialState>CHARGEBACK_INIT</initialState>
+ <operation>OP_CHARGEBACK</operation>
+ <operationResult>FAILURE</operationResult>
+ <finalState>CHARGEBACK_FAILED</finalState>
+ </transition>
+ <transition>
+ <initialState>CHARGEBACK_INIT</initialState>
+ <operation>OP_CHARGEBACK</operation>
+ <operationResult>EXCEPTION</operationResult>
+ <finalState>CHARGEBACK_ERRORED</finalState>
+ </transition>
+ </transitions>
+ <operations>
+ <operation name="OP_CHARGEBACK"/>
+ </operations>
+ </stateMachine>
+ </stateMachines>
+
+ <linkStateMachines>
+ <linkStateMachine>
+ <initialStateMachine>BIG_BANG</initialStateMachine>
+ <initialState>BIG_BANG_INIT</initialState>
+ <finalStateMachine>AUTHORIZE</finalStateMachine>
+ <finalState>AUTH_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>BIG_BANG</initialStateMachine>
+ <initialState>BIG_BANG_INIT</initialState>
+ <finalStateMachine>PURCHASE</finalStateMachine>
+ <finalState>PURCHASE_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>BIG_BANG</initialStateMachine>
+ <initialState>BIG_BANG_INIT</initialState>
+ <finalStateMachine>CREDIT</finalStateMachine>
+ <finalState>CREDIT_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>AUTHORIZE</initialStateMachine>
+ <initialState>AUTH_SUCCESS</initialState>
+ <finalStateMachine>CAPTURE</finalStateMachine>
+ <finalState>CAPTURE_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>AUTHORIZE</initialStateMachine>
+ <initialState>AUTH_SUCCESS</initialState>
+ <finalStateMachine>VOID</finalStateMachine>
+ <finalState>VOID_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>VOID</initialStateMachine>
+ <initialState>VOID_SUCCESS</initialState>
+ <finalStateMachine>VOID</finalStateMachine>
+ <finalState>VOID_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>VOID</initialStateMachine>
+ <initialState>VOID_SUCCESS</initialState>
+ <finalStateMachine>CAPTURE</finalStateMachine>
+ <finalState>CAPTURE_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>VOID</initialStateMachine>
+ <initialState>VOID_SUCCESS</initialState>
+ <finalStateMachine>REFUND</finalStateMachine>
+ <finalState>REFUND_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>VOID</initialStateMachine>
+ <initialState>VOID_SUCCESS</initialState>
+ <finalStateMachine>CREDIT</finalStateMachine>
+ <finalState>CREDIT_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>CAPTURE</initialStateMachine>
+ <initialState>CAPTURE_SUCCESS</initialState>
+ <finalStateMachine>REFUND</finalStateMachine>
+ <finalState>REFUND_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>CAPTURE</initialStateMachine>
+ <initialState>CAPTURE_SUCCESS</initialState>
+ <finalStateMachine>CAPTURE</finalStateMachine>
+ <finalState>CAPTURE_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>CAPTURE</initialStateMachine>
+ <initialState>CAPTURE_SUCCESS</initialState>
+ <finalStateMachine>CHARGEBACK</finalStateMachine>
+ <finalState>CHARGEBACK_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>CAPTURE</initialStateMachine>
+ <initialState>CAPTURE_SUCCESS</initialState>
+ <finalStateMachine>VOID</finalStateMachine>
+ <finalState>VOID_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>REFUND</initialStateMachine>
+ <initialState>REFUND_SUCCESS</initialState>
+ <finalStateMachine>REFUND</finalStateMachine>
+ <finalState>REFUND_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>REFUND</initialStateMachine>
+ <initialState>REFUND_SUCCESS</initialState>
+ <finalStateMachine>CHARGEBACK</finalStateMachine>
+ <finalState>CHARGEBACK_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>REFUND</initialStateMachine>
+ <initialState>REFUND_SUCCESS</initialState>
+ <finalStateMachine>VOID</finalStateMachine>
+ <finalState>VOID_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>PURCHASE</initialStateMachine>
+ <initialState>PURCHASE_SUCCESS</initialState>
+ <finalStateMachine>REFUND</finalStateMachine>
+ <finalState>REFUND_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>PURCHASE</initialStateMachine>
+ <initialState>PURCHASE_SUCCESS</initialState>
+ <finalStateMachine>CHARGEBACK</finalStateMachine>
+ <finalState>CHARGEBACK_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>CREDIT</initialStateMachine>
+ <initialState>CREDIT_SUCCESS</initialState>
+ <finalStateMachine>VOID</finalStateMachine>
+ <finalState>VOID_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>CHARGEBACK</initialStateMachine>
+ <initialState>CHARGEBACK_SUCCESS</initialState>
+ <finalStateMachine>CHARGEBACK</finalStateMachine>
+ <finalState>CHARGEBACK_INIT</finalState>
+ </linkStateMachine>
+ <linkStateMachine>
+ <initialStateMachine>CHARGEBACK</initialStateMachine>
+ <initialState>CHARGEBACK_FAILED</initialState>
+ <finalStateMachine>REFUND</finalStateMachine>
+ <finalState>REFUND_INIT</finalState>
+ </linkStateMachine>
+ </linkStateMachines>
+</stateMachineConfig>