Fixed PayPal NEW error with user upgrades.

You’re not the only person experiencing it so I wouldn’t assume it’s a bug. I haven’t looked into it yet though.

For now I recommend using the Legacy handler for PayPal.
 
You’re not the only person experiencing it so I wouldn’t assume it’s a bug. I haven’t looked into it yet though.

For now I recommend using the Legacy handler for PayPal.

If this info helps you, I think the issue has something to do with PayPal's subscription panel, and subscription plans. (Under Sales tab).

I have several inactive subscription offers in there, and whenever someone tries to subscribe via XF's PayPal rest, it defaults to one of the inactive subscriptions, regardless what User Upgrade the XF user selects.


1727296974239.webp
 
ask paypal if webhook supports sending permission via api which contains recurring payment or what is called?
if XF works on PayPal legacy, means payment_callback.php handles & solves fine

Billing subscription
Subscription webhooks
 
Last edited:
This seems to be one of those things that is not possible to test on a test installation, as it is the different URL seems to trigger errors from PayPal.

But it does seem to be a bit of a showstopper type bug
 
Thank you for reporting this issue, it has now been resolved. We are aiming to include any changes that have been made in a future XF release (2.3.4).

Change log:
Ensure PayPal products are created with a unique ID.
There may be a delay before changes are rolled out to the XenForo Community.
 
I drew some conclusions as to what I thought the issue was and it turns out that, while that was a bug, it was not the bug you were running into.

You can patch this yourself.

You will need to open the file: src/XF/Payment/PayPalRest.php

Find:

