View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0007388||module PayPal Checkout||module PayPal checkout - sub||public||2022-12-08 16:10||2023-07-24 17:48|
|Status||closed||Resolution||no change required|
|Product Version||2.2.2 / 1.2.2|
|Target Version||Fixed in Version|
|Summary||0007388: Idempotency issues at PayPal with Pay Upon Invoice (PUI) payments|
|Description||When a PUI payment is failing (e.g. the payment was declined by the processor), the order gets deleted in database and the user can try it again. If he tries to do so, all subsequent attempts for creating an order will also fail due to Idempotency issues because they all are using the same Order ID as the PayPal-Request-Id.|
See also: https://developer.paypal.com/api/rest/reference/idempotency/
I think this is caused because the order ID is stored in the session variable "sess_challenge" and is not destroyed after PUI payment fails. Therefore the same order ID will be reused. Normally this is fine, but PUI payments (and only those) are setting the PayPal-Request-Id and therefore are failing, because it is not allowed/supported to use the same Request-Id again (especially if the first request ran into a problem).
I don't know why the Request-Id is used for PUI payments only, but it is currently causing these problems. Is it a security feature for PUI payments or did you forgot to remove the Request-Id header after development, since it is used for PUI only? Is it safe to append the timestamp to the order ID in Payment::doExecutePuiPayment or removing the usage of the header completely as a workaround? The PayPal documentation states that the header is optional (see https://developer.paypal.com/api/rest/requests/#link-httprequestheaders).
|Steps To Reproduce||Trigger an error for PUI payments e.g. the processor declines the payment and try to execute another payment with PUI. You will notice the order ID stays the same and is used as Request-Id header in the order creation call.|
|Tags||No tags attached.|
||ready for review|
||Can you please explain the change a bit? According to the PayPal support, the recurring PayPal-Request-Id is the cause. But doesn't this change only have an effect on the PayPal-Client-Metadata-Id? The PayPal-Request-Id will stay the same anyway, because the Order ID remains the same. Or does the changed PayPal-Client-Metadata-Id have an effect on the idempotency behavior, even if the same PayPal-Request-Id is used in doExecutePuiPayment as $order->getId()?|
You can find the commit here:
||I was asking the question on base of this commit. ;) I don't understand why the Metadata-Id is getting reset, although the idempotency issues are bound to the Request-Id. Could you please explain that change?|
As already described in the previous answers, the behavior of PayPal is intentional:
The PayPal Fraud Detection provides that the customer must first carry out a successful OTHER payment method before they can start another attempt with PUI.
The PayPal fraud detection does not take into account that we completely deleted the PayPal session and also renewed the FraudID in an immediate second attempt.
Changing the email address certainly does not bring the desired effect.
Only the successful payment with an OTHER payment method solves the problem.
Therefore the ticket can be closed.