Intermittent Duplicate Payments

Created on 8 August 2018, almost 7 years ago
Updated 7 November 2024, 6 months ago

I have been receiving reports of duplicate payments going through with Braintree Hosted Fields.

I have been unable to recreate the issue locally. However, the issue is intermittent so I am trying to source what might be causing the issue.

Looking into the data we have multiple orders that have more than one payment:
These payments are usually made within 5 seconds of each other, all for the exact same amount.
The only thing that differs between payment is the remote ID.

Response from Braintree:

Taking a look at these transactions, it looks as though they were submitted to Braintree at separate requests. Although your gateway is currently set to reject duplicate transactions submitted within 30 seconds of one another, these transactions were passed with unique order IDs, meaning our system saw them as separate transactions.

This confuses me somewhat as if they were made with unique order IDs how are they being attached to the same order when we track the payment?

πŸ› Bug report
Status

Needs work

Version

1.0

Component

Code

Created by

πŸ‡¬πŸ‡§United Kingdom jafacakes2011

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

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States andyg5000 North Carolina, USA

    We're still having this issue with multiple submits (see logs below)

    I'm going forward with a patch to disable the submit button when the form is submitted (attached) and will report back if we're still experiencing this.

    xxx.xxx.xxx - - [01/Nov/2024:20:43:11 +0000] "POST /checkout/21117/review HTTP/1.1" 303 422 "https://site.net/checkout/21117/review" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0"
    xxx.xxx.xxx - - [01/Nov/2024:20:43:15 +0000] "GET /checkout/21117/payment HTTP/1.1" 302 342 "https://site.net/checkout/21117/review" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0"
    xxx.xxx.xxx - - [01/Nov/2024:20:43:16 +0000] "POST /checkout/21117/review HTTP/1.1" 303 422 "https://site.net/checkout/21117/review" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0"
    xxx.xxx.xxx - - [01/Nov/2024:20:43:18 +0000] "GET /checkout/21117/payment HTTP/1.1" 302 342 "https://site.net/checkout/21117/review" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0"
    xxx.xxx.xxx - - [01/Nov/2024:20:43:19 +0000] "POST /checkout/21117/review HTTP/1.1" 303 422 "https://site.net/checkout/21117/review" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0"
    xxx.xxx.xxx - - [01/Nov/2024:20:43:21 +0000] "GET /checkout/21117/payment HTTP/1.1" 302 342 "https://site.net/checkout/21117/review" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0"
    xxx.xxx.xxx - - [01/Nov/2024:20:43:21 +0000] "GET /checkout/21117/complete HTTP/1.1" 200 81607 "https://site.net/checkout/21117/review" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0"
    
  • πŸ‡¬πŸ‡§United Kingdom chrisscrumping

    I am getting these as well - I have duplicate payments detection in Braintree turned on but need to remove the timestamp from the order ID for this to work.

    I also have the patch in #15 applied.

    Will try dig out some logs and gather some more info when I have time.

  • πŸ‡ΊπŸ‡ΈUnited States DamienMcKenna NH, USA
  • πŸ‡¬πŸ‡§United Kingdom farse

    I have applied both patches #11 and #15 and a few issues still.
    I am only using the credit card version so this just applies to that.

    The submit button is disabled but only one on pane. The pane where the data gets submitted (on my 'Review and Pay') if I submit the button multiple times it was creating multiple transactions. Although now with patch #11 it only creates one transaction, the order is forever in an error state so the order does not get completed.

    I have gotten around this by the following. It's probably not patch worthy hence why I am putting it here.

    My code starts with "// If it's a duplicate, we need to complete the order or else it's a completed order that is stuck."

    I have tested this and it works pretty well. It captures the payment with the 'duplicate' state and the remote id and when I then check in braintree I can see that transaction as a duplcate as well. And the payment completes without any worry to the user.

    This is in createPayment() in HostedFields.php

       catch (\Throwable $e) {
          // If this was a 3ds payment and a payment failure occurs,
          // we cannot reuse the nonce.
          // Reinstate the original payment method.
          if ($order = $payment->getOrder()) {
            if ($original_payment_method_id = $order->getData('3ds2_original_payment_method')) {
              $payment_method_storage = $this->entityTypeManager->getStorage('commerce_payment_method');
              if ($original_payment_method = $payment_method_storage->load($original_payment_method_id)) {
                $order->set('payment_method', $original_payment_method);
              }
              $order->unsetData('3ds2_original_payment_method');
              $order->save();
            }
          }
          // If it's a duplicate, we need to complete the order or else it's a completed order that is stuck.
          if ($e->getMessage() == 'Rejected by the gateway. Reason: duplicate') {
            $payment->setState('Duplicate');
            $payment->setAmount(new Price('0', 'USD'));
            $payment->setRemoteId($result->transaction->id);
            $payment->save();
            return;
          }
          else {
            throw $e;
          }
        }
    
        $next_state = $capture ? 'completed' : 'authorization';
        $payment->setState($next_state);
        $payment->setRemoteId($result->transaction->id);
        // @todo Find out how long an authorization is valid, set its expiration.
        $payment->save();
  • πŸ‡¬πŸ‡§United Kingdom farse

    I seemed to only partially solve my issue in https://www.drupal.org/project/commerce_braintree/issues/2991341#comment... πŸ› Intermittent Duplicate Payments Needs work

    For some reason the paymentprocess pane is only sometimes being called. twice. When I am running xdebug to see what is happening it seems to always work. Then it completely worked for half a day and now it's doing duplicates again consistently. I realised this is a bigger problem because it is running through the checkout complete twice and therefore sending emails twice.

    I am on commerce '8.x-2.40' so not sure if it's something to do with that.

Production build 0.71.5 2024