PHP FedEx API oAuth2 Error 422 INVALID.INPUT.EXCEPTION

290 Views Asked by At

FedEx is going to migrate to oAuth2 API for their Web Services in 2024 and I'm trying to change our shipping library to work with it. I was able to Authenticate - which is great and getting bearer token. Now I'm trying to get Rates and Transit Times. I'm using PHP. This is my script for the API call:

    $token = $this->get_token();

    $headers = [
        'Content-Type: application/json',
        'Authorization: Bearer '.$token,
        'X-locale: en_US'
    ];

    $url = "https://apis.fedex.com/rate/v1/rates/quotes";

    $payload = [];

    $payload["accountNumber"] = [
         "value" => "XXXXXXXXX"
    ];

    $payload["requestedShipment"] = [];
    $payload["requestedShipment"]["shipper"]["address"] = [
        "postalCode"    => "L4Z1X3",
        "countryCode"   => "CA"
    ];

    $payload["requestedShipment"]["recipient"]["address"] = [
        "postalCode"    => "V1Y5E1",
        "countryCode"   => "CA"
    ];

    $payload["requestedShipment"]["pickupType"] = "CONTACT_FEDEX_TO_SCHEDULE";

    $payload["requestedShipment"]["requestedPackageLineItems"][0] = [
        "weight" => [
            "units" => "KG",
            "value" => "10"
        ]
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);

    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // Added this on local system to avoid SSL error
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // Added this on local system to avoid SSL error
    curl_setopt($ch, CURLOPT_ENCODING, "gzip"); // Added this to decode the response

    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    $output         =   curl_exec($ch);
    $http_status    =   curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $content_type   =   curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
    $curlerr        =   curl_error($ch);
    curl_close($ch);

    // TO DEBUG OUTPUT
    echo "OUTPUT: ".$output."<br><br>";
    echo "HTTP STATUS: ".$http_status."<br><br>";
    echo "CONTENT TYPE: ".$content_type."<br><br>";
    echo "ERROR: ".$curlerr."<br><br>";

The response that I'm getting:

OUTPUT: {"transactionId":"874d6e61-d390-4410-a949-76d11e2ae67a","errors":[{"code":"INVALID.INPUT.EXCEPTION","message":"Invalid field value in the input"}]}

HTTP STATUS: 422

CONTENT TYPE: application/json

ERROR:

I have a feeling that my JSON formatting may not be correct or missing something. I tried addslashes(json_encode($payload)) - it returns the same thing. I checked curl documentation for maybe any option that I'm missing - can't see what I can add to make it work.

Any suggestions are appreciated.

1

There are 1 best solutions below

0
cjrb On

So, after trial and error I figured out the solution for my problem. If anybody faces the same issue this is what worked for me:

  1. Adding headers 'Pragma: no-cache' and 'Cache-Control: no-cache, no-store' to curl request.
  2. Adding rateRequestType to the JSON schema for the request.

Below is the working code. My development environment is on Windows 11 (WAMP).

    $token = $this->get_token();

    $headers = [
        'Content-Type: application/json',
        'Accept: application/json',
        'Authorization: Bearer '.$token,
        'X-locale: en_US',
        'Pragma: no-cache',
        'Cache-Control: no-cache, no-store'
    ];

    $url = "https://apis.fedex.com/rate/v1/rates/quotes";

    $payload["accountNumber"] = [
        "value" => "XXXXXXXX"
    ];

    $payload["rateRequestControlParameters"]["returnTransitTimes"] = true;

    $payload["requestedShipment"] = [];

    $payload["requestedShipment"]["shipper"]["address"] = [
        "postalCode"    => "L4Z1X3",
        "countryCode"   => "CA"
    ];

    $payload["requestedShipment"]["recipient"]["address"] = [
        "postalCode"    => "V2A5E1",
        "countryCode"   => "CA"
    ];

    $payload["requestedShipment"]["pickupType"] = "CONTACT_FEDEX_TO_SCHEDULE";

    $payload["requestedShipment"]["requestedPackageLineItems"][0] = [
        "weight" => [
            "units" => "KG",
            "value" => 10
        ]
    ];

    $payload["requestedShipment"]["rateRequestType"] = ["ACCOUNT"];
    $payload["requestedShipment"]["shipDateStamp"] = "2023-08-18";      

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);

    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // Added this on local system to avoid SSL error
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // Added this on local system to avoid SSL error
    curl_setopt($ch, CURLOPT_ENCODING, "gzip"); // Added this to decode the response
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");

    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    curl_setopt($ch, CURLINFO_HEADER_OUT, true);

    $output         =   curl_exec($ch);
    $http_status    =   curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $content_type   =   curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
    $curlerr        =   curl_error($ch);
    $header_out     =   curl_getinfo($ch);
    curl_close($ch);

    // TO DEBUG OUTPUT
    echo "OUTPUT: ".$output."<br><br>";
    echo "HTTP STATUS: ".$http_status."<br><br>";
    echo "CONTENT TYPE: ".$content_type."<br><br>";
    echo "ERROR: ".$curlerr."<br><br>";