View Issue Details

IDProjectCategoryView StatusLast Update
0007388module PayPal Checkoutmodule PayPal checkout - subpublic2023-07-24 17:48
Reporterdominik_ziegler Assigned To 
PrioritynormalSeveritymajorReproducibilityalways
Status closedResolutionno change required 
Product Version2.2.2 / 1.2.2 
Summary0007388: Idempotency issues at PayPal with Pay Upon Invoice (PUI) payments
DescriptionWhen 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 ReproduceTrigger 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.
TagsNo tags attached.

Activities

[email protected]

2022-12-13 18:26

manager   ~0014950

ready for review

dominik_ziegler

2023-01-11 10:38

reporter   ~0014974

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()?

QA

2023-01-11 16:14

administrator   ~0014976

You can find the commit here:
https://github.com/OXID-eSales/paypal-module/commit/5bf2e2e3d9c18c2b0fc2a9b73e9ae85f4f52ebf0

-MF

dominik_ziegler

2023-01-16 09:31

reporter   ~0014979

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?

mario_lorenz

2023-05-30 16:13

developer   ~0015188

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.