Free payments with custom Offsite Gateway

Created on 13 March 2025, 3 months ago

Describe your bug or feature request.

The new interface for handling free orders โ†’ is great, but our sole offsite custom payment gateway does not yet implement this new interface.
Reference: commerce_touchnet_upay.

After exploring multiple approaches, I'm trying to determine the recommended solution.
Our options seem to be:

  • Assign the order to the manual payment gateway (but that gateway does not implement SupportsZeroBalanceOrderInterface, which enforces SupportsStoredPaymentMethodsInterface as I would have expected... follow-up issue?).
  • Implement SupportsZeroBalanceOrderInterface along with SupportsStoredPaymentMethodsInterface in commerce_touchnet_upay, upgrade to 3.x, and resolve the issue properly.

Context (Commerce 2.x):

In 2.x, we encountered an issue where a product with a price of $0 triggers an error in finalizeCart().
This happens because the payment gateway is null when processing a zero-value order.
Interestingly, this issue does not occur when a product is discounted to $0โ€”only when its original price is $0, such as for a free event product.

As a workaround, we manually assign a payment gateway if none is set for a zero-value order:

/**
 * Implements hook_commerce_order_update().
 */
function MODULE_commerce_commerce_order_update(OrderInterface $order) {
  // Ensure the order has an assigned payment gateway for zero-value orders.
  if ($order->getTotalPrice()->isZero() && $order->get('payment_gateway')->isEmpty()) {
    $payment_gateway = PaymentGateway::load('upay');
    if ($payment_gateway) {
      $order->set('payment_gateway', $payment_gateway->id());
      $order->save();
    }
  }
}

Steps to reproduce (clean install):

  1. Enable an offsite payment gateway.
  2. Create a product with a price of $0.
  3. Proceed to checkout.
  4. Encounter errors:
    • In 3.x: There are no payment gateways available for this order. (when the interface is not implemented).
    • In 2.x: Error: Call to a member function getPlugin() on null in Drupal\commerce_cart\CartProvider->finalizeCart() (line 127 of commerce/modules/cart/src/CartProvider.php).

Request for Guidance:

Should we:

  • Assign free orders to the manual payment gateway despite it not implementing SupportsZeroBalanceOrderInterface?
  • Implement SupportsZeroBalanceOrderInterface and SupportsStoredPaymentMethodsInterface in commerce_touchnet_upay?
  • Handle this scenario differently?

Any recommendations would be appreciated! I made this a support request because it's been reported in various other ways including the parent related issues, and it's more of a question on the correct approach to take from maintainers

๐Ÿ’ฌ Support request
Status

Active

Version

3.0

Component

Developer experience

Created by

๐Ÿ‡จ๐Ÿ‡ฆCanada joelpittet Vancouver

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @joelpittet
  • ๐Ÿ‡จ๐Ÿ‡ฆCanada joelpittet Vancouver
  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    In 2.x: Error: Call to a member function getPlugin() on null in Drupal\commerce_cart\CartProvider->finalizeCart() (line 127 of commerce/modules/cart/src/CartProvider.php).

    There is no call to getPlugin() from the CartProvider, is it patched?

    Since commerce_touchnet_upay is offsite, I don't really see the need of redirecting the customer to the payment gateway? Wouldn't it make sense to skip collecting payment all together for free orders?

    IN this case I'd recommend writing a checkout flow resolver that resolves a different checkout flow that doesn't include the payment information pane in case the order contains free products?

  • ๐Ÿ‡จ๐Ÿ‡ฆCanada joelpittet Vancouver

    Thanks @jsacksick โ€” oh yes, that makes sense. Weโ€™re using ๐Ÿ› "Warning: session_id(): Cannot change session id" when cron runs to delete abandoned carts Needs review on 2.x, which explains the fatal error.

    We collect some payment info locally (like home address) to retain important order details before theyโ€™re handed off to the offsite gateway (TouchNet upay proxy for UBC). I suppose we could move that to a custom pane โ€” but would that avoid the error, or would we still hit There are no payment gateways available for this order. if the order is free in 3.x?

    For context, these are event registrations for kids learning to code.

    Also, regarding SupportsZeroBalanceOrderInterface โ€” should the manual payment gateway implement that? Should we?

  • ๐Ÿ‡ฎ๐Ÿ‡ฑIsrael jsacksick

    Also, regarding SupportsZeroBalanceOrderInterface โ€” should the manual payment gateway implement that? Should we?

    Nope, otherwise we would have implemented it already. This interface is mostly for onsite gateways that support tokenizing payment methods when the order is free. (Some gateways don't support 0$ authorizations for example).

    Other than that, drupal.org is probably not the right place to get support (as stated in our issue queue guidelines which recommends Stackexchange instead)... Also, feel free to ask in our Slack.

  • ๐Ÿ‡จ๐Ÿ‡ฆCanada joelpittet Vancouver

    I guess it's ecosystem support for the custom gateway, not general support, but I am happy to chat in Slack if that is where you prefer.

  • Status changed to Fixed 19 days ago
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024