woocommerce / woocommerce-gateway-paypal-express-checkout

58 stars 65 forks source link

SHIP TO displays in Paypal dialog on orders that are not shipped #878

Open ifnull opened 3 years ago

ifnull commented 3 years ago

Describe the bug

We have an in-store pick up option that does not require shipping. Despite not setting a shipping address, the "Ship to" is displayed in the Paypal dialog. The issue appears to be that get_set_express_checkout_params() only checks if $details['shipping_address'] is empty (which it never is). $details calls _get_details_from_cart() which sets shipping_address using _get_address_from_customer(). Which sets $shipping_address using a shipping address if provided, but falls back to the billing address. This means, in our case, the billing address is always displayed as the "Ship to" in the Paypal dialog which can be confusing to customers who are expecting to pick up their order. Any suggestions on a short-term workaround that doesn't involve forking the plugin would be greatly appreciated. Thanks!

Screen Shot 2021-07-20 at 3 42 32 PM

To reproduce

  1. Do not set a shipping address
  2. Set billing address
  3. Click Paypal button
  4. Observe billing address in Ship to area

Expected behavior

If no shipping address is set, no shipping address is sent to Paypal.

Screen Shot 2021-07-20 at 3 43 39 PM

Environment:

Additional details

Removing the following block of code from get_set_express_checkout_params() achieves the desired result in our case. However, we are trying to avoid having to maintain a forked version of the plugin.

if ( ! empty( $details['shipping_address'] ) ) {
    $params = array_merge(
        $params,
        $details['shipping_address']->getAddressParams( 'PAYMENTREQUEST_0_SHIPTO' )
    );
}
ifnull commented 3 years ago

My colleague identified a workaround solution for this problem by applying a filter to woocommerce_paypal_express_checkout_request_body to remove PAYMENTREQUEST_0_SHIPTO* params when NOSHIPPING is present.

Example

add_filter('woocommerce_paypal_express_checkout_request_body', array($this, 'correct_paypal_params_for_no_shipping'), 9999, 1);

public function correct_paypal_params_for_no_shipping($params){
    if (array_key_exists('NOSHIPPING', $params) && 1 == $params['NOSHIPPING']){
        $params = array_filter($params, function($key){
            return !(0 === strpos($key, 'PAYMENTREQUEST_0_SHIPTO'));
        }, ARRAY_FILTER_USE_KEY);
    }
    return $params;
}