lat9 / paypalr

PayPal RESTful API Payment Module
GNU General Public License v2.0
0 stars 3 forks source link

Invalid cc used cannot then reuse paypal on the same login session #33

Closed brittainmark closed 1 month ago

brittainmark commented 2 months ago

I don't know it this is really a big issue but thought I would raise it for your consideration. If you put one of the testing codes in the first name of the credit card request on PayPal to cause it to fail. Then try to complete the order, you get the standard message 'We are unable to process your PayPal Checkout payment at this time. Please contact us for assistance.' and returned to step 2 of the payment process. If you then try to use PayPal again (without loging off) as the payment method, the invalid payment persists, and you are just repeatedly returned to step 2 with the same error message.

I don't know if the same would be true if you tried to pay with paypal. The only way out if you don't want to use a different paymant method is to log out and back in.

It does not matter if you are using final payment or authorise. The error message is slightly different. final payment for final payment. log file

The curlPost (v2/checkout/orders/2TC08765C63727256/capture) request was unsuccessful.
{
    "errNum": 422,
    "errMsg": "An interface error (422) was returned from PayPal.",
    "curlErrno": 0,
    "name": "UNPROCESSABLE_ENTITY",
    "message": "The requested action could not be performed, semantically incorrect, or failed business validation.",
    "details": [
        {
            "issue": "INSTRUMENT_DECLINED",
            "description": "The instrument presented  was either declined by the processor or bank, or it can't be used for this payment."
        }
    ],
    "debug_id": "f839260d5d476"
}
The curlPost (v2/checkout/orders/2TC08765C63727256/confirm-payment-source) request was unsuccessful.
{
    "errNum": 422,
    "errMsg": "An interface error (422) was returned from PayPal.",
    "curlErrno": 0,
    "name": "UNPROCESSABLE_ENTITY",
    "message": "The requested action could not be performed, semantically incorrect, or failed business validation.",
    "details": [
        {
            "issue": "ORDER_ALREADY_CAPTURED",
            "description": "Order already captured.If 'intent=CAPTURE' only one capture per order is allowed."
        }
    ],
    "debug_id": "f87634828c1cc"
}

for authorise only

The curlPost (v2/checkout/orders/50J097366P5314740/authorize) request was unsuccessful.
{
    "errNum": 422,
    "errMsg": "An interface error (422) was returned from PayPal.",
    "curlErrno": 0,
    "name": "UNPROCESSABLE_ENTITY",
    "message": "The requested action could not be performed, semantically incorrect, or failed business validation.",
    "details": [
        {
            "issue": "INSTRUMENT_DECLINED",
            "description": "The instrument presented  was either declined by the processor or bank, or it can't be used for this payment."
        }
    ],
    "debug_id": "f72838158d981"
}
The curlPost (v2/checkout/orders/50J097366P5314740/confirm-payment-source) request was unsuccessful.
{
    "errNum": 422,
    "errMsg": "An interface error (422) was returned from PayPal.",
    "curlErrno": 0,
    "name": "UNPROCESSABLE_ENTITY",
    "message": "The requested action could not be performed, semantically incorrect, or failed business validation.",
    "details": [
        {
            "issue": "ORDER_ALREADY_AUTHORIZED",
            "description": "Order already authorized.If 'intent=AUTHORIZE' only one authorization per order is allowed."
        }
    ],
    "debug_id": "f595039cdb623"
}

I am using 1.0.4, zc 2.0.1 php 8.3.9 I can send you the full log file if it helps. Interestingly the one log file holds both sets of transactions and the final successful transaction having logged out between each set.

lat9 commented 2 months ago

I'm unable to reproduce on the v1.0.4 branch. I'll note that one of the v1.0.3 changes corrected scenarios like this.

brittainmark commented 2 months ago

I'll double-check Thought I was using 1.0.4

brittainmark commented 2 months ago

Recopied all files and retested. Still failing. Process. 1) sign in as customer 2) add item to cart 3) go to checkout 4) select postage 5) select payment method paypal (tick terms and conditions) 6) when paypal screen displayed. select credit card 7) on credit card screen complete telephone number 8) change billing first name to "CCREJECT-IF" 9) add test credit card number, expire date and security number 10) complete cc screen 11) finish payment process in zen cart. Rejection message is presented and you are returned to step 2 12) select paypal as the payment option tick terms and conditions 13) click continue. You are returned to step to with the same error message as before.

logs as above

lat9 commented 2 months ago

