C# RestClient вызов magento api возвращает 401 подпись недействительной - PullRequest
1 голос
/ 18 февраля 2020

Я пытаюсь вызвать определенную c конечную точку на magento из c# RestClient, но безуспешно. Звонок начинается здесь:

private void SendDeletedProduct(string itemCode)
    {
        string consumerKey = "....."; 
        string consumerSecret = ".....";
        string tokenSecret = ".....";
        string tokenValue = ".....";
        string url = string.Format("http://.........:8090/api/rest/pylon/{0}", itemCode);

        var client = new RestClient(url);
        client.Timeout = -1;
        var request = new RestRequest(Method.PUT);
        request.AddHeader("Content-Type", "application/json");
        request.AddHeader("Authorization", GetHeader("DELETE", consumerKey, consumerSecret, tokenSecret, tokenValue, url));

        IRestResponse response = client.Execute(request);
        if (response.StatusCode != HttpStatusCode.OK)
        {
            LogError(response, string.Empty, itemCode, "Product", "DELETE");
        }
    }

и здесь генерируется заголовок:

private string GetHeader(string method, string cKey, string cSecret, string tSecret, string tValue, string apiUrl)
    {
        Dictionary<string, string> oauthD = new Dictionary<string, string>();
        oauthD.Add("consumerKey", cKey);
        oauthD.Add("consumerSecret", cSecret);
        oauthD.Add("tokenSecret", tSecret);
        oauthD.Add("tokenValue", tValue);
        oauthD.Add("url", apiUrl.Replace(":8090", string.Empty));

        var timeStamp = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
        var nonce = Convert.ToBase64String(Encoding.UTF8.GetBytes(timeStamp));

        var signatureBaseString = HttpUtility.UrlEncode(method + "&");
        signatureBaseString += HttpUtility.UrlEncode(oauthD["url"] + "&");
        signatureBaseString += HttpUtility.UrlEncode(
                "oauth_consumer_key=" + oauthD["consumerKey"] + "&" +
                "oauth_nonce=" + nonce + "&" +
                "oauth_signature_method=HMAC-SHA1" + "&" +
                "oauth_timestamp=" + timeStamp + "&" +
                "oauth_token=" + oauthD["tokenValue"] + "&" +
                "oauth_version=1.0");

        var key = HttpUtility.UrlEncode(oauthD["consumerSecret"] + "&" + oauthD["tokenSecret"]);

        var signatureEncoding = new ASCIIEncoding();
        var keyBytes = signatureEncoding.GetBytes(key);
        var signatureBaseBytes = signatureEncoding.GetBytes(signatureBaseString);
        string signatureString;// = HMACSHA1(key, signatureBaseString);
        using (var hmacsha1 = new HMACSHA1(keyBytes))
        {
            var hashBytes = hmacsha1.ComputeHash(signatureBaseBytes);
            signatureString = Convert.ToBase64String(hashBytes);
        }

        signatureString = HttpUtility.UrlEncode(signatureString);


        string SimpleQuote(string s) => '"' + s + '"';
        string header =             
            "oAuth oauth_consumer_key=" + SimpleQuote(oauthD["consumerKey"]) + "," +
            "oauth_nonce=" + SimpleQuote(nonce) + "," +
            "oauth_signature_method=" + SimpleQuote("HMAC-SHA1") + "," +
            "oauth_timestamp=" + SimpleQuote(timeStamp) + "," +
            "oauth_token=" + SimpleQuote(oauthD["tokenValue"]) + "," +
            "oauth_version=" + SimpleQuote("1.0") + "," +
            "oauth_signature= " + SimpleQuote(signatureString);

        return header;
    }

Читая в Интернете и magento docs, я нашел много возможных ответов, но мне не удалось чтобы получить API ответить 200 ок. Я попытался удалить порт из URL-адреса, изменив порядок параметров в строке подписи на алфавитный, попробовал кодирование urlen с символом «&» и оставив «&» вне urlencode. Вызов api напрямую от почтальона работает нормально, кстати. Поэтому я полагаю, что у меня что-то не так в том, как я делаю свою подпись Любая помощь будет оценена.

