Known Issues

Verified payment bugs with workarounds and prevention patterns

3
Critical Issues
4
Major Issues
2
Minor Issues

Critical Issues

CRITICAL

Payment Method Becomes Unavailable Mid-Checkout

Problem

If a payment method's availability rules change (min/max order total, allowed countries) while customer is in checkout, they can encounter a silent failure when placing the order. The quote still has the payment method set, but it's no longer valid.

Impact

  • - Order placement fails with generic error
  • - Customer loses their cart configuration
  • - Payment gateway may have pending authorization

Workaround

// Add validation before order placement
class ValidatePaymentPlugin
{
    public function beforePlace(
        \Magento\Quote\Model\QuoteManagement $subject,
        CartInterface $quote,
        PaymentInterface $payment = null
    ) {
        $method = $quote->getPayment()->getMethod();
        $instance = $this->methodFactory->create($method);

        if (!$instance->isAvailable($quote)) {
            throw new LocalizedException(
                __('Selected payment method is no longer available.')
            );
        }
    }
}
CRITICAL

Gateway Response Handler Swallows Exceptions

Problem

If a response handler throws an exception after a successful gateway authorization, the exception may be caught and order placement fails, but the authorization remains active on the gateway. Customer is charged later or funds are held.

Impact

  • - Orphaned authorizations on payment gateway
  • - Customer funds held without order
  • - Manual reconciliation required

Workaround

// Implement void command on failure
class SafeResponseHandler implements HandlerInterface
{
    public function handle(array $handlingSubject, array $response)
    {
        try {
            // Normal handler logic
            $this->processResponse($handlingSubject, $response);
        } catch (\Exception $e) {
            // Void the transaction
            $this->voidCommand->execute($handlingSubject);
            throw $e;
        }
    }
}
CRITICAL

Sensitive Data in additional_information

Problem

Custom payment methods sometimes store full credit card numbers, CVV, or other sensitive data in the payment additional_information field. This data is persisted to the database unencrypted and may be exposed in admin, logs, or exports.

Impact

  • - PCI compliance violation
  • - Data breach risk
  • - Legal liability

Prevention

// NEVER store these in additional_information:
// - Full card number (cc_number)
// - CVV/CVC (cc_cid)
// - Full expiration date

// Instead, store only:
$payment->setAdditionalInformation([
    'cc_type' => 'VI',        // OK
    'cc_last4' => '1111',     // OK
    'transaction_id' => '...', // OK
    'auth_code' => '...',      // OK
]);

// Use Vault for tokenization

Major Issues

MAJOR

Method sortOrder Conflicts

Multiple payment methods with the same sortOrder display in unpredictable order. The "default" payment method selection in checkout may not match merchant expectations.

Workaround

Ensure unique sortOrder values for all payment methods. Use increments of 10 (e.g., 10, 20, 30) to allow insertion of new methods later.

MAJOR

Capture Fails Without Clear Error

When invoice capture fails due to expired authorization, the error message is often generic ("Unable to capture payment"). Admin users don't know if they need to re-authorize or if there's a gateway issue.

Workaround

// Implement detailed error mapping
<!-- error_mapping.xml -->
<error_messages>
    <message code="auth_expired">
        Authorization has expired. Please create a new order.
    </message>
    <message code="insufficient_funds">
        Card declined: Insufficient funds.
    </message>
</error_messages>
MAJOR

Free Payment Method with Negative Totals

When discounts or store credit make the order total $0 or negative, the "Free" payment method should activate. However, some configurations cause the method to not appear, leaving customers unable to complete checkout.

Workaround

Ensure payment/free/active is enabled. Check that the Free method's SpecificationInterface rules don't conflict with zero-total orders.

MAJOR

Partial Refund Transaction ID Collision

Multiple partial refunds may use the same base transaction ID, causing lookups to fail or return wrong transaction data. This affects reconciliation and dispute handling.

Workaround

// Generate unique refund transaction IDs
$payment->setTransactionId(
    $gatewayRefundId . '-refund-' . time()
);

Minor Issues

MINOR

Payment Method Icons Not Displaying

Custom payment method icons configured in admin don't display in checkout due to missing CSS or incorrect path configuration.

Workaround

Use absolute paths in config or implement a custom ConfigProvider that returns full URLs for icons.

MINOR

payment.log Grows Unbounded

The var/log/payment.log file can grow very large on high-traffic sites, especially with debug logging enabled for payment methods.

Workaround

Implement log rotation via cron or system-level logrotate. Disable debug logging in production (payment/method/debug = 0).

Prevention Best Practices

Security

  • Never store full card numbers in database
  • Use Vault for tokenization
  • Mask sensitive data in logs
  • Use HTTPS for all gateway communication

Reliability

  • Implement void on handler failure
  • Set appropriate gateway timeouts
  • Use unique transaction IDs
  • Implement comprehensive error mapping