PHP:
        $planDetails = $this->makePayPalRequest('get', 'v1/billing/plans', [
            'json' => [

And change to:

PHP:
        $planDetails = $this->makePayPalRequest('get', 'v1/billing/plans', [
            'query' => [

(Change this one line to read query instead of json).


in the same file, we are also changing this line:

PHP:
            'name' => substr($purchase->title, 0, 127),

To:

PHP:
            'name' => substr($purchase->purchasableTitle, 0, 127),
 
I drew some conclusions as to what I thought the issue was and it turns out that, while that was a bug, it was not the bug you were running into.

You can patch this yourself.

You will need to open the file: src/XF/Payment/PayPalRest.php

Find:

PHP:
        $planDetails = $this->makePayPalRequest('get', 'v1/billing/plans', [
            'json' => [

And change to:

PHP:
        $planDetails = $this->makePayPalRequest('get', 'v1/billing/plans', [
            'query' => [

(Change this one line to read query instead of json).


in the same file, we are also changing this line:

PHP:
            'name' => substr($purchase->title, 0, 127),

To:

PHP:
            'name' => substr($purchase->purchasableTitle, 0, 127),
Good,
But there is still the problem that user subscriptions are digital goods and in paypal it appears as a physical product to be sent. So it appears the physical address of the user and this brings problems of disputes with ill-intentioned users.

On the other hand, in the PayPal email the user account does not appear in the title of the subscription, with the legacy api it does.

Both of the above mentioned things work correctly with the legacy api.
Maybe an option should be added in xenforo to mark the product as digital or physical.
 
This is how we create the PayPal products:

PHP:
$productDetails = $this->makePayPalRequest('post', 'v1/catalogs/products', [
    'json' => [
        'id' => $productId,
        'name' => $purchase->title,
        'type' => 'DIGITAL',
        'category' => 'MISCELLANEOUS_GENERAL_SERVICES',
    ],
], $accessToken, $errors);
 
This is how we create the PayPal products:

PHP:
$productDetails = $this->makePayPalRequest('post', 'v1/catalogs/products', [
    'json' => [
        'id' => $productId,
        'name' => $purchase->title,
        'type' => 'DIGITAL',
        'category' => 'MISCELLANEOUS_GENERAL_SERVICES',
    ],
], $accessToken, $errors);
is there any function for the api to indicate that it is a product that does not require shipping ?

Thanks for fast reply
 





o resolve the issue, please follow the below detailed steps & instructions based on your website integration.



1. For REST API integration : You can pass value "NO_SHIPPING" to disable shipping address during checkout.



For digital goods, the payment API request call should be correct value under "Shipping_Preference" field.

shipping_preference :​

  • GET_FROM_FILE. Get the customer-provided shipping address on the PayPal site.
  • NO_SHIPPING. Redacts the shipping address from the PayPal site. Recommended for digital goods.
  • SET_PROVIDED_ADDRESS. Get the merchant-provided address. The customer cannot change this address on the PayPal site. If merchant does not pass an address, customer can choose the address on PayPal pages.
Default: GET_FROM_FILE.



Guide link - https://developer.paypal.com/docs/api/orders/v2/#definition-application_context



2. For NVP API integration, pass the "no_shipping" as "1" in your SetExpressCheckoutRequest API call to disable shipping address during checkout.



NOSHIPPING : Determines whether PayPal displays shipping address fields on the PayPal pages. For digital goods, this field is required, and you must set it to 1.

Value is:
• 0 — PayPal displays the shipping address on the PayPal pages. But do not require one.
1 — PayPal does not display shipping address fields and removes shipping information from the transaction.
• 2 — If you do not pass the shipping address, PayPal obtains it from the buyer's account profile. require one.

Guide link - https://developer.paypal.com/docs/classic/api/merchant/SetExpressCheckout-API-Operation-NVP/



3. For "PayPal Payments Standard" legacy button integration, pass the "no_shipping" as "1" to disable shipping address during checkout.
 
I drew some conclusions as to what I thought the issue was and it turns out that, while that was a bug, it was not the bug you were running into.

You can patch this yourself.

You will need to open the file: src/XF/Payment/PayPalRest.php

Find:

PHP:
        $planDetails = $this->makePayPalRequest('get', 'v1/billing/plans', [
            'json' => [

And change to:

PHP:
        $planDetails = $this->makePayPalRequest('get', 'v1/billing/plans', [
            'query' => [

(Change this one line to read query instead of json).


in the same file, we are also changing this line:

PHP:
            'name' => substr($purchase->title, 0, 127),

To:

PHP:
            'name' => substr($purchase->purchasableTitle, 0, 127),

You can find the code on line 275:

PHP:
        $planDetails = $this->makePayPalRequest('get', 'v1/billing/plans', [
            'json' => [

And on line 290:
PHP:
            'name' => substr($purchase->title, 0, 127),

Of course, after doing so you will fail the file health check:

1737739844831.webp
 
How to stop PayPal asking for Shipping Address

You can change the setting in your XenForo code. Specifically, look at this part of your XenForo PayPal payment provider: src/XF/Payment/PayPal.php

PayPal.php on line 109 : 'no_shipping' => !empty($paymentProfile->options['require_address']) ? 2 : 1,

This line controls whether PayPal asks for a shipping address:
  • 2: Address is required.
  • 1: Address is not required.
  • 0: Address is optional.

Solution:​

If you don’t need the address at all, change this line to: 'no_shipping' => 1,

Or, if you want to allow but not require the address, use: 'no_shipping' => 0,

This should stop PayPal from requesting the user's shipping address when they check out.

UPDATE: @Chris D - This does not seem to work, where would Xenforo be hardcoding 'no_shipping' = 2 into the request? Or is it just skipping the 'no_shipping' parameter all together?
 
Last edited:
How to stop PayPal asking for Shipping Address

You can change the setting in your XenForo code. Specifically, look at this part of your XenForo PayPal payment provider: src/XF/Payment/PayPal.php

PayPal.php on line 109 : 'no_shipping' => !empty($paymentProfile->options['require_address']) ? 2 : 1,

This line controls whether PayPal asks for a shipping address:
  • 2: Address is required.
  • 1: Address is not required.
  • 0: Address is optional.

Solution:​

If you don’t need the address at all, change this line to: 'no_shipping' => 1,

Or, if you want to allow but not require the address, use: 'no_shipping' => 0,

This should stop PayPal from requesting the user's shipping address when they check out.

UPDATE: This still does not seem to work, I suspect Xenforo is hardcoding 2 into the request.
These kinds of things should be fully integrated from a tick to mark in the administration control panel.
Just like Stripe Tax should be.

In something as important as payment gateways, xenforo has just what is necessary so that it cannot be said that it does not have payment gateways. :(
 
@est3ban129 , best option is to go back to Paypal Legacy.

With the changes described by Chris in this post, PayPal REST works fine, but the red warning still shows up in the admin panel.
However, I switched to Stripe, and I’ve also had issues with it.

As I mentioned earlier, I think the payment gateways need more polishing. They are the entry point for revenue for forum admins, and they are not well-maintained.
 
Back
Top Bottom