The Completion functionality allows you to finalize the lifecycle of an authorized transaction. Completion can take two forms:
- Capture - Finalize an authorized transaction by capturing the funds (typically when goods are shipped)
- Void - Finalize an authorized transaction by cancelling it (if you decide not to proceed)
Both operations "complete" the transaction by moving it from an authorized state to a terminal state.
1. Transaction Completion (TransactionCompletion)
This is a Domain Entity that represents the result of a completion operation. It is independent of the SDK and contains:
- ID: The unique identifier of the completion.
- Linked Transaction ID: The ID of the transaction that was completed.
- State: The current state of the completion (e.g., SUCCESSFUL, PENDING, FAILED).
- Line Items: The list of items involved in the completion (useful for partial captures).
2. The Completion Gateway
Following the gateway pattern used in the checkout engine, the completion logic is encapsulated in the TransactionCompletionGatewayInterface. This allows the TransactionService to remain pure while delegating the SDK-specific calls to the infrastructure layer.
The TransactionCompletionService requires the TransactionCompletionGatewayInterface and a logger.
use PostFinanceCheckout\PluginCore\Transaction\Completion\TransactionCompletionService;
use PostFinanceCheckout\PluginCore\Sdk\SdkV1\TransactionCompletionGateway;
// 1. Setup Gateways
$completionGateway = new TransactionCompletionGateway($sdkProvider);
// 2. Setup Service
$completionService = new TransactionCompletionService(
$completionGateway,
$logger
);Completion can be performed in two ways:
Capture - Finalize the transaction by capturing funds
Typically triggered from a "Shipment" or "Capture" action in your shop's backend.
try {
// Perform the capture
$completion = $completionService->capture($spaceId, $transactionId);
echo "Capture successful! Completion ID: " . $completion->id;
} catch (TransactionException $e) {
// Handle specific capture errors (e.g., transaction not in AUTHORIZED state)
$logger->error("Capture failed: " . $e->getMessage());
}Void - Finalize the transaction by cancelling it
Typically triggered when you decide not to proceed with the transaction.
try {
// Perform the void
$state = $completionService->void($spaceId, $transactionId);
echo "Void successful! State: " . $state;
} catch (TransactionException $e) {
$logger->error("Void failed: " . $e->getMessage());
}Capture Flow:
sequenceDiagram
participant Admin
participant ShopBackend
participant PluginCore
participant PostFinanceCheckoutAPI
Admin->>ShopBackend: Clicks "Ship/Capture"
ShopBackend->>PluginCore: capture(spaceId, transactionId)
PluginCore->>PostFinanceCheckoutAPI: completeOnline(spaceId, transactionId)
PostFinanceCheckoutAPI-->>PluginCore: SDK TransactionCompletion
PluginCore-->>ShopBackend: Domain TransactionCompletion
ShopBackend-->>Admin: Show Success Message
Void Flow:
sequenceDiagram
participant Admin
participant ShopBackend
participant PluginCore
participant PostFinanceCheckoutAPI
Admin->>ShopBackend: Clicks "Cancel/Void"
ShopBackend->>PluginCore: void(spaceId, transactionId)
PluginCore->>PostFinanceCheckoutAPI: void(spaceId, transactionId)
PostFinanceCheckoutAPI-->>PluginCore: Updated Transaction State
PluginCore-->>ShopBackend: Void State
ShopBackend-->>Admin: Show Success Message
Capture Example:
- Start Checkout: Run
docs/Checkout/example/1_start_checkout.php. - Confirm & Pay: Run
docs/Checkout/example/3_confirm_checkout.php. Authorize the transaction. - Capture: Run
docs/Completion/example/capture.php- You will need to manually set the
transactionIdin the script as it does not automatically pick up the session.
- You will need to manually set the
Void Example:
- Start Checkout: Run
docs/Checkout/example/1_start_checkout.php. - Confirm & Pay: Run
docs/Checkout/example/3_confirm_checkout.php. Authorize the transaction. - Void: Run
docs/Completion/example/void.php.- You will need to manually set the
transactionIdin the script as it does not automatically pick up the session.
- You will need to manually set the