Есть две основные части 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;
}