Home > Back-end >  Need help converting a Python script to PHP
Need help converting a Python script to PHP

Time:10-29

I've written a PHP script to track packages from various shippers, but wasn't able to write one for FedEx that worked. Then I found the python script below. It works great, but I'd like to standardize on PHP for all my code. I've spent the last few weeks trying to convert it, but the middle part with the json data has me stumped.

Would someone be willing to provide some pointers on how to convert that part to PHP?

#!/usr/local/bin/python3

import requests, json, subprocess, datetime, sys, os.path

################
## Grab the argument(s) passed by the calling script.
################
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('tracking_number')
args = parser.parse_args()
tracking_number = args.tracking_number
################

data = requests.post('https://www.fedex.com/trackingCal/track', data={
    'data': json.dumps({
        'TrackPackagesRequest': {
            'appType': 'wtrk',
            'uniqueKey': '',
            'processingParameters': {
                'anonymousTransaction': True,
                'clientId': 'WTRK',
                'returnDetailedErrors': True,
                'returnLocalizedDateTime': False
            },
            'trackingInfoList': [{
                'trackNumberInfo': {
                    'trackingNumber': tracking_number,
                    'trackingQualifier': '',
                    'trackingCarrier': ''
                }
            }]
        }
    }),
    'action': 'trackpackages',
    'locale': 'en_US',
    'format': 'json',
    'version': 99
}).json()

fedex_status  = data['TrackPackagesResponse']['packageList'][0]['keyStatus']
fedex_details = data['TrackPackagesResponse']['packageList'][0]['statusWithDetails']
delivery_date = data['TrackPackagesResponse']['packageList'][0]['displayActDeliveryDt']
delivery_time = data['TrackPackagesResponse']['packageList'][0]['displayActDeliveryTm']

This is the closest I've been able to come using the PHP Requests library:

<?php

$dir = __DIR__;
include $dir .'/vendor/autoload.php';

$tracking_number = '123456789';

$url = 'https://www.fedex.com/trackingCal/track';

$headers = ['Content-Type' => 'application/json'];

$data = ['data' => [
            'TrackPackagesRequest' => [
                'appType'   => 'wtrk',
                'uniqueKey' => '',
                'processingParameters'       => [
                    'anonymousTransaction'    => true,
                    'clientId'                => 'WTRK',
                    'returnDetailedErrors'    => true,
                    'returnLocalizedDateTime' => false
                ],
                'trackingInfoList' => [
                    [
                        'trackNumberInfo'      => [
                            'trackingNumber'    => $tracking_number,
                            'trackingQualifier' => '',
                            'trackingCarrier'   => ''
                        ]
                    ]
                ]
            ]],
    'action' => 'trackpackages',
    'locale' => 'en_US',
    'format' => 'json',
    'version' => 99
    ];
            
$response = Requests::post($url, $headers, json_encode($data));

print_r($response);

but it returns

{
    "CALError": {
        "code":"UNSUPPORTED.ACTION",
        "message":" is not a supported action",
        "rootCause":null
    }
}

I think this would also help a lot of other people looking to track FedEx packages as I've seen this question asked before.

For the record, I'm not looking to set up a FedEx account just to use their API for this.

Thank you, Frank

CodePudding user response:

The Python script doesn't send the POST request body as JSON. It uses data= rather than json=, which sends it as a URL-encoded data=value, where the value is a JSON-encoded object.

You need to do it similarly in the PHP version. Only the data parameter should be encoded as JSON, not the entire request.

<?php

$dir = __DIR__;
include $dir .'/vendor/autoload.php';

$tracking_number = '123456789';

$url = 'https://www.fedex.com/trackingCal/track';

$headers = [];

$data = [
    "data" => json_encode([
        "TrackPackagesRequest" => [
            "appType" => "wtrk",
            "uniqueKey" => "",
            "processingParameters" => [
                "anonymousTransaction" => true,
                "clientId" => "WTRK",
                "returnDetailedErrors" => true,
                "returnLocalizedDateTime" => false
            ],
            "trackingInfoList" => [[
                "trackNumberInfo" => [
                    "trackingNumber" => $tracking_number,
                    "trackingQualifier" => "",
                    "trackingCarrier" => ""
                ]
            ]]
        ]

    ]),
    "action" => "trackpackages",
    "locale" => "en_US",
    "format" => "json",
    "version" => 99
];

$response = Requests::post($url, $headers, $data);

print_r($response);

CodePudding user response:

Thanks to Barmar!, I got it to work. Here's some working code using the Requests library https://github.com/WordPress/Requests, in case anyone else is interested:

<?php

$dir = __DIR__;
include $dir .'/vendor/autoload.php';

$tracking_number = '123';

$url = 'https://www.fedex.com/trackingCal/track';

$data = [
    "data" => json_encode([
        "TrackPackagesRequest" => [
            "appType" => "wtrk",
            "uniqueKey" => "",
            "processingParameters" => [
                "anonymousTransaction" => true,
                "clientId" => "WTRK",
                "returnDetailedErrors" => true,
                "returnLocalizedDateTime" => false
            ],
            "trackingInfoList" => [[
                "trackNumberInfo" => [
                    "trackingNumber" => $tracking_number,
                    "trackingQualifier" => "",
                    "trackingCarrier" => ""
                ]
            ]]
        ]

    ]),
    "action" => "trackpackages",
    "locale" => "en_US",
    "format" => "json",
    "version" => 99
];

$response = Requests::post($url, array(), $data);

$new_data = json_decode($response->body, true);

$fedex_status  = $new_data['TrackPackagesResponse']['packageList'][0]['keyStatus'];
$fedex_details = $new_data['TrackPackagesResponse']['packageList'][0]['statusWithDetails'];
$delivery_date = $new_data['TrackPackagesResponse']['packageList'][0]['displayActDeliveryDt'];
$delivery_time = $new_data['TrackPackagesResponse']['packageList'][0]['displayActDeliveryTm'];

echo $fedex_status . '|' . $delivery_date . '|' . $delivery_time;
  • Related