Заранее спасибо!

1 Ответ

0 голосов
/ 21 февраля 2020

Ошибка была в пути, когда я подготовил строку и ключ для хеширования. Я нашел множество шагов, предложенных разными людьми, и в итоге я все перепутал и доставил мне проблемы. В конце концов я наткнулся на этот сайт , который прояснил ситуацию и помог мне положить конец моим страданиям. Для any1 в моей ситуации конечный рабочий код:

private string GetHeader(string method, string cKey, string cSecret, string tSecret, string tValue, string apiUrl)
{
    Dictionary<string, string> oauthD = new Dictionary<string, string>();
    oauthD.Add("consumerKey", cKey);
    oauthD.Add("consumerSecret", cSecret);
    oauthD.Add("tokenSecret", tSecret);
    oauthD.Add("tokenValue", tValue);
    oauthD.Add("url", apiUrl);

    var timeStamp =  ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
    var nonce = Convert.ToBase64String(Encoding.UTF8.GetBytes(timeStamp));


    string[] lexOrdering = new string[6];

    lexOrdering[0] = UpperCaseUrlEncode("oauth_consumer_key=" + oauthD["consumerKey"]);
    lexOrdering[1] = UpperCaseUrlEncode("oauth_version=1.0");
    lexOrdering[2] = UpperCaseUrlEncode("oauth_timestamp=" + timeStamp);
    lexOrdering[3] = UpperCaseUrlEncode("oauth_signature_method=HMAC-SHA1");
    lexOrdering[4] = UpperCaseUrlEncode("oauth_token=" + oauthD["tokenValue"]);
    lexOrdering[5] = UpperCaseUrlEncode("oauth_nonce=" + UpperCaseUrlEncode(nonce));

    string orderedString = LexicographicalOrder(lexOrdering);
    var key1 = Encoding.Default.GetBytes(oauthD["consumerSecret"]);
    var key2 = Encoding.Default.GetBytes(oauthD["tokenSecret"]);
    var key = UpperCaseUrlEncode(Encoding.UTF8.GetString(key1)) + "&" + UpperCaseUrlEncode(Encoding.UTF8.GetString(key2));

    string signatureString = Hash(key, method.ToUpper() + "&" + UpperCaseUrlEncode(oauthD["url"]) + "&" + orderedString);

    signatureString = UpperCaseUrlEncode(signatureString);     
    string header =
        "OAuth oauth_consumer_key=\"" + oauthD["consumerKey"] + "\"," +
        "oauth_token=\"" + oauthD["tokenValue"] + "\"," +
        "oauth_signature_method=\"HMAC-SHA1\"," +
        "oauth_timestamp=\"" + timeStamp + "\"," +
        "oauth_nonce=\"" + UpperCaseUrlEncode(nonce) + "\"," +
        "oauth_version=\"1.0\"," +
        "oauth_signature=\"" + signatureString + "\"";

    return header;
}

private string Hash(string Key, string Data)
{
    Byte[] secretBytes = UTF8Encoding.UTF8.GetBytes(Key);
    HMACSHA1 hmac = new HMACSHA1(secretBytes);

    Byte[] dataBytes = UTF8Encoding.UTF8.GetBytes(Data);
    Byte[] calcHash = hmac.ComputeHash(dataBytes);
    String calcHashString = Convert.ToBase64String(calcHash);
    return calcHashString;
}

private string UpperCaseUrlEncode(string s)
{
    char[] temp = HttpUtility.UrlEncode(s).ToCharArray();
    for (int i = 0; i < temp.Length - 2; i++)
    {
        if (temp[i] == '%')
        {
            temp[i + 1] = char.ToUpper(temp[i + 1]);
            temp[i + 2] = char.ToUpper(temp[i + 2]);
        }
    }
    return new string(temp).Normalize();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...