C# Paypal REST api调用可以从cURL中工作,但不能从C代码中工作

C# Paypal REST api调用可以从cURL中工作,但不能从C代码中工作,c#,paypal,C#,Paypal,我正在尝试从代码中调用Paypal api。我设置了沙盒帐户,当我使用curl时它可以工作,但是我的代码不是以同样的方式工作的,而是返回401 下面是curl命令,如下所示 更新:显然,.Credentials不起作用,而是手动设置授权标题(请参见代码) 以下是代码(根据其本质进行了精简): 这是来自Fiddler捕获的代码(raw)的请求,由于某些原因,没有授权参数: POST https://api.sandbox.paypal.com/v1/oauth2/token HTTP/1.1 Ac

我正在尝试从代码中调用Paypal api。我设置了沙盒帐户,当我使用curl时它可以工作,但是我的代码不是以同样的方式工作的,而是返回401

下面是curl命令,如下所示

更新:显然,
.Credentials
不起作用,而是手动设置
授权
标题(请参见代码)

以下是代码(根据其本质进行了精简):

这是来自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

这项工作使用HttpClient。。。 “RequestT”是PayPal请求参数的泛型,但未使用。使用“响应集”,根据PayPal的文档,它是PayPal的响应

“PayPalConfig”类使用ConfigurationManager从web.config文件读取clientid和密码。 需要记住的是,将授权头设置为“基本”而不是“承载者”,并使用正确的媒体类型(x-www-form-urlencoded)正确构造“StringContent”对象

//获取PayPal accessToken
公共异步任务InvokePostAsync(请求请求,字符串actionUrl)
{
应答结果;
//“HTTP基本身份验证帖子”
字符串clientId=PayPalConfig.clientId;
string secret=PayPalConfig.clientSecret;
string oAuthCredentials=Convert.ToBase64String(Encoding.Default.GetBytes(clientId+“:”+secret));
//基于“productionMode”的PayPAl“live”或“stage”的基本uri
字符串uriString=PayPalConfig.endpoint(PayPalConfig.productionMode)+actionUrl;
HttpClient=新的HttpClient();
//构造请求消息
var h_request=newhttprequestmessage(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=new-StringContent(“授权类型=客户端凭据”,UTF8Encoding.UTF8,“应用程序/x-www-form-urlencoded”);
尝试
{
HttpResponseMessage response=等待客户端.SendAsync(h_请求);
//如果调用失败,则创建ErrorResponse…具有响应属性的简单类
如果(!response.issucessStatusCode)
{
var error=await response.Content.ReadAsStringAsync();
ErrorResponse errResp=JsonConvert.DeserializeObject(错误);
抛出新的PayPaleException{error_name=errResp.name,details=errResp.details,message=errResp.message};
}
var success=wait response.Content.ReadAsStringAsync();
结果=JsonConvert.DeserializeObject(成功);
}
捕获(例外)
{
抛出新的HttpRequestException(“对贝宝服务的请求失败”);
}
返回结果;
}
重要提示:使用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<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;
    }
//通过HttpClient调用获取访问令牌..并确保在继续之前有结果
//因此,您不会尝试传递空的或失败的令牌。
公共异步任务授权异步(令牌请求请求)
{
令牌响应;
尝试
{
var task=new PayPalHttpClient().invokepostatsync(req,req.actionUrl);
等待任务。WhenAll(任务);
响应=任务。结果;
}
捕获(PayPalException例外)
{
response=newtokenresponse{access_token=“error”,error=ex};
}
返回响应;
}

希望下面的代码能帮助那些仍在寻找一块好蛋糕来连接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<KeyValuePair<string, string>>
                            {
                                new KeyValuePair<string, string>("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<PayPalTokenModel>(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; }
}
公共类付费客户端
{
公共异步任务RequestPayPalToken()
{
//关于SSL安全通道的讨论
// http://stackoverflow.com/questions/32994464/could-not-create-ssl-tls-secure-channel-despite-setting-servercertificatevalida
ServicePointManager.ServerCertificateValidationCallback+=(发件人、证书、链、sslPolicyErrors)=>true;
ServicePointManager.SecurityProtocol=SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
尝试
{
//Paypal应用程序API的客户端ID
字符串APIClientId=“**”[您的\u API\u客户端\u Id]\u**”;
//你的Paypal应用程序API的密钥
字符串APISecret=“**”[your\u API\u secret]\u**”;
使用(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=新Uri(“https://api.sandbox.paypal.com/v1/oauth2/token“,乌里金。绝对);
client.DefaultRequestHeaders.IfModifiedSince=DateTime.UtcNow;
var requestParams=新列表
{
新的KeyValuePair(“授权类型”、“客户端凭据”)
};
var content=newformurlencodedcontent(requestParams);
var webresponse=wait client.PostAsync(url、内容);
var jsonString=wait webresponse.Content.ReadAsStringAsync();
//响应将使用Jsonconver反序列化
var payPalTokenModel=JsonConvert.DeserializeObject(jsonString);
}
}
catch(System.Exception-ex)
{
//TODO:日志连接
    //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;
    }
    // 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;
    }
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<KeyValuePair<string, string>>
                            {
                                new KeyValuePair<string, string>("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<PayPalTokenModel>(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; }
}
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        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<PayPalTokenModel>(authResponse.Content);