贝宝REST API调用从卷曲的作品,但不是从C#代码 [英] Paypal REST api call works from cURL but not from C# code

查看:283
本文介绍了贝宝REST API调用从卷曲的作品,但不是从C#代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从我的代码调用API贝宝。我成立了沙盒帐户和它的作品,当我用卷曲,但我的代码是不工作以同样的方式,返回401未授权来代替。



下面的curl命令为< A HREF =https://developer.paypal.com/webapps/developer/docs/integration/direct/make-your-first-call/相对=nofollow>贝宝记录

 卷曲https://api.sandbox.paypal.com/v1/oauth2/token -H接受:应用/ JSON-H接受语言:EN_US-UA ****:电子****-dgrant_type = client_credentials

更新:显然, .Credentials 不会做的伎俩,而不是设置授权头手动工作(见代码)



下面的代码(修剪到它的本质):

  HttpWebRequest的要求=(HttpWebRequest的)HttpWebRequest.Create(https://api.sandbox.paypal.com/v1/oauth2/token); 
request.Method =POST;
request.Accept =应用/ JSON;
request.Headers.Add(接受语言:EN_US)

//这不起作用:
** request.Credentials =新的NetworkCredential(A * ***,E ****); **

//而是执行此操作
**串AUTHINFO = Convert.ToBase64String(System.Text.Encoding.Default。 GetBytes会(A ****:电子****)); **
** request.Headers [授权] =基本+ AUTHINFO **

按(SWT的StreamWriter =新的StreamWriter(request.GetRequestStream()))
{
swt.Write(grant_type = client_credentials);
}

request.BeginGetResponse((R)=>
{
尝试
{
HttpWebResponse响应= request.EndGetResponse(R )作为HttpWebResponse; //这里的异常
....
}赶上(例外X){...} //记录异常 - 401未授权
},NULL);

这是从代码由小提琴手(生),也有出于某种原因没有授权参数捕获的请求

  POST https://api.sandbox.paypal.com/v1/oauth2/token HTTP / 1.1 
接受:应用/ JSON
接受语言:EN_US
主机:api.sandbox.paypal.com
的Content-Length:29
期望:100-继续
连接:保持活动

grant_type = client_credentials


解决方案

本作品使用的HttpClient ...
'RequestT'是一个通用的贝宝的请求参数,但不使用它。在'ResponseT'被使用,它是根据其文档来自PayPal的响应。



PayPalConfig'类读取使用ConfigurationManager中web.config文件中的clientid和秘密。
要记住的事情是设置授权头基本NOT旗手,如果并妥善构建具有正确的介质类型(X WWW的窗体-urlencoded)了的StringContent'对象。

  //获得贝宝的accessToken 
公共异步任务< ResponseT> InvokePostAsync< RequestT,ResponseT>(RequestT请求字符串actionUrl)
{
ResponseT结果;

//'HTTP基本认证后'< HTTP://stackoverflow.com/questions/21066622/how-to-send-a-http-basic-auth-post>
串的clientId = PayPalConfig.clientId;
串秘密= PayPalConfig.clientSecret;
串oAuthCredentials = Convert.ToBase64String(Encoding.Default.GetBytes(的clientId +:+秘密));

//基URI基于productionMode'
串uriString中= PayPalConfig.endpoint(PayPalConfig.productionMode)+ actionUrl贝宝现场或舞台;

HttpClient的客户端=新的HttpClient();

//构造请求消息
变种h_request =新HttpRequestMessage(HttpMethod.Post,uriString中);
h_request.Headers.Authorization =新AuthenticationHeaderValue(基本,oAuthCredentials);
h_request.Headers.Accept.Add(新MediaTypeWithQualityHeaderValue(应用/ JSON));
h_request.Headers.AcceptLanguage.Add(新StringWithQualityHeaderValue(EN_US));

h_request.Content =新的StringContent(grant_type = client_credentials,UTF8Encoding.UTF8,应用程序/ x-WWW的形式,进行了urlencoded);


{
HttpResponseMessage响应=等待client.SendAsync(h_request);

//如果调用失败ErrorResponse创建...与反应特性的简单类
如果(!response.IsSuccessStatusCode)
{
VAR误差=等待response.Content .ReadAsStringAsync();
ErrorResponse errResp = JsonConvert.DeserializeObject< ErrorResponse>(错误);
抛出新PayPalException {ERROR_NAME = errResp.name,细节= errResp.details,消息= errResp.message};
}

VAR成功=等待response.Content.ReadAsStringAsync();
结果= JsonConvert.DeserializeObject< ResponseT>(成功);
}
赶上(例外)
{
抛出新HttpRequestException(请求到PayPal服务失败。);
}

返回结果;
}



重要提示:使用Task.WhenAll(),以确保您有一个结果

  //获得访问令牌与HttpClient的call..and确保有持续前
A结果//所以你不T试图通过一个空的或失败的标记。
公共异步任务< TokenResponse> AuthorizeAsync(TokenRequest REQ)
{
TokenResponse响应;

{
变种任务=新PayPalHttpClient()InvokePostAsync< TokenRequest,TokenResponse>(REQ,req.actionUrl);
等待Task.WhenAll(任务);

响应= task.Result;
}
赶上(PayPalException前)
{
响应=新TokenResponse {ACCESS_TOKEN =错误,错误=前};
}

返回响应;
}


I'm trying to call Paypal api from my code. I set up the sandbox account and it works when I use curl but my code isn't working the same way, returning 401 Unauthorized instead.

Here's the curl command as documented by Paypal

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" 

UPDATE: Apparently the .Credentials doesn't do the trick, instead setting Authorization header manually works (see code)

Here's the code (trimmed to its essence):

  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);

This is the request from code captured by Fiddler (raw), there are no authorization parameters for some reason:

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

解决方案

This Works using HttpClient... 'RequestT' is a generic for the PayPal request arguments, however it is not used. The 'ResponseT' is used and it is the response from PayPal according to their documentation.

'PayPalConfig' class reads the clientid and secret from the web.config file using ConfigurationManager. The thing to remember is to set the Authorization header to "Basic" NOT "Bearer" and if and to properly construct the 'StringContent' object with right media type (x-www-form-urlencoded).

    //gets PayPal accessToken
    public async Task<ResponseT> InvokePostAsync<RequestT, ResponseT>(RequestT request, string actionUrl)
    {
        ResponseT result;

        // 'HTTP Basic Auth Post' <http://stackoverflow.com/questions/21066622/how-to-send-a-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<ErrorResponse>(error);
                throw new PayPalException { error_name = errResp.name, details = errResp.details, message = errResp.message };
            }

            var success = await response.Content.ReadAsStringAsync();
            result = JsonConvert.DeserializeObject<ResponseT>(success);
        }
        catch (Exception)
        {
            throw new HttpRequestException("Request to PayPal Service failed.");
        }

        return result;
    }

IMPORTANT: use Task.WhenAll() to ensure you have a result.

    // 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<TokenResponse> AuthorizeAsync(TokenRequest req)
    {
        TokenResponse response;
        try
        {
            var task = new PayPalHttpClient().InvokePostAsync<TokenRequest, TokenResponse>(req, req.actionUrl);
            await Task.WhenAll(task);

            response = task.Result;
        }
        catch (PayPalException ex)
        {
            response = new TokenResponse { access_token = "error", Error = ex };
        }

        return response;
    }

这篇关于贝宝REST API调用从卷曲的作品,但不是从C#代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