In the past couple of months I've had an issue pop up randomly on some PayPal transactions where the payment shows twice in the admin views with time stamps (created/changed) just a few seconds apart but otherwise identical. I've verified with PayPal that only a single payment was captured. This does not involve foreign currencies as was mentioned in another issue. I havenever had this occur with Auth.net transactions which are also enabled on my site. Is it possible that some users click back or refresh causing two successful transaction messages to be captured?

Here are the rows from the payment table for an example order. I apologize if I took too much detail out but i didn't want to risk exposing customer data:

(196, 196, 0, 623, 'paypal_wps', 'paypal_wps|commerce_payment_paypal_wps', '04K341671P088693R', 'The payment has completed.', 'a:0:{}', 24318, 'USD', 'success', 'Completed', '
a : 1 : {
	i : 1349393043;
	a : 50 : {
		s : 8 : "mc_gross";
		s : 6 : "243.18";
		s : 7 : "invoice";
		s : 14 : "623-1349392965";
		s : 9 : "item_mpn1";
		s : 0 : "";
		s : 22 : "protection_eligibility";
		s : 10 : "Ineligible";
		s : 16 : "item_count_unit1";
		s : 1 : "0";
		s : 12 : "item_number1";
		s : 0 : "";
		s : 3 : "tax";
		s : 4 : "0.00";
		s : 8 : "payer_id";
		s : 13 : "Sanitized";
		s : 12 : "payment_date";
		s : 25 : "16:19:05 Oct 04, 2012 PDT";
		s : 14 : "item_tax_rate1";
		s : 1 : "0";
		s : 19 : "option_selection1_1";
		s : 1 : "1";
		s : 14 : "payment_status";
		s : 9 : "Completed";
		s : 7 : "charset";
		s : 12 : "windows-1252";
		s : 11 : "mc_shipping";
		s : 4 : "0.00";
		s : 21 : "item_tax_rate_double1";
		s : 4 : "0.00";
		s : 11 : "mc_handling";
		s : 4 : "0.00";
		s : 10 : "first_name";
		s : 5 : "Sanitized";
		s : 6 : "Sanitized";
		s : 4 : "7.35";
		s : 14 : "notify_version";
		s : 3 : "3.7";
		s : 6 : "custom";
		s : 0 : "";
		s : 12 : "payer_status";
		s : 10 : "unverified";
		s : 8 : "business";
		s : 23 : "Sanitized";
		s : 14 : "num_cart_items";
		s : 1 : "1";
		s : 12 : "mc_handling1";
		s : 4 : "0.00";
		s : 11 : "verify_sign";
		s : 56 : "Sanitized";
		s : 11 : "payer_email";
		s : 18 : "Sanitized";
		s : 12 : "mc_shipping1";
		s : 4 : "0.00";
		s : 18 : "item_style_number1";
		s : 0 : "";
		s : 4 : "tax1";
		s : 4 : "0.00";
		s : 14 : "option_name1_1";
		s : 13 : "Product count";
		s : 9 : "item_plu1";
		s : 0 : "";
		s : 6 : "txn_id";
		s : 17 : "Sanitized But Matches Dupe";
		s : 12 : "payment_type";
		s : 7 : "instant";
		s : 9 : "last_name";
		s : 6 : "Sanitized";
		s : 10 : "item_isbn1";
		s : 0 : "";
		s : 10 : "item_name1";
		s : 46 : "Sanitized";
		s : 14 : "receiver_email";
		s : 23 : "Sanitized";
		s : 11 : "payment_fee";
		s : 4 : "7.35";
		s : 9 : "quantity1";
		s : 1 : "1";
		s : 11 : "receiver_id";
		s : 13 : "Sanitized";
		s : 8 : "txn_type";
		s : 4 : "cart";
		s : 18 : "item_model_number1";
		s : 0 : "";
		s : 10 : "mc_gross_1";
		s : 6 : "243.18";
		s : 11 : "mc_currency";
		s : 3 : "USD";
		s : 13 : "item_taxable1";
		s : 1 : "N";
		s : 17 : "residence_country";
		s : 2 : "US";
		s : 19 : "transaction_subject";
		s : 59 : "Sanitized";
		s : 13 : "payment_gross";
		s : 6 : "243.18";
		s : 12 : "ipn_track_id";
		s : 13 : "Sanitized but matched";
		s : 8 : "order_id";
		s : 3 : "623";
	}
}
', 1349393043, 1349393043, NULL),

(197, 197, 0, 623, 'paypal_wps', 'paypal_wps|commerce_payment_paypal_wps', '04K341671P088693R', 'The payment has completed.', 'a:0:{}', 24318, 'USD', 'success', 'Completed', '
a : 1 : {
	i : 1349393058;
	a : 50 : {
		s : 8 : "mc_gross";
		s : 6 : "243.18";
		s : 7 : "invoice";
		s : 14 : "623-1349392965";
		s : 9 : "item_mpn1";
		s : 0 : "";
		s : 22 : "protection_eligibility";
		s : 10 : "Ineligible";
		s : 16 : "item_count_unit1";
		s : 1 : "0";
		s : 12 : "item_number1";
		s : 0 : "";
		s : 3 : "tax";
		s : 4 : "0.00";
		s : 8 : "payer_id";
		s : 13 : "Sanitized";
		s : 12 : "payment_date";
		s : 25 : "16:19:05 Oct 04, 2012 PDT";
		s : 14 : "item_tax_rate1";
		s : 1 : "0";
		s : 19 : "option_selection1_1";
		s : 1 : "1";
		s : 14 : "payment_status";
		s : 9 : "Completed";
		s : 7 : "charset";
		s : 12 : "windows-1252";
		s : 11 : "mc_shipping";
		s : 4 : "0.00";
		s : 21 : "item_tax_rate_double1";
		s : 4 : "0.00";
		s : 11 : "mc_handling";
		s : 4 : "0.00";
		s : 10 : "first_name";
		s : 5 : "Sanitized";
		s : 6 : "Sanitized";
		s : 4 : "7.35";
		s : 14 : "notify_version";
		s : 3 : "3.7";
		s : 6 : "custom";
		s : 0 : "";
		s : 12 : "payer_status";
		s : 10 : "unverified";
		s : 8 : "business";
		s : 23 : "Sanitized";
		s : 14 : "num_cart_items";
		s : 1 : "1";
		s : 12 : "mc_handling1";
		s : 4 : "0.00";
		s : 11 : "verify_sign";
		s : 56 : "Sanitized";
		s : 11 : "payer_email";
		s : 18 : "Sanitized";
		s : 12 : "mc_shipping1";
		s : 4 : "0.00";
		s : 18 : "item_style_number1";
		s : 0 : "";
		s : 4 : "tax1";
		s : 4 : "0.00";
		s : 14 : "option_name1_1";
		s : 13 : "Product count";
		s : 9 : "item_plu1";
		s : 0 : "";
		s : 6 : "txn_id";
		s : 17 : "Sanitized But Matches Dupe";
		s : 12 : "payment_type";
		s : 7 : "instant";
		s : 9 : "last_name";
		s : 6 : "Sanitized";
		s : 10 : "item_isbn1";
		s : 0 : "";
		s : 10 : "item_name1";
		s : 46 : "Sanitized";
		s : 14 : "receiver_email";
		s : 23 : "Sanitized";
		s : 11 : "payment_fee";
		s : 4 : "7.35";
		s : 9 : "quantity1";
		s : 1 : "1";
		s : 11 : "receiver_id";
		s : 13 : "Sanitized";
		s : 8 : "txn_type";
		s : 4 : "cart";
		s : 18 : "item_model_number1";
		s : 0 : "";
		s : 10 : "mc_gross_1";
		s : 6 : "243.18";
		s : 11 : "mc_currency";
		s : 3 : "USD";
		s : 13 : "item_taxable1";
		s : 1 : "N";
		s : 17 : "residence_country";
		s : 2 : "US";
		s : 19 : "transaction_subject";
		s : 59 : "Sanitized";
		s : 13 : "payment_gross";
		s : 6 : "243.18";
		s : 12 : "ipn_track_id";
		s : 13 : "Sanitized but matched";
		s : 8 : "order_id";
		s : 3 : "623";
	}
}
 
', 1349393058, 1349393058, NULL);
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rszrama’s picture

Version: 7.x-1.0-rc1 » 7.x-1.x-dev
Category: bug » support
Status: Active » Postponed (maintainer needs more info)

Honestly, I'm not sure how this can happen. Part of our IPN validation prior to actually creating any payment transaction is to ensure the IPN hasn't already been processed. The pertinent code is in commerce_paypal.module:

  // Exit if the IPN has already been processed.
  if (!empty($ipn['txn_id']) && $prior_ipn = commerce_paypal_ipn_load($ipn['txn_id'])) {
    if ($prior_ipn['payment_status'] == $ipn['payment_status']) {
      watchdog('commerce_paypal', 'Attempted to process an IPN that has already been processed with transaction ID @txn_id.', array('@txn_id' => $ipn['txn_id']), WATCHDOG_NOTICE);
      return FALSE;
    }
  }

Do you see that message in your log anywhere? Looking at the timestamps in your payment transaction data arrays, I can see that these transactions are being create a mere 15 seconds apart. The challenge will be to determine why - what can result in this happening without the above check not catching the problem?

Do you have any custom code running on this site at all? Anything else you can glean from the logs? Why not turn on IPN logging and look at how the IPN array is structured. Does it actually have a txn_id specified each time?

mattreba’s picture

Unfortunately this has not occurred since.

IPN logging is enabled. The txn_id of each payment is a match. Unfortunately by the time I discovered this payment my watchdog log had already rolled over so I cannot report on other log messages around the time of this occurring.

I have many contrib modules installed but nothing related to payments except the Authorize.net module. No custom modules.

I have one sandbox module (Commerce Quickbooks Webconnect) in use. It does implement hook_commerce_payment_transaction_insert/delete/update but it appears benign to me. http://drupalcode.org/sandbox/stephen.colson/1100862.git/blob/HEAD:/commerce_qb_webconnect.module#l440

I expect it is unrelated but I was also surprised to see PayPal refunds showing up in the payments tab. Refunds were executed on the PayPal website and not through any Commerce modules. Can you confirm this is expected behavior?

BrianLP’s picture

Also getting double entries. System loggin says this. It validates the order twice:

__________
commerce_paypal_wps 05.02.2013 - 21:21 IPN processed for Order 4353 with ID (.......). Guest (not confirmed)

commerce_paypal_wps 05.02.2013 - 21:21 IPN validated for Order 4353 with ID (.....). Guest (not confirmed)

Rules 05.02.2013 - 21:21 Unable to evaluate condition entity_has_field. Guest (not confirmed) edit configuration

Rules 05.02.2013 - 21:21 The variable or parameter entity is empty. Guest (not confirmed)

variable_email 05.02.2013 - 21:21 Successfully sent email to office@.......com Guest (not confirmed)

Rules 05.02.2013 - 21:21 Successfully sent email to office@......com Guest (not confirmed)

commerce_paypal_wps 05.02.2013 - 21:21 IPN validated for Order 4353 with ID (.....).
__________

mikgreen’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev
Category: Support request » Bug report
Status: Postponed (maintainer needs more info) » Needs review
FileSize
1.31 KB

The IPN message is not being saved, because there is a redirect before.
Since IPN message in not saved, whem the next message comes in (Paypal tries a few times if it it thinks it failed), there is not way to see if it's a dublicate.

The attached patch is for WPS. Maybe the same problem persists on other method.

3CWebDev’s picture

FileSize
21.74 KB
31.75 KB

@Ryan, I'm hoping you may be able to chime again with some more info. We're experiencing the exact same issue as the original poster.

A small percentage of checkouts using Paypal WPS produce the following issues:

  1. Double entries in the order payment tab -- although the actual Paypal charge only goes through once (see screenshot).
  2. commerce_checkout_complete() does not appear to be called and, therefore, the Rules dependent on "Completing the checkout process" never fire, resulting in no emails be sent, or the order status being changed properly.
  3. The order Revisions tab also shows the last entry as being from Anonymous instead of the customer and the status being Checkout: Complete(see screenshot). While orders without this issue show this entry as being from the customer account and then other Rules fire from the commerce_checkout_complete() function.

There are watchdog errors right after the commerce_paypal_wps IPN validated... log entry:

Location: SITE_URL/commerce_paypal/ipn/paypal_wps%7Ccommerce_payment_paypal_wps

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 'name': INSERT INTO {users} (uid, name, pass, mail, theme, signature, signature_format, created, access, login, status, timezone, language, picture, init, data) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9, :db_insert_placeholder_10, :db_insert_placeholder_11, :db_insert_placeholder_12, :db_insert_placeholder_13, :db_insert_placeholder_14, :db_insert_placeholder_15); Array ( [:db_insert_placeholder_0] => 25044 [:db_insert_placeholder_1] => [:db_insert_placeholder_2] => [:db_insert_placeholder_3] => [:db_insert_placeholder_4] => [:db_insert_placeholder_5] => [:db_insert_placeholder_6] => [:db_insert_placeholder_7] => 0 [:db_insert_placeholder_8] => 0 [:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10] => 0 [:db_insert_placeholder_11] => [:db_insert_placeholder_12] => [:db_insert_placeholder_13] => 0 [:db_insert_placeholder_14] => [:db_insert_placeholder_15] => a:1:{s:17:"mimemail_textonly";i:0;} ) in drupal_write_record() (line 7387 of /home/SITE/public_html/includes/common.inc).

This only happens to a small percantage of the orders but when it does it causes major issues, mainly because commerce_checkout_complete() is never called.

Any ideas on what may cause this? Or, is it possible to at least put in a safegaurd to make sure commerce_checkout_complete() is called?

mglaman’s picture

I wonder if this could also be tied to https://www.drupal.org/project/commerce_paypal/issues/2842938 since we're not loading previous IPNs via their txn_id

mglaman’s picture

Status: Needs review » Postponed (maintainer needs more info)

The patch in #4 will not solve the issue. The IPN is only "skipped" if it is missing a txn_id or has an invalid state.

If there is no txn_id, no steps are taken:

  // Do not perform any processing on WPS transactions here that do not have
  // transaction IDs, indicating they are non-payment IPNs such as those used
  // for subscription signup requests.
  if (empty($ipn['txn_id'])) {
    return FALSE;
  }

If it's an invalid step the order is kicked back a step

  // Exit when we don't get a payment status we recognize.
  if (!in_array($ipn['payment_status'], array('Failed', 'Voided', 'Pending', 'Completed', 'Refunded'))) {
    commerce_payment_redirect_pane_previous_page($order);
    return FALSE;
  }

RE: #5.

The order Revisions tab also shows the last entry as being from Anonymous instead of the customer and the status being Checkout: Complete(see screenshot).

That is because the IPN did its job and pushed the order through checkout. It calls commerce_payment_redirect_pane_next_page($order); at the end of its processing.

The following should have, then, been called:

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

Also, #5: your error is something trying to create a new user. That is not a bug from this module.

Anybody’s picture

Status: Postponed (maintainer needs more info) » Closed (duplicate)

Closing this as duplicate of #2036149: PayPal WPS not updating completing checkout to join forces, because I guess all these issues (see #2036149-33) are based on the same problem.

I think it's a race condition between IPN and UI!

If you guess I'm wrong and this issue is not a duplicate, please feel free to reopen. Otherwise please help to finally fix that issue! :)