Paypal REST api调用来自cURL,但不适用于C#代码

我试图从我的代码中调用Paypal api。 我设置了沙箱帐户,当我使用curl但它的代码工作方式不同时,它会起作用,返回401 Unauthorized。

这是Paypal记录的curl命令

curl https://api.sandbox.paypal.com/v1/oauth2/token -H "Accept: application/json" -H "Accept-Language: en_US" -u "A****:E****" -d "grant_type=client_credentials" 

更新:显然.Credentials问题,而是手动设置Authorization标头(参见代码)

这是代码(修剪到它的本质):

  HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://api.sandbox.paypal.com/v1/oauth2/token"); request.Method = "POST"; request.Accept = "application/json"; request.Headers.Add("Accept-Language:en_US") // this doesn't work: **request.Credentials = new NetworkCredential("A****", "E****");** // DO THIS INSTEAD **string authInfo = Convert.ToBase64String(System.Text.Encoding.Default.GetBytes("A****:E****"));** **request.Headers["Authorization"] = "Basic " + authInfo;** using (StreamWriter swt = new StreamWriter(request.GetRequestStream())) { swt.Write("grant_type=client_credentials"); } request.BeginGetResponse((r) => { try { HttpWebResponse response = request.EndGetResponse(r) as HttpWebResponse; // Exception here .... } catch (Exception x) { .... } // log the exception - 401 Unauthorized }, null); 

这是Fiddler(raw)捕获的代码的请求,由于某种原因没有授权参数:

 POST https://api.sandbox.paypal.com/v1/oauth2/token HTTP/1.1 Accept: application/json Accept-Language: en_US Host: api.sandbox.paypal.com Content-Length: 29 Expect: 100-continue Connection: Keep-Alive grant_type=client_credentials 

希望以下代码能帮助那些仍在寻找好蛋糕以便与PayPal连接的人。

和很多人一样,我花了很多时间试图让我的PayPal令牌访问失败,直到找到以下内容:

 public class PayPalClient { public async Task RequestPayPalToken() { // Discussion about SSL secure channel // http://stackoverflow.com/questions/32994464/could-not-create-ssl-tls-secure-channel-despite-setting-servercertificatevalida ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; try { // ClientId of your Paypal app API string APIClientId = "**_[your_API_Client_Id]_**"; // secret key of you Paypal app API string APISecret = "**_[your_API_secret]_**"; using (var client = new System.Net.Http.HttpClient()) { var byteArray = Encoding.UTF8.GetBytes(APIClientId + ":" + APISecret); client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)); var url = new Uri("https://api.sandbox.paypal.com/v1/oauth2/token", UriKind.Absolute); client.DefaultRequestHeaders.IfModifiedSince = DateTime.UtcNow; var requestParams = new List> { new KeyValuePair("grant_type", "client_credentials") }; var content = new FormUrlEncodedContent(requestParams); var webresponse = await client.PostAsync(url, content); var jsonString = await webresponse.Content.ReadAsStringAsync(); // response will deserialized using Jsonconver var payPalTokenModel = JsonConvert.DeserializeObject(jsonString); } } catch (System.Exception ex) { //TODO: Log connection error } } } public class PayPalTokenModel { public string scope { get; set; } public string nonce { get; set; } public string access_token { get; set; } public string token_type { get; set; } public string app_id { get; set; } public int expires_in { get; set; } } 

这段代码对我很有用,也希望你也能。 这些学分属于Patel Harshal,他在这里发布了他的解决方案。

这个使用HttpClient的工作……’RequestT’是PayPal请求参数的通用,但它没有被使用。 使用’ResponseT’,它是PayPal根据其文档的响应。

‘PayPalConfig’类使用ConfigurationManager从web.config文件中读取clientid和secret。 要记住的是将Authorization标头设置为“Basic”NOT“Bearer”,以及是否正确构造具有正确媒体类型的“StringContent”对象(x-www-form-urlencoded)。

  //gets PayPal accessToken public async Task InvokePostAsync(RequestT request, string actionUrl) { ResponseT result; // 'HTTP Basic Auth Post'  string clientId = PayPalConfig.clientId; string secret = PayPalConfig.clientSecret; string oAuthCredentials = Convert.ToBase64String(Encoding.Default.GetBytes(clientId + ":" + secret)); //base uri to PayPAl 'live' or 'stage' based on 'productionMode' string uriString = PayPalConfig.endpoint(PayPalConfig.productionMode) + actionUrl; HttpClient client = new HttpClient(); //construct request message var h_request = new HttpRequestMessage(HttpMethod.Post, uriString); h_request.Headers.Authorization = new AuthenticationHeaderValue("Basic", oAuthCredentials); h_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); h_request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue("en_US")); h_request.Content = new StringContent("grant_type=client_credentials", UTF8Encoding.UTF8, "application/x-www-form-urlencoded"); try { HttpResponseMessage response = await client.SendAsync(h_request); //if call failed ErrorResponse created...simple class with response properties if (!response.IsSuccessStatusCode) { var error = await response.Content.ReadAsStringAsync(); ErrorResponse errResp = JsonConvert.DeserializeObject(error); throw new PayPalException { error_name = errResp.name, details = errResp.details, message = errResp.message }; } var success = await response.Content.ReadAsStringAsync(); result = JsonConvert.DeserializeObject(success); } catch (Exception) { throw new HttpRequestException("Request to PayPal Service failed."); } return result; } 

重要信息:使用Task.WhenAll()确保您有结果。

  // gets access token with HttpClient call..and ensures there is a Result before continuing // so you don't try to pass an empty or failed token. public async Task AuthorizeAsync(TokenRequest req) { TokenResponse response; try { var task = new PayPalHttpClient().InvokePostAsync(req, req.actionUrl); await Task.WhenAll(task); response = task.Result; } catch (PayPalException ex) { response = new TokenResponse { access_token = "error", Error = ex }; } return response; } 

Paypal已经弃用了TLS 1.1,现在只接受1.2。 不幸的是,.NET(版本4.7之前)默认使用1.1,除非你另外配置它​​。

您可以使用此行打开TLS 1.2。 我建议将它放在Application_Startglobal.asax

 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 

我也缺乏示例代码以及响应错误和代码的各种问题。

我是RestClient的忠实粉丝,因为它对集成和越来越多的RESTful API调用有很大帮助。

我希望使用RestSharp的这小段代码可以帮助某人: –

  if (ServicePointManager.SecurityProtocol != SecurityProtocolType.Tls12) ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // forced to modern day SSL protocols var client = new RestClient(payPalUrl) { Encoding = Encoding.UTF8 }; var authRequest = new RestRequest("oauth2/token", Method.POST) {RequestFormat = DataFormat.Json}; client.Authenticator = new HttpBasicAuthenticator(clientId, secret); authRequest.AddParameter("grant_type","client_credentials"); var authResponse = client.Execute(authRequest); // You can now deserialise the response to get the token as per the answer from @ryuzaki var payPalTokenModel = JsonConvert.DeserializeObject(authResponse.Content);