From e1e00943988cbd5d58bcaf255ac85cc780de7c06 Mon Sep 17 00:00:00 2001 From: Kyrylo Date: Fri, 8 Aug 2025 18:31:58 +0300 Subject: [PATCH 1/2] Add filter for shipping preference --- .../src/Factory/ShippingPreferenceFactory.php | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/modules/ppcp-api-client/src/Factory/ShippingPreferenceFactory.php b/modules/ppcp-api-client/src/Factory/ShippingPreferenceFactory.php index 3c3cee0df..4ecd16e1c 100644 --- a/modules/ppcp-api-client/src/Factory/ShippingPreferenceFactory.php +++ b/modules/ppcp-api-client/src/Factory/ShippingPreferenceFactory.php @@ -33,6 +33,29 @@ public function from_state( ?WC_Cart $cart = null, string $funding_source = '' ): string { + /** + * If you are using this filter to set 'NO_SHIPPING', you may also want to disable sending + * shipping fields completely. + * + * @see PurchaseUnitFactory::shipping_needed() for + * the woocommerce_paypal_payments_shipping_needed filter. + * + * @see ExperienceContext for SHIPPING_PREFERENCE_* constants. + * @see https://developer.paypal.com/serversdk/php/models/enumerations/shipping-preference/ + */ + $shipping_preference = apply_filters( + 'woocommerce_paypal_payments_shipping_preference', + null, + $purchase_unit, + $context, + $cart, + $funding_source + ); + + if ( is_string( $shipping_preference ) ) { + return $shipping_preference; + } + $contains_physical_goods = $purchase_unit->contains_physical_goods(); if ( ! $contains_physical_goods ) { return ExperienceContext::SHIPPING_PREFERENCE_NO_SHIPPING; From 68c82a831db42bbf28f40365f2c47b1ac0cc6e55 Mon Sep 17 00:00:00 2001 From: Kyrylo Date: Fri, 8 Aug 2025 18:34:27 +0300 Subject: [PATCH 2/2] Add filter for shipping_needed --- .../src/Factory/PurchaseUnitFactory.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/modules/ppcp-api-client/src/Factory/PurchaseUnitFactory.php b/modules/ppcp-api-client/src/Factory/PurchaseUnitFactory.php index e0be1954d..828c1bac6 100644 --- a/modules/ppcp-api-client/src/Factory/PurchaseUnitFactory.php +++ b/modules/ppcp-api-client/src/Factory/PurchaseUnitFactory.php @@ -289,6 +289,23 @@ function ( \stdClass $item ): Item { */ private function shipping_needed( Item ...$items ): bool { + /** + * If you are returning false from this filter, do not forget to also set + * shipping_preference to 'NO_SHIPPING', otherwise PayPal will return an error. + * + * @see ShippingPreferenceFactory::from_state() for + * the 'woocommerce_paypal_payments_shipping_preference' filter. + */ + $shipping_needed = apply_filters( + 'woocommerce_paypal_payments_shipping_needed', + null, + $items + ); + + if ( is_bool( $shipping_needed ) ) { + return $shipping_needed; + } + foreach ( $items as $item ) { if ( $item->category() !== Item::DIGITAL_GOODS ) { return true;