您必须了解 HTTP 请求的两个主要部分才能使其工作:
Headers 是 HTTP 请求的第一部分,包含有关请求的信息,如授权、内容长度、内容格式等。
第二部分是内容。这是您要传递给服务器的实际数据。内容可以以多种不同的方式格式化,并且您的标题应该通知服务器使用哪种类型的格式化。您的 sn-p 中引用的其中两种格式是:
- Form 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 - Bad Request,由无效的内容结构引起。或者它可能是由无效令牌解析引起的 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;
}