Skip to content

Commit 247d167

Browse files
authored
Merge pull request #4292 from woocommerce/dev/PCP-6265-shipping-city-required
Drop shipping when city is missing to prevent CITY_REQUIRED (6265)
2 parents d6476fb + 96b3377 commit 247d167

2 files changed

Lines changed: 821 additions & 1099 deletions

File tree

modules/ppcp-api-client/src/Factory/PurchaseUnitFactory.php

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)