Handle Webhook Transaction FAILED state

Created on 24 September 2024, 4 months ago

Problem/Motivation

In some cases, PostFinance Checkout Flex encounters issues (e.g., a UI crash), or a user fails to complete payment for an order. Despite this, the PostFinance Webhook is triggered, and the transaction is marked with a FAILED state.

Currently, these FAILED states are skipped, leaving the order in the "Cart" list within Drupal Commerce. The order remains as if it was neither placed nor canceled, which is not the desired behavior.

We aim to automatically cancel these payments and orders when a FAILED state is received from PostFinance, ensuring proper order management in Drupal Commerce.

We would like to cancel those payment & orders when receiving the FAILED state from Postfinance

Steps to reproduce

  • Create a cart on a Drupal Commerce instance and proceed to the checkout until you reach the PostFinance Gateway platform.
  • Stop at this stage and review the Orders list in PostFinance Checkout; the order will be in a "pending" state.
  • Wait a few minutes until the Webhook process begins. You should observe the Webhook being triggered.
  • However, the Webhook does not update the order to a FAILED state in Drupal Commerce. Instead, the order remains in the "Cart" list.

Proposed resolution

The solution is to cancel the associated orders in Drupal Commerce when the Webhook receives a FAILED state.

Remaining tasks

  • (Completed)
  • Community evaluation of the proposed patch (Waiting on Review)
  • Add tests in CheckoutWebhookTest

User interface changes

None

API changes

  • Orders with a FAILED state from PostFinance will now be canceled in Drupal Commerce instead of remaining as carts.

Data model changes

None

Feature request
Status

Active

Version

1.0

Component

Code

Created by

🇨🇭Switzerland wengerk Lausanne

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

Comments & Activities

  • Issue created by @wengerk
  • 🇨🇭Switzerland wengerk Lausanne
    +++ b/src/Plugin/Commerce/PaymentGateway/PostFinanceCheckout.php
    @@ -822,6 +825,14 @@ class PostFinanceCheckout extends OffsitePaymentGatewayBase implements PostFinan
    +        // Prevents \Drupal\commerce_payment\EventSubscriber\OrderPaidSubscriber::onPaid
    +        // to place the order on cancellation.
    +        if ($state === 'canceled') {
    +          $order = $order_storage->loadForUpdate($payment->getOrderId());
    +          $order->state->value = 'canceled';
    +          $order->save();
    +        }
    +
    

    I was unable to find a more effective way to prevent the order from being placed automatically.

    In our project, when the payment status was changed to 'canceled,' the system placed the order instead of canceling it, triggering the 'placed' transition and sending out order-related emails and other actions.

    Is there a better approach to handle order cancellations without triggering the order placement process?

  • 🇨🇭Switzerland wengerk Lausanne
  • Status changed to Needs review 2 months ago
  • 🇨🇭Switzerland znerol

    Hi! Thanks for the report and the patch, and sorry it took that long before somebody took a look.

    I guess the $payment->completed field shouldn't be updated for failed payments. It looks like this is subsequently checked by the PaymentOrderUpdater::updateOrder() to decide whether to update the total_paid field whenever the order is saved. Based on that, OrderStorage::doOrderPreSave() will dispatch the ORDER_PAID event.

  • 🇨🇭Switzerland znerol
    +++ b/src/Plugin/Commerce/PaymentGateway/PostFinanceCheckout.php
    @@ -567,6 +567,9 @@ class PostFinanceCheckout extends OffsitePaymentGatewayBase implements PostFinan
    +    if ($postfinance_state == 'FAILED') {
    +      $commerce_sate = 'canceled';
    +    }
    

    I was attempting to add tests for this change. However, it turns out that canceled is not valid as a payment state. See the commerce docs for a list of valid states, as well as the commerce_payment.workflows.yml for possible transitions.

Production build 0.71.5 2024