Still not reproducible. I used the CCREJECT-IF with card number 4012 8888 8888 1881 (as indicated in the documentation). Received the insufficient-funds message. I then followed that up with the test-account's name and card 371449635398431, with which the order was successfully placed.

brittainmark commented 2 months ago

Interesting, I cannot even get to PayPal after the first failure and I do not get an insufficient funds message, (just the general we cannot process the payment) unless I log out and log back in. I'll do some more investigation, my end, to see if I can find out what is happening.

lat9 commented 2 months ago

What Zen Cart version and template? Noting that I've been validating on zc200/210 with both responsive_classic and bootstrap.

brittainmark commented 2 months ago

I am using zc 2.0.1 with a modified bootstrap. I'll strip my test down to just 2.0.1 and bootstrap and have another go tomorrow. I have a few extra modules also, big royal mail, SquarewebPay modified to work with php 8.3 and the latest square sdk, EuStandardBankTransfer, productLocation mod, Accout delete, Image handeler. and a bispoke mode to stop books being ordered with crystals. I'll retest on a basic install with bootstrap and see if it works for me then take it from there.

Any suggestions where to look would be appreciated.

brittainmark commented 2 months ago

Having a mare of a day. been at this most of today and cannot solve this issue with a base build, paypal restfull and bootstrap.

[17-Aug-2024 15:35:15 UTC] Request URI: /test/toasT-mZz-Coach/index.php?cmd=modules&set=payment, IP address: 127.0.0.1

--> PHP Fatal error: Uncaught Error: Class "currencies" not found in /home/lotus/public_html/innerlightcrystals/test/includes/modules/payment/paypalr.php:350
Stack trace:
#0 /home/lotus/public_html/innerlightcrystals/test/ADMIN/modules.php(173): paypalr->__construct()
#1 /home/lotus/public_html/innerlightcrystals/test/ADMIN/index.php(16): require('...')
#2 {main}
  thrown in /home/lotus/public_html/innerlightcrystals/test/includes/modules/payment/paypalr.php on line 350.

Currencies class does not seem to be loaded. was ok until i tried to enable paypal restful? Any ideas what i have screwed up?

lat9 commented 2 months ago

Separate issue. The admin doesn't autoload the currencies.php class and there's some wonkiness going on in the payment module's constructor.

Once I determine what the root cause is, I'll create an issue with the correction.

lat9 commented 2 months ago

Having a mare of a day. been at this most of today and cannot solve this issue with a base build, paypal restfull and bootstrap.

[17-Aug-2024 15:35:15 UTC] Request URI: /test/toasT-mZz-Coach/index.php?cmd=modules&set=payment, IP address: 127.0.0.1

--> PHP Fatal error: Uncaught Error: Class "currencies" not found in /home/lotus/public_html/innerlightcrystals/test/includes/modules/payment/paypalr.php:350
Stack trace:
#0 /home/lotus/public_html/innerlightcrystals/test/ADMIN/modules.php(173): paypalr->__construct()
#1 /home/lotus/public_html/innerlightcrystals/test/ADMIN/index.php(16): require('...')
#2 {main}
  thrown in /home/lotus/public_html/innerlightcrystals/test/includes/modules/payment/paypalr.php on line 350.

Currencies class does not seem to be loaded. was ok until i tried to enable paypal restful? Any ideas what i have screwed up?

I'm guessing that there was a PHP Notice or Warning log on/around the same time as this Fatal Error. Could you post that as well?

brittainmark commented 2 months ago

Now have a base build with just bootstrap unmodified and paypal restful still getting stuck in the loop. DO you have your full log from when it was successful for you. It might give me some pointers to see what is different with my processing. Have attached my log for you to see. paypalr-c-2-testes-20240818.log

With the error message not sure if the issue is that the id line 702"id": "7HJ587704T816332T", or the invoice id line 733 "invoice_id": "PPR-20240818085015-2-testes-192479c0", has not changed.

when i log out and back in both of these are changed and I get to paypal again.

line 1005 and 1033

"id": "9U911435G8109421G",
"invoice_id": "PPR-20240818091037-2-testes-721bd38b",
lat9 commented 2 months ago

There's the log from my successful attempt. I'm still trying to see the processing-order difference.

paypalr-c-7-JohDoe-20240818.log

brittainmark commented 2 months ago

My sequence was as soon as completed failed order returned to payment method step click paypal and click continue then just returned to choose payment method with same error. Looking at your log the Invoice_id has changed between your failure and the success. It did not on mine. Did you log out after failure as that works for me.

