Skip to main content

Vault capture deep-dive

For the admin-facing config and trigger choices, see Vault capture configuration. This page documents the service architecture and extension seams.

The pipeline at a glance​

Order placement
│
▼
VaultTokenResolver
│ resolves the order's vault token (vault_payment_token row)
│ stores it on the byte8_preorder row at `vault_token_id`
│
▼
[ wait for trigger ]
│
├─ shipment_create → ShipmentPlugin marks vault_capture_pending
├─ shipment_track → TrackPlugin marks vault_capture_pending
└─ manual → admin grid action marks vault_capture_pending
│
▼
Cron/ProcessVaultCaptures (every 5 min)
│
▼
VaultMethodResolver → VaultCaptureService → gateway charge API
│
├─ success → status = succeeded → completion email
└─ failure → attempts++ → schedule retry
│
└─ if attempts ≥ max → fallback email + status = fallback_sent

Service classes​

ClassRole
Model/Service/VaultTokenResolverAt order placement, finds the vault token used to pay the deposit. Stores vault_token_id and vault_method_code on the pre-order.
Model/Service/VaultMethodResolverMaps the order's payment method code to the right gateway adapter for vault charge. Pluggable.
Model/Service/VaultCaptureServiceThe actual charge call. Wraps Magento Vault's CommandPool to execute the gateway's vault_authorize_capture command.
Cron/ProcessVaultCapturesThe background worker that picks up vault_capture_pending pre-orders and retries with backoff.

Plugin / extension points​

Add a custom gateway adapter​

If your gateway isn't auto-resolved by VaultMethodResolver, plugin around its resolveForOrder method:

public function aroundResolveForOrder(
VaultMethodResolver $subject,
callable $proceed,
OrderInterface $order
): VaultMethodInterface {
$methodCode = $order->getPayment()->getMethod();
if ($methodCode === 'my_custom_gateway_vault') {
return $this->myCustomAdapter;
}
return $proceed($order);
}

Override the retry schedule​

The default schedule is attempts × retry_backoff_minutes. To change, plugin Cron/ProcessVaultCaptures::scheduleNextAttempt:

public function aroundScheduleNextAttempt(
ProcessVaultCaptures $subject,
callable $proceed,
PreorderInterface $preorder
): \DateTimeInterface {
// exponential backoff
return new \DateTimeImmutable("+{$preorder->getVaultCaptureAttempts() ** 2} hours");
}

Hook the success / failure events​

VaultCaptureService dispatches:

  • byte8_preorder_vault_capture_success — after a successful charge, with preorder and transaction_id in the event data.
  • byte8_preorder_vault_capture_failure — after a failed charge, with preorder and error_message.

Subscribe in etc/events.xml to wire alerts, Slack notifications, ERP updates, etc.

Schema​

The byte8_preorder table carries:

ColumnTypeNotes
vault_token_idintFK to vault_payment_token.entity_id
vault_method_codevarcharPayment method code for resolver dispatch
vault_capture_statusvarcharEnum — see Model/Config/Source/VaultCaptureStatus
vault_capture_attemptsintRetry counter
vault_capture_last_errortextLast gateway error
vault_capture_next_attempt_atdatetimeWhen the cron should next try
vault_capture_completed_atdatetimeSuccess timestamp

Plus quote_item.preorder_id so the pre-order context survives quote-to-order conversion.

Gateway-specific notes​

  • Stripe — works with stripe_payments and the Stripe Magento connector's vault variants. Token format is the standard pm_... payment method ID.
  • Adyen — works with both adyen_cc and adyen_oneclick variants. Recurring contract reference must be present on the token.
  • Braintree — Vault stored as braintree payment method nonce → token. Both the standard and PayPal-via-Braintree flows are covered.
  • Authorize.net — Vault works via authorizenet_directpost with the CIM extension enabled. The vault token is the CIM customer profile ID.
  • PayPal Express — does NOT support vault capture. Pre-orders paid with PayPal Express are flagged vault_capture_status = unsupported at order placement and routed to the manual completion fallback automatically.

Failure modes​

ModeWhat it looks likeWhat to do
Token expiredGateway returns "Token not found"Send the customer to the manual completion link via fallback email.
Customer card declinedGateway returns insufficient funds / card-declinedCron retries up to max_attempts. After that, fallback email.
Gateway outageNetwork errors / 5xxCron retries automatically; usually clears within an hour.
Vault method changedCustomer deleted their stored cardvault_capture_status = unsupported, fallback email immediately.