Problem/Motivation

Steps to reproduce:

1. Enable PayPal WPS or EC as payment methods.
2. Create a GC of any amount
3. Apply GC to your order at checkout. Note that it is listed in the line items with its usage amount.
4. Choose PayPal as your payment method, and proceed to the PayPal login screen.
5. Click the "cancel and return to store" link to go back to the checkout review page.

Your gift card will have been removed from the line items of the order, and the transaction for the line item amount will be in Pending status. In some cases this means the user no longer can apply their GC because the transaction was created.

Proposed resolution

Do not set the transaction to Pending until the order is completed. This may be an issue with the default Rules for Commerce GC

Remaining tasks

I will try to test some solutions by editing the Rules used for applying the transactions, but the issue may also lie in the usage of hook_commerce_coupon_final_checkout_validate() which, in the case of how Commerce GC is handling its line items, does not seem to be fully compatible with payment methods that include off-site redirects.

(NOTE: Ordinary discount coupons from Commerce Coupon do not manifest this bug.)

User interface changes

None.

API changes

Possible changes to default Rules or the usage of hook_commerce_coupon_final_checkout_validate().

Comments

torgospizza’s picture

Priority: Normal » Major

I should note that we first encountered this bug when a user attempted to checkout with an amount less than 50 cents, which PayPal refused. In her case the review page refreshed and the GC had disappeared. So this is not only relegated to "canceling and returning" but if there is an error at checkout, this could occur as well.

I'm going to set this to Major because it essentially makes Commerce GC incompatible with off-site payment methods.

torgospizza’s picture

Status: Active » Closed (works as designed)

Upon further digging this looks to be the fault of Commerce PayPal's Express Checkout implementation of hook_checkout_router():

function commerce_paypal_ec_commerce_checkout_router($order, $checkout_page) {
  // If the current page is the Express Checkout page but the current order did
  // not use the Express Checkout flow...
  if ($checkout_page['page_id'] == 'paypal_ec' &&
    (empty($order->data['commerce_paypal_ec']['flow']) || $order->data['commerce_paypal_ec']['flow'] != 'ec')) {
    // Update the order status to the next checkout page.
    $next_page = $checkout_page['next_page'];
    $order = commerce_order_status_update($order, 'checkout_' . $next_page, FALSE, FALSE);

    // Inform modules of checkout completion if the next page is Completed.
    if ($next_page == 'complete') {
      commerce_checkout_complete($order);
    }

    // Redirect to the URL for the new checkout page.
    $target_uri = commerce_checkout_order_uri($order);
    return drupal_goto($target_uri);
  }
}

Particularly this bit:

  if ($next_page == 'complete') {
      commerce_checkout_complete($order);
  }

I have no idea why the module would just assume that checkout_complete() should be called at this stage, since errors and cancellations can happen at this point.

I will open a new issue against that project and close this one since PayPal EC appears to be the only payment method that does this.

Thanks and sorry for the false alarm.