Mam następujący skrypt PHP, który doskonale działa w uzyskiwaniu dostępu do zdalnego reszty API. Ostatecznie daję mu zapytanie wzdłuż linii ?fromDate=2020-07-22 i generuje ostateczny adres URL, który zwraca XML na podstawie tej odpowiedzi. Moim problemem jest to, że próbowałem przekonwertować go do JavaScript, dzięki czemu mogę pracować w aplikacji w węźle (jestem nowy w JavaScript i nie znam niczego o jQuery !!). Nie mogę za mnie, że pracuje. Problem, w który wierzę, że leży z przekazaniem zapytania {X2}} 2020-07-22 do parametrów, które są wymagane do wygenerowania prawidłowego śladu, który należy dołączyć do ostatniego żądania API reszty, dzięki czemu może być prawidłowo uwierzytelniony.

Uwzględniłem oryginalny Pracujący skrypt PHP poniżej i moich wysiłków, aby odpowiednik JS. Pracowałem teraz przez wiele godzin, a mój mózg w końcu się poddał!

Czy ktoś może zobaczyć, gdzie idę źle?

<?php
$publicKey  = "insert public key here";
$privateKey = "insert private key here";
$url = 'https://www.api_endpoint.com/rest/1.0/reports?fromDate=2020-07-22';
$finalUrl = generateSignedUrl($url, $publicKey, $privateKey);
 
echo $finalUrl;
 
function generateSignedUrl($url, $publicKey, $privateKey) {
    $urlParts = parse_url($url);
    parse_str($urlParts['query'], $parameters);

    $parameters['myWebServiceID'] = $publicKey;
    $parameters['timeStamp'] = time();
    $parameters['footprint'] = generateFootPrint($privateKey, $parameters);
 
    return sprintf('%s://%s%s?%s', $urlParts['scheme'], $urlParts['host'], $urlParts['path'], http_build_query($parameters));
}
 
function generateFootPrint($privateKey, $parameters) {
    if (empty($parameters)) throw new InvalidArgumentException('Parameters cannot be null');
 
    $parameters["secretKey"] = $privateKey;
    unset($parameters["footprint"]);
    ksort($parameters);
    $queryString = http_build_query($parameters);
    return base64_encode(hash_hmac('sha1', $queryString, $privateKey, true));
}
?>

A oto moja wersja JS:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/core.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/hmac.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/sha1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/sha256.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/enc-base64.js"></script>
<script>
$( document ).ready(function() {

var url = 'https://www.api_endpoint.com/rest/1.0/reports?fromDate=2020-07-22'; //Where I append my query
var publicKey = 'insert public key here';
var secretKey = 'insert private key here';
var timestamp = Math.round(new Date().getTime()/1000);
      
var parametersToHmac = {
    "myWebServiceID": publicKey,
    "secretKey": secretKey,
    "timeStamp": timestamp,
    "fromDate": '2020-07-22' //Where I last attempted to insert the query manually
};

var stringParametersToHmac = jQuery.param(parametersToHmac);
var hash_hmac = CryptoJS.HmacSHA1(stringParametersToHmac, secretKey);
var base64 = hash_hmac.toString(CryptoJS.enc.Base64);
      
var finalResult = {
    "myWebServiceID": publicKey,
    "timeStamp": timestamp,
    "footprint": base64
};
      
var finalQueryParams = jQuery.param(finalResult);
var finalUrl = url + "?" + finalQueryParams;
console.log(finalUrl);

Próbowałem umieścić zapytanie ręcznie i różne próby analizowania go, ale zmagam się z koncepcją, w której należy wstawiać, aby upewnić się, że ślad zostanie wygenerowany prawidłowo, a zatem nie odrzucony przez punkt końcowy.

0
Hoppo 22 lipiec 2020, 17:01

1 odpowiedź

Najlepsza odpowiedź

Ok, to dość niesamowite, jak zadasz pytanie, pomaga wyjaśnić, co zrobiłeś źle. W skrypcie PHP w funkcji GenerateFootprint jest funkcja KSort, która sortuje klawisze alfabetycznie w obrębie PHP. Brakowało mi tego w moim tłumaczeniu na JavaScript.

Dlatego zmiana parametrów przekazywanych do HMAC:

var parametersToHmac = {
    "myWebServiceID": publicKey,
    "secretKey": secretKey,
    "timeStamp": timestamp,
    "fromDate": '2020-07-22' //move this from here
};

Do:

var parametersToHmac = {
    "fromDate": '2020-07-22', //to here!!
    "myWebServiceID": publicKey,
    "secretKey": secretKey,
    "timeStamp": timestamp
};

I.e. alfabetycznie według klawisza, zwraca identyczny ślad do skryptu PHP, a po skompilowaniu do reszty URL jest akceptowane przez punkt końcowy i zwraca potrzebne dane.

Dziękuję za słuchanie!

2
Hoppo 22 lipiec 2020, 14:49