skip to Main Content

I’m calling the API to get a list of shipments but I can’t seem to page through the results.

The API call is successful with only one query parameter but when I call it with two query parameters, I get the error “The signature is invalid. Verify and try again”. I’m including my test code below.

<?php
function sign($method, $url, $data, $consumerSecret, $tokenSecret)
{
    $url = urlEncodeAsZend($url);

    $data = urlEncodeAsZend(http_build_query($data, '', '&'));
    $data = implode('&', [$method, $url, $data]);

    $secret = implode('&', [$consumerSecret, $tokenSecret]);

    return base64_encode(hash_hmac('sha1', $data, $secret, true));
}

function urlEncodeAsZend($value)
{
    $encoded = rawurlencode($value);
    $encoded = str_replace('%7E', '~', $encoded);
    return $encoded;
}

// REPLACE WITH YOUR ACTUAL DATA OBTAINED WHILE CREATING NEW INTEGRATION
$consumerKey       = 'htj8ze6ntr0mz1s4hjxrqeicia8rxgt4';
$consumerSecret    = 'djjzdwfgbbr7ganlkv01qr6p3l7ptvfe';
$accessToken       = '60o0mfrvqnjvin7tjuqsv37arijrqe9e';
$accessTokenSecret = 'caq9wfdx99zaygwgbhw91i9imj89p4zb';

$method = 'GET';

/* test 1 PASS */
//$url = 'http://localhost/rest/V1/shipments/';
//$qs = ['searchCriteria'=>'all'];

/* test 2 PASS */
//$url = 'http://localhost/rest/V1/shipments/';
//$qs = ['searchCriteria[pageSize]'=>'10'];

/* test 3 FAIL "The signature is invalid. Verify and try again" */
$url = 'http://localhost/rest/V1/shipments/';
$qs = ['searchCriteria[pageSize]'=>'10', 'searchCriteria[currentPage]'=>'1'];

$data = [
    'oauth_consumer_key' => $consumerKey,
    'oauth_nonce' => md5(uniqid(rand(), true)),
    'oauth_signature_method' => 'HMAC-SHA1',
    'oauth_timestamp' => time(),
    'oauth_token' => $accessToken,
    'oauth_version' => '1.0',
];
$data = array_merge($data, $qs);

$data['oauth_signature'] = sign($method, $url, $data, $consumerSecret, $accessTokenSecret);

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_URL => $url .'?' .http_build_query($qs),
    CURLOPT_HTTPHEADER => [
        'Authorization: OAuth ' . http_build_query($data, '', ',')
    ]
]);

$result = curl_exec($curl);
curl_close($curl);
echo($result);

The code includes three tests.

If I uncomment test 1 and comment test 2 and 3, the code works properly and I get a list of shipments.

If I uncomment test 2 and comment test 1 and 3, the code works properly and I get a list of shipments.

If I run the code as is, I get the the message “The signature is invalid. Verify and try again.”

I’m running Magento ver. 2.3.2

2

Answers


  1. Chosen as BEST ANSWER

    The trick is to sort the parameters. I have some client code anyone is interested.

    <?php
    function sign($method, $url, $data, $consumerSecret, $tokenSecret)
    {
        $url = urlEncodeAsZend($url);
    
        $data = urlEncodeAsZend(http_build_query($data, '', '&'));
        $data = implode('&', [$method, $url, $data]);
    
        $secret = implode('&', [$consumerSecret, $tokenSecret]);
    
        return base64_encode(hash_hmac('sha1', $data, $secret, true));
    }
    
    function urlEncodeAsZend($value)
    {
        $encoded = rawurlencode($value);
        $encoded = str_replace('%7E', '~', $encoded);
        return $encoded;
    }
    
    function recursive_sort(&$array) {
        foreach ($array as &$value) {
            if (is_array($value)) recursive_sort($value);
        }
        return ksort($array);
    }
    
    // REPLACE WITH YOUR ACTUAL DATA OBTAINED WHILE CREATING NEW INTEGRATION
    $consumerKey       = 'htj8ze6ntr0mz1s4hjxrqeicia8rxgt4';
    $consumerSecret    = 'djjzdwfgbbr7ganlkv01qr6p3l7ptvfe';
    $accessToken       = '60o0mfrvqnjvin7tjuqsv37arijrqe9e';
    $accessTokenSecret = 'caq9wfdx99zaygwgbhw91i9imj89p4zb';
    
    $method = 'GET';
    
    /* test 1 PASS */
    //$url = 'http://localhost/rest/V1/shipments/';
    //$qs = ['searchCriteria'=>'all'];
    
    /* test 2 PASS */
    //$url = 'http://localhost/rest/V1/shipments/';
    //$qs = ['searchCriteria[pageSize]'=>'10'];
    
    /* test 3 FAIL "The signature is invalid. Verify and try again" */
    $url = 'http://localhost/rest/V1/shipments/';
    $qs = ['searchCriteria'=>['pageSize'=>10,'currentPage'=>1]];
    
    $data = [
        'oauth_consumer_key' => $consumerKey,
        'oauth_nonce' => md5(uniqid(rand(), true)),
        'oauth_signature_method' => 'HMAC-SHA1',
        'oauth_timestamp' => time(),
        'oauth_token' => $accessToken,
        'oauth_version' => '1.0',
    ];
    $data = array_merge($data, $qs);
    recursive_sort($data);
    
    $data['oauth_signature'] = sign($method, $url, $data, $consumerSecret, $accessTokenSecret);
    
    $curl = curl_init();
    
    curl_setopt_array($curl, [
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_URL => $url .'?' .http_build_query($qs),
        CURLOPT_HTTPHEADER => [
            'Authorization: OAuth ' . http_build_query($data, '', ',')
        ]
    ]);
    
    $result = curl_exec($curl);
    curl_close($curl);
    echo($result);
    

  2. Though this question is old, I want to post the answer for future cases.

    The code in the question is good, and it helped me a lot.

    It is needed to sort parameters by key. Also, please consider that the searchCriteria is a multidimensional array. So, the array must be sorted by key recursively.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search