httpclient Отображает отрицательный ответ - PullRequest
0 голосов
/ 10 февраля 2020

Во-первых, функция, которая создает токен. Затем вызывает GetClient (реальный токен)

public static HttpClient GetClient(string token)
{
  HttpClient client = new HttpClient();
  HttpContent content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("ContentType", "application/json"), new KeyValuePair<string, string>("Authorization", "Bearer '" + token + "'") });
  var response = client.PostAsync(new Uri("https://api.sandbox.paypal.com/v2/checkout/orders"), content).Result;
  if (response.IsSuccessStatusCode)
  {
    var responseContent = response.Content;
    string responseString = responseContent.ReadAsStringAsync().Result;
  }
  return client;
}

Ошибка:

{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{Paypal-Debug-Id: 5341e7ff8a884
Cache-Control: no-store, must-revalidate, no-cache, max-age=0
Date: Mon, 10 Feb 2020 05:36:37 GMT
Content-Length: 244
Content-Type: application/json
}}

Что такое исправление для такой вещи ??

1 Ответ

3 голосов
/ 10 февраля 2020

Есть две основные части HTTP-запроса, которые вы должны понимать, чтобы сделать эту работу:

  • Заголовки
  • Содержимое

Заголовки - это первая часть HTTP-запроса, которая содержит информацию о запросе, такую ​​как авторизация, длина контента, формат контента и т. д. c.

Вторая часть - это контент. Это ваши фактические данные, которые вы хотите передать на сервер. Содержимое может быть отформатировано различными способами, и ваши заголовки должны сообщать серверу, какой тип форматирования используется. Два из этих форматов, на которые есть ссылки в вашем фрагменте:

  • Форма Url / Encoded - этот тип данных обычно используется с HTML формами. Когда у вас есть что-то вроде

<form>
    <input name="key1" value="value1"/>
    <input name="key2" value="value2"/>
</form>

эти данные формы кодируются как key1=value1&key2=value2.

  • Json - это то, что вы хотите использовать для вызова PayPal API, в основном это просто структура Json, добавляемая в качестве контента с соответствующими заголовками, информирующая сервер о том, что он должен анализировать контент как Json.

У вас возникли проблемы, поскольку вы связываете заголовки с контентом и Form / UrlEncoded и Json типы контента. FormUrlEncodedContent Конструктор ожидает список пар ключ / значение формы, а не заголовков, и когда вы передаете ему тип содержимого и авторизацию, эти пары ключ / значение рассматриваются как данные, а не заголовки. Именно здесь возникает ошибка 401, когда сервер ищет заголовок авторизации, а не пару ключ / значение в содержимом. Попробуйте что-то вроде этого:

public static HttpClient GetClient(string token)
{
    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

    var yourContent = new
    {
        key1 = "value1",
        key2 = "value2"
    };
    var jsonContent = JsonConvert.SerializeObject(yourContent);
    var content = new StringContent(jsonContent, Encoding.ASCII, "application/json");

    var response = client.PostAsync(new Uri("https://api.sandbox.paypal.com/v2/checkout/orders"), content).Result;
    if (response.IsSuccessStatusCode)
    {
        var responseContent = response.Content;
        string responseString = responseContent.ReadAsStringAsync().Result;
    }
    return client;
}

Прежде всего, я переместил аутентификацию с контента на заголовки. Вам просто нужно создать новую AuthenticationHeaderValue и передать "Bearer" в качестве схемы (я не искал ее, но из вашего кода я предполагаю, что API использовал Bearer схему аутентификации).

Далее кажется, что вы хотите использовать Json content-type. Таким образом, вы должны генерировать Json как контент. Я выполняю это, используя анонимный тип данных и передавая его в JsonConvert (вам понадобится пакет Newtonsoft. Json, если вы скопируете этот код, Visual Studio автоматически предложит вам установить этот пакет).

Наконец, чтобы добавьте Json контент для запроса, вы должны использовать StringContent и передать как сгенерированную Json строку, так и тип контента "application/json".

РЕДАКТИРОВАТЬ: протестировал ваш код, я полагаю, что ваша последняя ошибка больше не была 401, а точнее 400 - неверный запрос, вызванный неверной структурой содержимого. Или это могло быть 401 из-за неправильного разбора токена (возможно, длина ответа немного отличается?). В любом случае, обновленный код для правильного преобразования объектов туда и обратно в JSON.

public class TokenResponse
{
    [JsonProperty(PropertyName = "scope")]
    public string Scope { get; set; }

    [JsonProperty(PropertyName = "access_token")]
    public string AccessToken { get; set; }

    [JsonProperty(PropertyName = "token_type")]
    public string TokenType { get; set; }

    [JsonProperty(PropertyName = "app_id")]
    public string AppId { get; set; }

    [JsonProperty(PropertyName = "expires_in")]
    public int ExpiresIn { get; set; }

    [JsonProperty(PropertyName = "nonce")]
    public string Nonce { get; set; }
}

public class Amount
{
    [JsonProperty(PropertyName = "currency_code")]
    public string CurrencyCode { get; set; }

    [JsonProperty(PropertyName = "value")]
    public string Value { get; set; }
}

public class PurchaseUnit
{
    [JsonProperty(PropertyName = "amount")]
    public Amount Amount { get; set; }
}

public class OrdersRequest
{
    [JsonProperty(PropertyName = "intent")]
    public string Intent { get; set; }

    [JsonProperty(PropertyName = "purchase_units")]
    public PurchaseUnit[] PurchaseUnits { get; set; }
}

public static void CreateToken()
{
    var client = new HttpClient();
    byte[] authBytes = Encoding.ASCII.GetBytes("user:pass");
    string base64Auth = Convert.ToBase64String(authBytes);
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64Auth);

    var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("grant_type", "client_credentials") });
    var response = client.PostAsync(new Uri("https://api.sandbox.paypal.com/v1/oauth2/token"), content).Result;
    if (response.IsSuccessStatusCode)
    {
        var tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(response.Content.ReadAsStringAsync().Result);
        GetClient(tokenResponse.AccessToken);
    }
}

public static HttpClient GetClient(string token)
{
    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

    var request = new OrdersRequest
    {
        Intent = "CAPTURE",
        PurchaseUnits = new PurchaseUnit[] { new PurchaseUnit
            {
                Amount = new Amount
                {
                    CurrencyCode = "USD",
                    Value = "100.0"
                }
            }
        }
    };

    var jsonContent = JsonConvert.SerializeObject(request);
    var content = new StringContent(jsonContent, Encoding.ASCII, "application/json");

    var response = client.PostAsync(new Uri("https://api.sandbox.paypal.com/v2/checkout/orders"), content).Result;
    if (response.IsSuccessStatusCode)
    {
        var responseString = response.Content.ReadAsStringAsync().Result;
    }
    return client;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...