Forum

Thread tagged as: Problem, Shop

Shop Double Charging

Hi,

I have an issue with orders going through twice on a site with Perch Shop implemented (Paypal Express).

It only happens on some orders, and when it does happen the Perch admin has two separate invoices, generated about 2-3 minutes apart. From what I know, the issue is that the customer tries to checkout, says it doesn't work, and then tries again and it goes through (Obviously going through the first time.).

Below I'll show the code to the entire shop process, please let me know if you see anything that I'm doing incorrectly:

The 'Checkout' button on the cart page sends them to the login page.

Login page:

If logged in sends them to /checkout.php

<?php include('perch/runtime.php'); ?>
<?php
  if (perch_member_logged_in()) {
    PerchSystem::redirect('/checkout.php');
  } 
?>

Otherwise displays login/register forms

Checkout page:

<?php
if (perch_member_logged_in()) {
  // your 'success' return URL
  $return_url = 'https://specialtymotorcams.com/success.php';
  $cancel_url = 'https://specialtymotorcams.com/cancel.php';

  perch_shop_checkout('paypal-express', [
    'return_url' => $return_url,
    'cancel_url' => $cancel_url,
  ]);
} 
?>

Success.php page ($return_url):

(This used to be my $cancel_url as well, I thought that the if(perch_shop_order_successful()) would be enough to determine if payment was successful. After the first double charge, I changed the cancel_url to cancel.php to try and fix this issue. This did not fix the issue.)

runtime included
...html...

<?php
  perch_shop_complete_payment('paypal-express');

  if (perch_shop_order_successful()) {
        perch_shop_empty_cart();
        perch_content('Success');
    }else{
      perch_content('Not Successful');
    }
?>

...html...

cancel.php page ($cancel_url):

runtime
...html...

<?php
      perch_content('Not Successful');
?>

..html..

Shop.php config file:

<?php
  return [
    'gateways' => [
      'paypal-express' => [
        'enabled'   => true,
        'test_mode' => false,
        'live' => [
          'username'  => '***************',
          'password'  => '***************',
          'signature' => '***************',
        ],
        'test' => [
          'username'  => '***************',
          'password'  => '***************',
          'signature' => '***************',
        ],
      ],
    ],
  ];
?>

Aaand diagnostics:

Perch: 3.0.12, PHP: 5.4.24, MySQL: mysqlnd 5.0.10 - 20111026 - $Id: 2d8f599f49e5e8d2f5ba7112b5c444b3e2e48cdf $, with PDO
Server OS: WINNT, cgi-fcgi
Installed apps: content (3.0.12), assets (3.0.12), categories (3.0.12), perch_shop_orders (1.2.5), perch_shop_products (1.2.5), perch_shop (1.2.5), perch_members (1.6.2)
App runtimes: <?php $apps_list = [ 'perch_members', 'perch_shop' ];
PERCH_LOGINPATH: /perch
PERCH_PATH: C:\inetpub\wwwroot\Motorcam-live\perch
PERCH_CORE: C:\inetpub\wwwroot\Motorcam-live\perch\core
PERCH_RESFILEPATH: C:\inetpub\wwwroot\Motorcam-live\perch\resources
Image manipulation: GD
PHP limits: Max upload 4096M, Max POST 1024M, Memory: 1024M, Total max file upload: 1024M
F1: 3b606135b33e6a102526838f4152a807
Resource folder writeable: Yes
SCRIPT_NAME: /perch/core/settings/diagnostics/index.php
REQUEST_URI: /perch/core/settings/diagnostics/
DOCUMENT_ROOT: C:\inetpub\wwwroot\Motorcam-live
HTTP_HOST: specialtymotorcams.com

Any help is appreciated, as this is a pretty serious issue. Thanks!!

Jared Dutra

Jared Dutra 0 points

  • 3 years ago
Drew McLellan

Drew McLellan 2638 points
Perch Support

Have you been able to reproduce the situation, or log evidence of it happening?

Thank you for your quick response. I'm currently setting up a separate environment to try and reproduce this, but no I haven't. All I have so far is identical orders a couple mins apart and the customers word. I thought I'd post to forums first.

Unfortunately I can't reproduce the issue. Even trying to go into history to refresh the paypal order is prevented by paypal. I'm not sure how they could have a completed payment but still get sent to the 'unsuccessful' screen.

Does perch_shop_order_successful() rely on perch_shop_complete_payment('paypal-express'); to determine if it's successful?

If not I could try putting perch_shop_complete_payment('paypal-express'); after

if (perch_shop_order_successful()) {
        perch_shop_empty_cart();
        perch_content('Success');
    }else{
      perch_content('Not Successful');
}

and instead of the perch_content('Not Successful') I could redirect them to the $cancel_url ? I'm open to any suggestions

Drew McLellan

Drew McLellan 2638 points
Perch Support

Does perch_shop_order_successful() rely on perch_shop_complete_payment('paypal-express'); to determine if it's successful?

Yes, perch_shop_complete_payment() completes the payment, and is absolutely essential.

After speaking with PayPal, it's been determined that the duplicate payments still redirect to 'success.php' (return_url) both times, but the first time around it calls perch_content('Not Successful'); . I'm still working with them to determine if it's Paypal sending the wrong token, which throws perch_shop_order_successful() off, or if Perch is catching the token wrong?

So now I know that the payment is completed both times, but the first time is displaying the wrong message to the user, which makes them think their payment didn't go through.

I don't think this would be the right thing to do, but couldn't I just change the perch_content('Not Successful'); to perch_content('Successful'); because if the payment wasn't successful, they'd be sent to the cancel_url anyways? (I didn't look at the conditions between cancel url's and return url's so I'm not sure if this is true)

Hussein Al Hammad

Hussein Al Hammad 105 points
Registered Developer

Drew would be able to confirm this: you may need to use perch_shop_complete_payment('paypal-express') before outputting any HTML.

Hussein, thank you for the advice. I put this change in place in hopes that it will solve the issue.

Drew, is there anything else I can do to ensure this will not happen again? It looks like it's coming down to that particular function perch_shop_complete_payment('paypal-express').

I have other sites I'm developing with Perch Shop and need to assure our clients that this won't happen again.

Hussein Al Hammad

Hussein Al Hammad 105 points
Registered Developer

From how you described the problem, it seems to me:

(1) perch_shop_order_successful() is returning false on the customer's first attempt even though the payment was successful and an order has been created.

Given an order is created from the customer's first attempt (they don't know), perch_shop_complete_payment('paypal-express') works fine, but perch_shop_order_successful() is returning false instead of true.

When it returns false, you're handling this case by displaying a failure message.

(2) The customer sees the failure message and sees they still have the items in cart. They attempt to pay again. This time, however, perch_shop_order_successful() returns true and as a result they see the success message and the cart is emptied.

At this stage it could be that perch_shop_order_successful() is actually returning true in reference to the first successful order in (1).


My suggestion is to use perch_shop_order_successful() and perch_shop_complete_payment('paypal-express') before outputting any HTML. For example:

<?php
// runtime included
perch_shop_complete_payment('paypal-express');

if (perch_shop_order_successful()) {
    perch_shop_empty_cart();
    $message = perch_content('Success', true);
}else{
    $message = perch_content('Not Successful');
}
?>

<!-- HTML output starts here -->

<?php echo $message; ?>

<!-- more HTML -->

Hussein, thanks for your suggestion.

I'll mark this as the solution for now, as of course I'm not able to test this on the issue without being able to reproduce the issue in the first place.

Thank you.