@@ -191,11 +191,7 @@ function ( Item $item ): bool {
191191 if ( $ this ->shipping_needed ( ...array_values ( $ items ) ) && $ customer instanceof \WC_Customer ) {
192192 $ shipping = $ this ->shipping_factory ->from_wc_customer ( \WC ()->customer , $ with_shipping_options );
193193 $ shipping_address = $ shipping ->address ();
194- if (
195- ! $ shipping_address ||
196- 2 !== strlen ( $ shipping_address ->country_code () ) ||
197- ( ! $ shipping_address ->postal_code () && ! $ this ->country_without_postal_code ( $ shipping_address ->country_code () ) )
198- ) {
194+ if ( ! $ shipping_address || ! $ this ->can_use_shipping_address ( $ shipping_address ) ) {
199195 $ shipping = null ;
200196 }
201197 }
@@ -387,10 +383,51 @@ private function sanitize_soft_descriptor( string $soft_descriptor ): string {
387383 * @return bool
388384 */
389385 private function should_disable_shipping ( array $ items , ?Address $ shipping_address ): bool {
390- return ! $ this ->shipping_needed ( ...array_values ( $ items ) ) ||
391- ! $ shipping_address ||
392- empty ( $ shipping_address ->country_code () ) ||
393- empty ( $ shipping_address ->address_line_1 () ) ||
394- ( ! $ shipping_address ->postal_code () && ! $ this ->country_without_postal_code ( $ shipping_address ->country_code () ) );
386+ // No items require physical shipping.
387+ if ( ! $ this ->shipping_needed ( ...array_values ( $ items ) ) ) {
388+ return true ;
389+ }
390+
391+ // Cannot proceed without a shipping address.
392+ if ( ! $ shipping_address ) {
393+ return true ;
394+ }
395+
396+ return ! $ this ->can_use_shipping_address ( $ shipping_address );
397+ }
398+
399+ /**
400+ * Decides whether a shipping address is complete enough to send to PayPal.
401+ *
402+ * PayPal's Orders v2 API rejects incomplete addresses. For virtually every
403+ * country, country_code, address_line_1, admin_area_2 (city), and postal_code
404+ * are required. A small set of countries (see country_without_postal_code())
405+ * have an optional postal code; city is still required there.
406+ *
407+ * @param Address $shipping_address The address to validate.
408+ * @return bool True if the address is usable, false if it should be dropped.
409+ */
410+ private function can_use_shipping_address ( Address $ shipping_address ): bool {
411+ // Country code must be a valid 2-letter ISO code.
412+ if ( 2 !== strlen ( $ shipping_address ->country_code () ) ) {
413+ return false ;
414+ }
415+
416+ // Street address is required.
417+ if ( empty ( $ shipping_address ->address_line_1 () ) ) {
418+ return false ;
419+ }
420+
421+ // City is required in virtually every country per PayPal's address rules.
422+ if ( empty ( $ shipping_address ->admin_area_2 () ) ) {
423+ return false ;
424+ }
425+
426+ // Postal code is required unless the country is on the no-postal-code allowlist.
427+ if ( empty ( $ shipping_address ->postal_code () ) && ! $ this ->country_without_postal_code ( $ shipping_address ->country_code () ) ) {
428+ return false ;
429+ }
430+
431+ return true ;
395432 }
396433}
0 commit comments