sauladam / shipment-tracker

Parses tracking information for several carriers, like UPS, USPS, DHL and GLS by simply scraping the data. No need for any kind of API access.
93 stars 32 forks source link

bug with DHL #22

Closed macmastermike closed 4 years ago

macmastermike commented 4 years ago

for me the DHL tracking is not working right now... $dhlTracker->track($dhlCode)

i fixed it by editing the Trackers/DHL.php file - last line:

return $this->serviceEndpoint . '?' . http_build_query($urlParams); into: return $this->serviceEndpoint . '%3F' . http_build_query($urlParams);

as soon as the question mark was replaced by the encoded letter everything worked like it should

sauladam commented 4 years ago

Hey @macmastermike, thank you for your feedback!

To my surprise, I'm actually able to reproduce this behaviour locally, although it's working fine in our production environment. The setups are neraly identical.

My understanding is that the questionmark is not part of the query and therefore should (must?) not be URL-encoded. But obviously this isn't quite right.

Every other URL in this package (or every other piece of code I've written) is being constructed in the exact same way and there is no issue whatsoever. So, honestly, I'm a bit buffled and not quite sure how to handle this or why this is happening in the first place.

Any ideas or explanations would be appreciated! I don't really want to make that change without understanding the reason behind it and what it might affect.

macmastermike commented 4 years ago

good question - i'm also confused why this happened. maybe helpful: my local environment is WSL1 running debian linux and i've tried your (awesome) script inside a symfony application...

maybe some locale problem? i found out about this problem using $dhlTracker->useDataProvider('php') - this option showed me the file_get_contents error after timeout. so i rebuilt the url manually until it worked...

wouldn't the change be working on all systems? the & letter is also always encoded as & ? ...but i'm not really an encoding-expert...

sauladam commented 4 years ago

Hey @macmastermike,

thank you so much for your effort!

My local environment is a Docker setup with Ubunutu 18.04, the production environment is an Ubuntu 18.04 VPS without docker. Anyway, I finally figured out why it worked in production but not locally: It's because I'm a fucking idiot.

The DHL tracker just mysteriously stopped working for me a few months or so ago. But since nobody was screaming on GitHub, I just figured that it was a 'just me' issue. So instead of the default Guzzle provider I gave it a custom CURL provider (which I completely forgot about!) with the following configuration:

class CustomCurlClient implements \Sauladam\ShipmentTracker\DataProviders\DataProviderInterface {

    public function get($url)
    {
        $curl = curl_init();

        curl_setopt_array($curl, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => "",
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 10,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => "GET",
        ]);

        $response = curl_exec($curl);

        curl_close($curl);

        return $response;
    }
}

$dhl = ShipmentTracker::get('DHL', new CustomCurlClient);

Honestly, I have no idea why this works, but it does. I guess Guzzle just messes with some headers. Everything seems to revolve around the CURLOPT_ENCODING CURL option because it stops working when I omit it. From the docs:

The contents of the "Accept-Encoding: " header. This enables decoding of the response. Supported encodings are "identity", "deflate", and "gzip". If an empty string, "", is set, a header containing all supported encoding types is sent.

So in my case it just sets Accept-Encoding: deflate, gzip. But if I set it manually on Guzzle, it fails.

So yeah, it seems to have something to do with the encoding, but not sure what it is. In the browser it just returns the content as gzip, so nothing too fancy going on there. Anyway, your solution worked fine for me and is a way easier fix than the custom provider, so I guess I will just go with that and merge that in in a minute.

Really appreciate your contribution so thanks again and have a great weekend!

luqman74 commented 3 years ago

Hi First of all thank you very much for great script. I am still facing the issue mentioned above. When ever I pass in variable in $dhlTracker->track($sendung_number) I get error " ErrorException Undefined offset: 0" in this file \vendor\sauladam\shipment-tracker\src\Trackers\DHL.php:133 but if pass in just string it works fine. I am not sure why is this so cann you please help.

sauladam commented 3 years ago

Hey @luqman74,

if it works with a hard coded string but not with a passed in variable, there's a pretty big chance that the value of $sendung_number is not what you expect it to be :)

What does var_dump($sendung_number) give you?

luqman74 commented 3 years ago

I just did dd() and got this result. "00340434296320485897"

luqman74 commented 3 years ago

and var dump gives me string(20) "00340434296320585807"

sauladam commented 3 years ago

That's interesting @luqman74. Which exact version are you using? Just tested it with the current version (0.7.0) and it seems to work fine.

Maybe you could tap into your local \vendor\sauladam\shipment-tracker\src\Trackers\DHL.php and place some var_dumps around line 133. The error sounds like it's referring to the line

$progress = $this->parseJson($xpath)->sendungen[0]->sendungsdetails->sendungsverlauf;

But index 0 should actually always be set if no Exception was thrown until then.

luqman74 commented 3 years ago

Hi @sauladam first of all thank you very much for your quick responses and solutions to debug it. once I did var_dump in dhl.php file for $progress variable. I found out I am a crack head 🤣 Actually I am working with third party dhl api and send the delievery info through that and then I save it in my database and if there is an error I also save it in database and in my loop some data is without sendungs nummer/ tracking code and that is why it was giving that 0 error because of empty string. I just put on some if conditions in my code and it is working like a charm thanks again for great script and I really appreciate your help. Have a nice weekend 👍

sauladam commented 3 years ago

Haha yeah, been there, done that :-D @luqman74

Glad you figured it out and especially glad to hear you're finding this package useful.

Have a nice weekend too!