8

コードから 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
4

4 に答える 4

3

Paypal は TLS 1.1 を廃止し、現在は 1.2 のみを受け入れています。残念ながら、.NET (バージョン 4.7 より前) は、特に設定しない限り、デフォルトで 1.1 を使用します。

この行で TLS 1.2 をオンにすることができます。Application_Startまたはに配置することをお勧めしglobal.asaxます。

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
于 2016-11-01T17:23:56.207 に答える
3

これは HttpClient を使用して動作します... 'RequestT' は PayPal 要求引数のジェネリックですが、使用されません。「ResponseT」が使用されます。これは、PayPal のドキュメントによると、PayPal からの応答です。

「PayPalConfig」クラスは、ConfigurationManager を使用して web.config ファイルから clientid とシークレットを読み取ります。覚えておくべきことは、Authorization ヘッダーを「Bearer」ではなく「Basic」に設定し、適切なメディア タイプ (x-www-form-urlencoded) で「StringContent」オブジェクトを適切に構築することです。

    //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;
    }

重要: 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;
    }
于 2014-01-30T06:51:28.247 に答える