before "id": "6SX33624X71233514", "invoice_id": "PPR-20240818070030-7-JohDoe-4b541ca7", after fail "id": "6SX33624X71233514", 'invoice_id' => 'PPR-20240818070111-7-JohDoe-12add33b',

lat9 commented 2 months ago

You're running on the PayPal sandbox, right? Perhaps your issue is that you're not using one of the sandbox email addresses or account names.

P.S. I didn't log out between the insufficient-funds return and the successful (i.e. good card) entry.

brittainmark commented 2 months ago

No it is a sandbox email account but I am paying by credit card so the email does not matter.

I am using GBP instead of USD?

Where is the "invoice id" generated. I am wondering if that is the issue as it does not change between my attempts but does yours?

I believe you as the id has not changed? I was just hoping it was that.

brittainmark commented 2 months ago

I'm getting a bit closer. It is generating a new invoice_id, but then using the original id from the failed transaction?

lat9 commented 2 months ago

No it is a sandbox email account but I am paying by credit card so the email does not matter.

paypalr-c-1-AdaMer-20240818.log

FWIW, I received a similar error (see the log above) when my dog Ada attempted to pay via credit card with her name/email.

brittainmark commented 2 months ago

That was a red herring, the issue appears to be that the $invoice_guid has not changed. If I make it change then it processes correctly. I modified includes/modules/payment/paypal/PayPalRestful/Api/PayPalRestfulApi.php line 164 ... to write out to the log file

    public function setPayPalRequestId(string $request_id)
    {
        $this->paypalRequestId = $request_id;
        $this->log->write('==> Set PayPal Request ID = ' . $request_id, true);
    }

On my system the $request_id does not change it is set to $order_guid in /includes/modules/payment/paypalr.php line 1109

If I manually change the $order_guid the process goes to paypal again. So it appears that $order_guid is not being changed in the return to the payment selection screen.

Having done a bit more research it appears that the data used for the hash is always the same so the invoice_guid does not change and hence the transaction is rejected. Don't know where to go now. Maybe set $_SESSION['PayPalRestful']['CompletedOrders'] to some random number on failure.

lat9 commented 2 months ago

If you're paying via credit card, the GUID changes if the credit card changes. I'm just not sure what's different with your setup and mind.

brittainmark commented 2 months ago

ok i only get to paypal to select credit card once. After that I cannot get back to paypal as the card is not rejected until the confirm order phase. so I cannot enter a new credit card number at the paypal screen as i do not get there.

I'm off to bed now. If you are free tomorrow sometime I could skype you and show you what happens if that would help or I could try to make a video of what is happening and send you a link.

Thanks for your help so far.

lat9 commented 2 months ago

Sure, I'll be around.

lat9 commented 2 months ago

Before we talk tomorrow, please check that the billing address in use when you're testing is using the same country as that associated with your sandbox.

If I tried to place an order using an address in Guernsey, I received the 'PAYER_CANNOT_PAY' return code. Once I changed that address to one in the US, I was able to see an "Insufficient funds" message and the order went through after that once I provided a valid sandbox card.

brittainmark commented 2 months ago

I think i may know where we differ. My fault for not being clear. I do not sign in to paypal to pay is use the button below the login to pay with debit or credit card. image I have checked the paypal test account and it is registered to gb

lat9 commented 2 months ago

I don't sign in there either; I'm using the list of credit-cards to enter the card's credentials.

lat9 commented 2 months ago

If you look in one of your paypalr logs, you'll see something akin to:

2024-08-18 06:53:33: (checkout_process) ==> Start createOrder
TokenCache::get, using saved access-token; expires in 31344 seconds.
The curlPost (v2/checkout/orders) request was unsuccessful.
{
    "errNum": 422,
    "errMsg": "An interface error (422) was returned from PayPal.",
    "curlErrno": 0,
    "name": "UNPROCESSABLE_ENTITY",
    "message": "The requested action could not be performed, semantically incorrect, or failed business validation.",
    "details": [
        {
            "issue": "PAYER_CANNOT_PAY",
            "description": "Payer cannot pay for this transaction. Please contact the payer to find other ways to pay for this transaction."
        }
    ],
    "debug_id": "f652933b9af34"
}

Sign into your PayPal sandbox's Management Account (or whatever it's called). You can use that debug_id value to see what PayPal says the underlying issue is.

lat9 commented 2 months ago

P.S. Please note that the forthcoming v1.0.4, upon initial install, will wipe all of the paypalr-c-*.log files from August. You'll need to make copies of any that you want to keep prior to that upgrade.

lat9 commented 1 month ago

See #40 for corrections; closing this one.