Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using query parameters with requests #112

Open
julien-MD opened this issue Feb 13, 2024 · 2 comments
Open

Using query parameters with requests #112

julien-MD opened this issue Feb 13, 2024 · 2 comments

Comments

@julien-MD
Copy link

Hi,

I had an issue where orders created were too big for the Woocommerce server to be able to build a response, the query ending in a server timeout.
I asked Woocommerce if it was possible to request the REST API to not send back the whole order data, as I send it in the first place and do not need it. They replied that I could use the query parameters in order to achieve that (see here).

It appears that this library does not allow this possibility (or I didn't find out how it is possible to do it), so I had to edit files for myself.

Is it possible to add this feature in a future release?

Thanks

@Codexshaper
Copy link
Owner

Hello @julien-MD,

Thanks for creating the issue and explaining your problem. We will be happy if we can include them. Can you share some examples that you are trying to do?

@julien-MD
Copy link
Author

Hi,

Here is some more data about the request.

I have a Controller which build the data array needed:

 $data = [
            'customer_note'         => $order_comment,
		    'billing' => [
		        'first_name' => $customer['billing']->first_name,
		        'last_name'  => $customer['billing']->last_name,
		        'address_1'  => $customer['billing']->address_1,
		        'address_2'  => $customer['billing']->address_2,
		        'city'       => $customer['billing']->city,
		        'state'      => $customer['billing']->state,
		        'postcode'   => $customer['billing']->postcode,
		        'country'    => $customer['billing']->country,
		        'email'      => $customer['billing']->email,
		        'phone'      => $customer['billing']->phone,
		    ],
		    'shipping' => [
		        'first_name' => $customer['shipping']->first_name,
		        'last_name'  => $customer['shipping']->last_name,
		        'address_1'  => $customer['shipping']->address_1,
		        'address_2'  => $customer['shipping']->address_2,
		        'city'       => $customer['shipping']->city,
		        'state'      => $customer['shipping']->state,
		        'postcode'   => $customer['shipping']->postcode,
		        'country'    => $customer['shipping']->country,
		    ],
		    'line_items'			=> [],
		    'shipping_lines' => [
		        [
		            'method_id' 	=> 'gls_chezvous',
		            'method_title'	=> 'GLS',
		            'total'			=> '0'
		        ]
		    ]
		];

		foreach ($order_products as $order_product) {
			$product = Products::where('id', $order_product->product_id)->first();
		    $data['line_items'][] =
		        [
		            'product_id'		=> $product->wc_product_id,
		            'variation_id'		=> $product->wc_variation_id,
		            'quantity'			=> $order_product->quantity,
		            'meta_data' 		=> [
		            	['key' => 'Commentaire', 'value' => $order_product->product_comment ?? '']
		            ]
		        ];
		}

Here, the thing is my $order_products array will eventually be quite big because the app is intended to be used by customers who buy a lot of products.

Then I have a Job which process the sending of the order to Woocommerce, it is called in the Controller like so:
ProcessExport::dispatch(['order_data' => $data, 'order_id' => $order->id, 'customer_id' => $customer_id]);

Here is the job:

    public function handle(): void
    {
        $wc_order = Order::create($this->data['order_data']);

        if(isset($wc_order['id'])) {
            do_things();
        }
        else{
            do_other_things();
        }
    }

You can see that I need to wait for the Woocommerce response in order to go on with the code. The issue is at this point, because the Woocommerce API default behavior is to send me back the whole order data. If the server is almost idling and the order not to big, it has time to build its response. Otherway, it timeouts (but the order is created on the Woocommerce side).

In order to get around the issue I had to edit the Woocommerce API, forcing it to send me back only the data I need:
File vendor/automattic/woocommerce/src/WooCommerce/HttpClient/HttpClient.php

    protected function createRequest($endpoint, $method, $data = [], $parameters = [])
    {
        $body    = '';
        $url     = $this->url . $endpoint;
        $hasData = !empty($data);
        $headers = $this->getRequestHeaders($hasData);

        // HTTP method override feature which masks PUT and DELETE HTTP methods as POST method with added
        // ?_method=PUT query parameter and/or X-HTTP-Method-Override HTTP header.
        if (!in_array($method, ['GET', 'POST'])) {
            $usePostMethod = false;
            if ($this->options->isMethodOverrideQuery()) {
                $parameters = array_merge(['_method' => $method], $parameters);
                $usePostMethod = true;
            }
            if ($this->options->isMethodOverrideHeader()) {
                $headers['X-HTTP-Method-Override'] = $method;
                $usePostMethod = true;
            }
            if ($usePostMethod) {
                $method = 'POST';
            }
        }

        // Setup authentication.
        $parameters = $this->authenticate($url, $method, $parameters);

        // Setup method.
        $this->setupMethod($method);

        // Include post fields.
        if ($hasData) {
            $body = \json_encode($data);
            \curl_setopt($this->ch, CURLOPT_POSTFIELDS, $body);
        }

/* Start of what I added */

        if($method == 'POST' && $endpoint == 'orders')
            $parameters = array_merge(['_fields' => 'id'], $parameters);

/* End of what I added */

        $this->request = new Request(
            $this->buildUrlQuery($url, $parameters),
            $method,
            $parameters,
            $headers,
            $body
        );

        return $this->getRequest();
    }

This method allows a $parameters input which can be used to do a lot of things but in my case it let me tell it that I only needed the id of the created order using the _fields key.

I did not find a proper way to send this $parameters parameter using the Order::create() method within laravel-woocommerce.

Let me know if you need more info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants