Open ifnull opened 2 years ago
I saw someone else reported the same error on the WP forum about 2 weeks ago. I've also created a ticket on the Inpsyde website.
It looks like the issue may have something to do with the all_authorizations()
method. It looks like capture_authorization()
assumes the response from all_authorizations()
will contain at least one valid authorization. When it does not find at least one authorization, it fails silently.
I'm not sure why it would not be finding an authorization for only some orders. When we make a request to the https://api.paypal.com/v2/checkout/orders/:order_id
endpoint on the orders failing to capture in this way, we still see purchase_units
in the API response with payments->authorizations containing at least one authorization with a CREATED
status.
Example response from https://api.paypal.com/v2/checkout/orders/***
{
"id": "*********",
"intent": "AUTHORIZE",
"status": "COMPLETED",
"purchase_units":
[
{
"reference_id": "default",
"amount":
{
"currency_code": "USD",
"value": "32.58",
"breakdown":
{
"item_total":
{
"currency_code": "USD",
"value": "32.58"
},
"shipping":
{
"currency_code": "USD",
"value": "0.00"
},
"handling":
{
"currency_code": "USD",
"value": "0.00"
},
"insurance":
{
"currency_code": "USD",
"value": "0.00"
},
"shipping_discount":
{
"currency_code": "USD",
"value": "0.00"
}
}
},
"payee":
{
"email_address": ""*********",
"merchant_id": ""*********"
},
"custom_id": ""*********",
"invoice_id": "WC-"*********",
"soft_descriptor": "PAYPAL *"*********",
"shipping":
{
"name":
{
"full_name": ""*********"
}
},
"payments":
{
"authorizations":
[
{
"status": "CREATED",
"id": ""*********",
"amount":
{
"currency_code": "USD",
"value": "32.58"
},
"invoice_id": "WC-"*********",
"custom_id": ""*********",
"seller_protection":
{
"status": "ELIGIBLE",
"dispute_categories":
[
"ITEM_NOT_RECEIVED",
"UNAUTHORIZED_TRANSACTION"
]
},
"expiration_time": "2022-06-21T20:20:24Z",
"links":
[
{
"href": "https://api.paypal.com/v2/payments/authorizations/"*********",
"rel": "self",
"method": "GET"
},
{
"href": "https://api.paypal.com/v2/payments/authorizations/"*********/capture",
"rel": "capture",
"method": "POST"
},
{
"href": "https://api.paypal.com/v2/payments/authorizations/"*********/void",
"rel": "void",
"method": "POST"
},
{
"href": "https://api.paypal.com/v2/payments/authorizations/"*********/reauthorize",
"rel": "reauthorize",
"method": "POST"
},
{
"href": "https://api.paypal.com/v2/checkout/orders/"*********",
"rel": "up",
"method": "GET"
}
],
"create_time": "2022-05-23T20:20:24Z",
"update_time": "2022-05-23T20:20:24Z"
}
]
}
}
],
"payer":
{
"name":
{
"given_name": ""*********",
"surname": ""*********"
},
"email_address": ""*********",
"payer_id": ""*********",
"phone":
{
"phone_number":
{
"national_number": ""*********"
}
},
"address":
{}
},
"update_time": "2022-05-23T20:20:24Z",
"links":
[
{
"href": "https://api.paypal.com/v2/checkout/orders/"*********",
"rel": "self",
"method": "GET"
}
]
}
@InpsydeNiklas Do you need any more info?
All we can say is that the behavior seems to have been introduced by a change at PayPal as reports about it started coming in across several plugin versions at the same time. We haven't been able to reproduce it yet internally but have brought this up with PayPal. We haven't heard back yet though. We appreciate the detailed report in any case and will provide an update when we know more.
I'm having the same issue with WooCommerce 6.5.1 on WP 5.9.3 with WooCommerce PayPal Payments 1.8.0. The debug logs look like everything is successful, but we get the error message "Could not retrieve information. Try again later." when we try to do the capture, and it doesn't capture, on multiple different orders.
Hello @ifnull @lmds
It seems that there is a problem getting the PayPal order from WC order here: https://github.com/woocommerce/woocommerce-paypal-payments/blob/trunk/modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php#L137
When the exception is thrown it returns self::INACCESSIBLE
which is then used to display the error message here: https://github.com/woocommerce/woocommerce-paypal-payments/blob/trunk/modules/ppcp-wc-gateway/src/Notice/AuthorizeOrderActionNotice.php#L49-L55
As we are not currently able to reproduce it will be great if you can add this line:
$this->logger->error( 'Could not get PayPal order from WC order: ' . $exception->getMessage() );
here after line 133: https://github.com/woocommerce/woocommerce-paypal-payments/commit/6c36843069644699e4eafc51c4b4335310493524
I´m attaching the package here in case you can not add the above line manually: woocommerce-paypal-payments.zip
So after adding the above line it should display the concrete error message, will be great if you can let us know here what error message it does contains after "Could not get PayPal order from WC order:" entry log.
Thanks in advance.
@Dinamiko We had to disable the plugin and all uncaptured payments were manually captured in the Paypal portal. Unfortunately, I do not have a way to test the change you suggested. If Paypal had returned anything other than a 200 response code, it would have been written to the log. Since we don't see that in the log, I think there may be an issue with parsing the response from Paypal. Is there an easy way to use the example order JSON I provided and pass it to $this->order_factory->from_paypal_response( $json );
to get the exception we need?
@lmds I went able to reproduce by passing the json to the order factory as you suggested, it throws exception because 'No country given for address.' from here: https://github.com/woocommerce/woocommerce-paypal-payments/blob/trunk/modules/ppcp-api-client/src/Factory/AddressFactory.php#L72-L76
We had the same issue recently in refunds: https://github.com/woocommerce/woocommerce-paypal-payments/issues/639 and we fixed it by not throwing exception but just adding an empty string when creating the Address
: https://github.com/woocommerce/woocommerce-paypal-payments/pull/672/files
The above fix will be included in the upcoming release, in the meantime I´m adding the package in case anyone wants to give it a try: woocommerce-paypal-payments.zip
@Dinamiko We will plan to include this fix in our next release. I think it would be good to include https://github.com/woocommerce/woocommerce-paypal-payments/commit/6c36843069644699e4eafc51c4b4335310493524 in the next release too. This would be helpful if we need to debug any other factory's from_paypal_response()
method.
@Dinamiko I took another look and found another issue with the conditional to check if shipping is needed. I think the issue for us is PurchaseUnitFactory's shipping_needed()
method which uses $item->category() !== Item::DIGITAL_GOODS
to identify if shipping is needed. Since we have physical goods with an in-store pickup fulfillment option this check is failing. We use WC()->cart->needs_shipping()
during the purchase process (see below) which works great. However, I do not think there is a similar method for WC Orders that we could use here. It would be great if there was a way for us to hook into your shipping_needed()
method to overwrite it and check our custom fulfillment method to determine if shipping is needed.
use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext;
add_filter( 'ppcp_request_args', array($this,'hide_ship_to_in_paypal_popup'), 11, 2);
public function hide_ship_to_in_paypal_popup(array $args, string $url): array {
if ( ! isset( $args['body'] ) ) {
return $args;
}
if ( ! is_null( WC()->cart ) && WC()->cart->needs_shipping() ) {
return $args;
}
$args_body_obj = json_decode( $args['body'] );
// If we have shipping_preference, let's set the value here. Otherwise, do nothing.
if ( isset( $args_body_obj->application_context ) && isset( $args_body_obj->application_context->shipping_preference ) ) {
$args_body_obj->application_context->shipping_preference = ApplicationContext::SHIPPING_PREFERENCE_NO_SHIPPING;
$args['body'] = json_encode( $args_body_obj );
}
return $args;
}
@Dinamiko Any word on when we can expect an official release with https://github.com/woocommerce/woocommerce-paypal-payments/pull/672 ?
A new release is expected in the coming days but a pre-release is available from here already: https://github.com/woocommerce/woocommerce-paypal-payments/releases Please give it a try and let us know how that works. Thanks!
Describe the Bug
We are running v1.7.0. We have noticed that sometime in early May some of our payments stopped capturing. Yesterday roughly 20% of payments failed to capture. Selecting the "Capture authorized PayPal payment" order actions returns
Could not retrieve information. Try again later
. The order gets marked as "Paid" but also marked as "Not captured". The debug log does not show an error or even an attempt to capture when this error is shown. I see that it makes a request toDEBUG /v2/checkout/orders/:order_id
but for the orders that are failing to capture, I never see a request to capture (e.g.POST /v2/checkout/orders/:order_id/capture
).To Reproduce
Expected Behavior
The request is made to Paypal to capture the payment and the payment is captured.
Actual Behavior
No request is made to Paypal. Payment remains in Pending status in Paypal.
Environment