mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-08-30 05:00:51 +08:00
Merge pull request #3557 from woocommerce/PCP-4974-contact-module-virtual-product-from-block-pages-and-classic-checkout-always-return-default-contact-information-from-pay-pal-window
Some checks failed
Some checks failed
Contact module -does not work for virtual products in block pages and classic checkout
This commit is contained in:
commit
2ec6daca38
7 changed files with 109 additions and 83 deletions
|
@ -17,46 +17,46 @@ class Shipping {
|
|||
/**
|
||||
* The name.
|
||||
*
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
private $name;
|
||||
private ?string $name;
|
||||
|
||||
/**
|
||||
* The address.
|
||||
*
|
||||
* @var Address
|
||||
* @var Address|null
|
||||
*/
|
||||
private $address;
|
||||
private ?Address $address;
|
||||
|
||||
/**
|
||||
* Custom contact email address, usually added via the Contact Module.
|
||||
*/
|
||||
private ?string $email_address = null;
|
||||
private ?string $email_address;
|
||||
|
||||
/**
|
||||
* Custom contact phone number, usually added via the Contact Module.
|
||||
*/
|
||||
private ?Phone $phone_number = null;
|
||||
private ?Phone $phone_number;
|
||||
|
||||
/**
|
||||
* Shipping methods.
|
||||
*
|
||||
* @var ShippingOption[]
|
||||
*/
|
||||
private $options;
|
||||
private array $options;
|
||||
|
||||
/**
|
||||
* Shipping constructor.
|
||||
*
|
||||
* @param string $name The name.
|
||||
* @param Address $address The address.
|
||||
* @param string|null $name The name.
|
||||
* @param Address|null $address The address.
|
||||
* @param string|null $email_address Contact email.
|
||||
* @param Phone|null $phone_number Contact phone.
|
||||
* @param ShippingOption[] $options Shipping methods.
|
||||
*/
|
||||
public function __construct(
|
||||
string $name,
|
||||
Address $address,
|
||||
string $name = null,
|
||||
Address $address = null,
|
||||
?string $email_address = null,
|
||||
?Phone $phone_number = null,
|
||||
array $options = array()
|
||||
|
@ -71,18 +71,18 @@ class Shipping {
|
|||
/**
|
||||
* Returns the name.
|
||||
*
|
||||
* @return string
|
||||
* @return null|string
|
||||
*/
|
||||
public function name(): string {
|
||||
public function name(): ?string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shipping address.
|
||||
*
|
||||
* @return Address
|
||||
* @return null|Address
|
||||
*/
|
||||
public function address(): Address {
|
||||
public function address(): ?Address {
|
||||
return $this->address;
|
||||
}
|
||||
|
||||
|
@ -119,19 +119,26 @@ class Shipping {
|
|||
* @return array
|
||||
*/
|
||||
public function to_array(): array {
|
||||
$result = array(
|
||||
'name' => array(
|
||||
'full_name' => $this->name(),
|
||||
),
|
||||
'address' => $this->address()->to_array(),
|
||||
);
|
||||
$result = array();
|
||||
|
||||
$name = $this->name();
|
||||
if ( $name ) {
|
||||
$result['name'] = array(
|
||||
'full_name' => $name,
|
||||
);
|
||||
}
|
||||
|
||||
$address = $this->address();
|
||||
if ( $address ) {
|
||||
$result['address'] = $address->to_array();
|
||||
}
|
||||
|
||||
$contact_email = $this->email_address();
|
||||
$contact_phone = $this->phone_number();
|
||||
|
||||
if ( $contact_email ) {
|
||||
$result['email_address'] = $contact_email;
|
||||
}
|
||||
|
||||
$contact_phone = $this->phone_number();
|
||||
if ( $contact_phone ) {
|
||||
$result['phone_number'] = $contact_phone->to_array();
|
||||
}
|
||||
|
@ -144,6 +151,7 @@ class Shipping {
|
|||
$this->options
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\PurchaseUnitSanitizer;
|
||||
use WooCommerce\PayPalCommerce\Webhooks\CustomIds;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Address;
|
||||
|
||||
/**
|
||||
* Class PurchaseUnitFactory
|
||||
|
@ -108,21 +109,20 @@ class PurchaseUnitFactory {
|
|||
* @return PurchaseUnit
|
||||
*/
|
||||
public function from_wc_order( \WC_Order $order ): PurchaseUnit {
|
||||
$amount = $this->amount_factory->from_wc_order( $order );
|
||||
$items = array_filter(
|
||||
$amount = $this->amount_factory->from_wc_order( $order );
|
||||
$items = array_filter(
|
||||
$this->item_factory->from_wc_order( $order ),
|
||||
function ( Item $item ): bool {
|
||||
return $item->unit_amount()->value() >= 0;
|
||||
}
|
||||
);
|
||||
$shipping = $this->shipping_factory->from_wc_order( $order );
|
||||
if (
|
||||
! $this->shipping_needed( ... array_values( $items ) ) ||
|
||||
empty( $shipping->address()->country_code() ) ||
|
||||
( ! $shipping->address()->postal_code() && ! $this->country_without_postal_code( $shipping->address()->country_code() ) )
|
||||
) {
|
||||
|
||||
$shipping = $this->shipping_factory->from_wc_order( $order );
|
||||
$shipping_address = $shipping->address();
|
||||
if ( $this->should_disable_shipping( $items, $shipping_address ) ) {
|
||||
$shipping = null;
|
||||
}
|
||||
|
||||
$reference_id = 'default';
|
||||
$description = '';
|
||||
$custom_id = (string) $order->get_id();
|
||||
|
@ -176,10 +176,12 @@ class PurchaseUnitFactory {
|
|||
$shipping = null;
|
||||
$customer = \WC()->customer;
|
||||
if ( $this->shipping_needed( ... array_values( $items ) ) && is_a( $customer, \WC_Customer::class ) ) {
|
||||
$shipping = $this->shipping_factory->from_wc_customer( \WC()->customer, $with_shipping_options );
|
||||
$shipping = $this->shipping_factory->from_wc_customer( \WC()->customer, $with_shipping_options );
|
||||
$shipping_address = $shipping->address();
|
||||
if (
|
||||
2 !== strlen( $shipping->address()->country_code() ) ||
|
||||
( ! $shipping->address()->postal_code() && ! $this->country_without_postal_code( $shipping->address()->country_code() ) )
|
||||
! $shipping_address ||
|
||||
2 !== strlen( $shipping_address->country_code() ) ||
|
||||
( ! $shipping_address->postal_code() && ! $this->country_without_postal_code( $shipping_address->country_code() ) )
|
||||
) {
|
||||
$shipping = null;
|
||||
}
|
||||
|
@ -248,7 +250,7 @@ class PurchaseUnitFactory {
|
|||
}
|
||||
$shipping = null;
|
||||
try {
|
||||
if ( isset( $data->shipping ) ) {
|
||||
if ( isset( $data->shipping ) && ! empty( (array) $data->shipping ) ) {
|
||||
$shipping = $this->shipping_factory->from_paypal_response( $data->shipping );
|
||||
}
|
||||
} catch ( RuntimeException $error ) {
|
||||
|
@ -337,4 +339,19 @@ class PurchaseUnitFactory {
|
|||
|
||||
return substr( $sanitized, 0, 22 ) ?: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether shipping should be disabled for a purchase unit.
|
||||
*
|
||||
* @param array $items Purchase unit items.
|
||||
* @param Address|null $shipping_address The shipping address to validate.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function should_disable_shipping( array $items, ?Address $shipping_address ): bool {
|
||||
return ! $this->shipping_needed( ... array_values( $items ) ) ||
|
||||
! $shipping_address ||
|
||||
empty( $shipping_address->country_code() ) ||
|
||||
( ! $shipping_address->postal_code() && ! $this->country_without_postal_code( $shipping_address->country_code() ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,30 +96,25 @@ class ShippingFactory {
|
|||
* @throws RuntimeException When JSON object is malformed.
|
||||
*/
|
||||
public function from_paypal_response( \stdClass $data ): Shipping {
|
||||
if ( ! isset( $data->name->full_name ) ) {
|
||||
throw new RuntimeException( 'No name was given for shipping.' );
|
||||
}
|
||||
if ( ! isset( $data->address ) ) {
|
||||
throw new RuntimeException( 'No address was given for shipping.' );
|
||||
}
|
||||
$contact_phone = null;
|
||||
$contact_email = null;
|
||||
$address = $this->address_factory->from_paypal_response( $data->address );
|
||||
$name = $data->name->full_name ?? null;
|
||||
|
||||
$address = isset( $data->address )
|
||||
? $this->address_factory->from_paypal_response( $data->address )
|
||||
: null;
|
||||
|
||||
$contact_email = $data->email_address ?? null;
|
||||
|
||||
$contact_phone = isset( $data->phone_number->national_number )
|
||||
? new Phone( $data->phone_number->national_number )
|
||||
: null;
|
||||
|
||||
$options = array_map(
|
||||
array( $this->shipping_option_factory, 'from_paypal_response' ),
|
||||
$data->options ?? array()
|
||||
);
|
||||
|
||||
if ( isset( $data->phone_number->national_number ) ) {
|
||||
$contact_phone = new Phone( $data->phone_number->national_number );
|
||||
}
|
||||
if ( isset( $data->email_address ) ) {
|
||||
$contact_email = $data->email_address;
|
||||
}
|
||||
|
||||
return new Shipping(
|
||||
$data->name->full_name,
|
||||
$name,
|
||||
$address,
|
||||
$contact_email,
|
||||
$contact_phone,
|
||||
|
|
|
@ -265,7 +265,10 @@ export const PayPalComponent = ( {
|
|||
};
|
||||
}
|
||||
|
||||
const addresses = paypalOrderToWcAddresses( paypalOrder );
|
||||
let addresses = {};
|
||||
if ( paypalOrder.purchase_units?.[ 0 ]?.shipping?.address ) {
|
||||
addresses = paypalOrderToWcAddresses( paypalOrder );
|
||||
}
|
||||
|
||||
return {
|
||||
type: responseTypes.SUCCESS,
|
||||
|
|
|
@ -99,31 +99,34 @@ export const handleApprove = async (
|
|||
order = json.data;
|
||||
}
|
||||
|
||||
const addresses = paypalOrderToWcAddresses( order );
|
||||
const shippingAddress = order.purchase_units?.[ 0 ]?.shipping?.address;
|
||||
if ( shippingAddress ) {
|
||||
const addresses = paypalOrderToWcAddresses( order );
|
||||
|
||||
const promises = [
|
||||
// save address on server
|
||||
wp.data.dispatch( 'wc/store/cart' ).updateCustomerData( {
|
||||
billing_address: addresses.billingAddress,
|
||||
shipping_address: addresses.shippingAddress,
|
||||
} ),
|
||||
];
|
||||
if ( shouldHandleShippingInPayPal() ) {
|
||||
// set address in UI
|
||||
promises.push(
|
||||
wp.data
|
||||
.dispatch( 'wc/store/cart' )
|
||||
.setBillingAddress( addresses.billingAddress )
|
||||
);
|
||||
if ( shippingData.needsShipping ) {
|
||||
const promises = [
|
||||
// save address on server
|
||||
wp.data.dispatch( 'wc/store/cart' ).updateCustomerData( {
|
||||
billing_address: addresses.billingAddress,
|
||||
shipping_address: addresses.shippingAddress,
|
||||
} ),
|
||||
];
|
||||
if ( shouldHandleShippingInPayPal() ) {
|
||||
// set address in UI
|
||||
promises.push(
|
||||
wp.data
|
||||
.dispatch( 'wc/store/cart' )
|
||||
.setShippingAddress( addresses.shippingAddress )
|
||||
.setBillingAddress( addresses.billingAddress )
|
||||
);
|
||||
if ( shippingData.needsShipping ) {
|
||||
promises.push(
|
||||
wp.data
|
||||
.dispatch( 'wc/store/cart' )
|
||||
.setShippingAddress( addresses.shippingAddress )
|
||||
);
|
||||
}
|
||||
}
|
||||
await Promise.all( promises );
|
||||
}
|
||||
await Promise.all( promises );
|
||||
|
||||
setPaypalOrder( order );
|
||||
|
||||
|
|
|
@ -237,17 +237,18 @@ class WooCommerceOrderCreator {
|
|||
|
||||
if ( $shipping ) {
|
||||
$address = $shipping->address();
|
||||
|
||||
$shipping_address = array(
|
||||
'first_name' => $shipping->name(),
|
||||
'last_name' => '',
|
||||
'address_1' => $address->address_line_1(),
|
||||
'address_2' => $address->address_line_2(),
|
||||
'city' => $address->admin_area_2(),
|
||||
'state' => $address->admin_area_1(),
|
||||
'postcode' => $address->postal_code(),
|
||||
'country' => $address->country_code(),
|
||||
);
|
||||
if ( $address ) {
|
||||
$shipping_address = array(
|
||||
'first_name' => $shipping->name(),
|
||||
'last_name' => '',
|
||||
'address_1' => $address->address_line_1(),
|
||||
'address_2' => $address->address_line_2(),
|
||||
'city' => $address->admin_area_2(),
|
||||
'state' => $address->admin_area_1(),
|
||||
'postcode' => $address->postal_code(),
|
||||
'country' => $address->country_code(),
|
||||
);
|
||||
}
|
||||
|
||||
$shipping_options = $shipping->options()[0] ?? '';
|
||||
}
|
||||
|
|
|
@ -162,7 +162,6 @@ class PurchaseUnitFactoryTest extends TestCase
|
|||
$shipping = Mockery::mock(Shipping::class);
|
||||
$shipping
|
||||
->expects('address')
|
||||
->times(3)
|
||||
->andReturn($address);
|
||||
$shippingFactory = Mockery::mock(ShippingFactory::class);
|
||||
$shippingFactory
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue