WC_REST_Paypal_Standard_Controller::process_shipping_callbackpublicWC 1.0

Callback for when the customer updates their shipping details in PayPal. https://developer.paypal.com/docs/checkout/standard/customize/shipping-module/#server-side-shipping-callbacks

Method of the class: WC_REST_Paypal_Standard_Controller{}

No Hooks.

Returns

WP_REST_Response. The response object.

Usage

$WC_REST_Paypal_Standard_Controller = new WC_REST_Paypal_Standard_Controller();
$WC_REST_Paypal_Standard_Controller->process_shipping_callback( $request );
$request(WP_REST_Request) (required)
The request object.

WC_REST_Paypal_Standard_Controller::process_shipping_callback() code WC 10.7.0

public function process_shipping_callback( WP_REST_Request $request ) {
	$paypal_order_id  = $request->get_param( 'id' );
	$shipping_address = $request->get_param( 'shipping_address' );
	$shipping_option  = $request->get_param( 'shipping_option' );
	$purchase_units   = $request->get_param( 'purchase_units' );

	// Note: shipping_option may or may not be present.
	if ( empty( $paypal_order_id ) || empty( $shipping_address ) || empty( $purchase_units ) ) {
		$response = $this->get_update_shipping_error_response();
		return new WP_REST_Response( $response, 422 );
	}

	// Get the WC order.
	$order = PayPalHelper::get_wc_order_from_paypal_custom_id( $purchase_units[0]['custom_id'] ?? '{}' );
	if ( ! $order ) {
		$custom_id = isset( $purchase_units[0]['custom_id'] ) ? $purchase_units[0]['custom_id'] : '{}';
		WC_Gateway_Paypal::log( 'Unable to determine WooCommerce order from PayPal custom ID: ' . $custom_id );
		$response = $this->get_update_shipping_error_response();
		return new WP_REST_Response( $response, 422 );
	}

	// Compare PayPal order IDs.
	$paypal_order_id_from_order_meta = $order->get_meta( '_paypal_order_id', true );
	if ( empty( $paypal_order_id_from_order_meta ) || $paypal_order_id !== $paypal_order_id_from_order_meta ) {
		WC_Gateway_Paypal::log(
			'PayPal order ID mismatch. Order ID: ' . $order->get_id() .
			'. PayPal order ID (request): ' . $paypal_order_id .
			'. PayPal order ID (order meta): ' . $paypal_order_id_from_order_meta
		);
		$response = $this->get_update_shipping_error_response();
		return new WP_REST_Response( $response, 422 );
	}

	// Validate that the order is in a valid state for shipping updates.
	// Only draft or pending orders should accept shipping updates.
	if ( ! in_array( $order->get_status(), array( OrderStatus::CHECKOUT_DRAFT, OrderStatus::PENDING ), true ) ) {
		WC_Gateway_Paypal::log(
			'Order is not in a valid state for shipping updates. Order ID: ' . $order->get_id() .
			'. Order status: ' . $order->get_status()
		);
		$response = $this->get_update_shipping_error_response();
		return new WP_REST_Response( $response, 422 );
	}

	// If the order has a PayPal transaction ID, a charge has already occurred, so we shouldn't change the shipping address.
	$transaction_id = $order->get_transaction_id();
	if ( ! empty( $transaction_id ) ) {
		WC_Gateway_Paypal::log(
			'Order already has a transaction ID, cannot update shipping. Order ID: ' . $order->get_id() .
			'. Transaction ID: ' . $transaction_id
		);
		$response = $this->get_update_shipping_error_response();
		return new WP_REST_Response( $response, 422 );
	}

	if ( ! WC()->session ) {
		WC()->session = new WC_Session_Handler();
	}
	WC()->session->init();

	// Update the shipping address before we do anything else.
	$this->update_order_shipping_address( $order, $shipping_address );

	// We need to rebuild the cart from the order, as we do not have session cart data
	// for REST API requests.
	$this->rebuild_cart_from_order( $order );

	// Get the new shipping options, which depend on the new shipping address.
	$updated_shipping_options = $this->get_updated_shipping_options( $order, $shipping_option );
	if ( empty( $updated_shipping_options ) ) {
		WC_Gateway_Paypal::log(
			'No shipping options found for address. Order ID: ' . $order->get_id() .
			'. Address: ' . wp_json_encode( $shipping_address )
		);
		$response = $this->get_update_shipping_error_response();
		return new WP_REST_Response( $response, 422 );
	}

	// Set the chosen shipping method in the session.
	if ( ! empty( $shipping_option ) ) {
		WC()->session->set( 'chosen_shipping_methods', array( $shipping_option['id'] ) );
	}

	// Recompute fees after everything has been updated.
	$this->recompute_fees( $order );

	$paypal_request = new PayPalRequest( WC_Gateway_Paypal::get_instance() );
	$updated_amount = $paypal_request->get_paypal_order_purchase_unit_amount( $order );

	$response = array(
		'id'             => $paypal_order_id,
		'purchase_units' => array(
			array(
				'reference_id'     => isset( $purchase_units[0]['reference_id'] ) ? $purchase_units[0]['reference_id'] : '', // No change.
				'amount'           => $updated_amount,
				'shipping_options' => $updated_shipping_options,
			),
		),
	);

	return new WP_REST_Response( $response, 200 );
}