贝宝REST API -沙箱返回401的API请求但成功的访问令牌。

时间:2022-10-14 16:32:23

I am using the PayPal REST API in Java to make a request to the testing (sandbox) servers for an access token, which succeeds, and then sending that access token back to the same sandbox servers for a Payment which fails with a 401 Not Authorized.

我正在使用Java的贝宝REST API向测试(沙箱)服务器请求访问令牌,该访问令牌成功,然后将该访问令牌发送回相同的沙箱服务器,以支付未授权的401。

I followed the PayPal REST API instructions found here: https://developer.paypal.com/webapps/developer/docs/api/#authentication--headers and here https://developer.paypal.com/webapps/developer/docs/integration/direct/make-your-first-call/

我遵循PayPal REST API的指示,在这里找到了:https://developer.paypal.com/webapps/developer/docs/api/#认证——header和这里https://developer.paypal.com/webapps/developer/docs/integration/direct/your-firstcall/。

I tried using the OAuthTokenCredential object to provide my clientId and clientSecret but it only returns me the access token, not the appID provided by PayPal nor the expiresIn time in minutes. In addition, it complains about a missing sdk_conf.properties file in my classpath.

我尝试使用OAuthTokenCredential对象来提供我的clientId和clientSecret,但它只返回访问令牌,而不是贝宝提供的appID,以及分钟内的过期时间。此外,它还抱怨缺少sdk_conf。类路径中的属性文件。

I then created my own class to make the call using Apache's HttpClient to get the full response and that works:

然后,我创建了自己的类,以使用Apache的HttpClient进行调用,以获得完整的响应,这是可行的:

Custom PayPalAPI interface for RestEasy

@Path("v1/oauth2/token")
public interface PayPalOAuthAPI {
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public OAuthInfo requestAccessToken(
        @HeaderParam("Authorization") String basicEncodedToken, 
        String requestBody
    );
}

Custom OAuth token request

private OAuthInfo getOAuthInfo() {
    OAuthInfo info = null;

    PayPalOAuthAPI client = HttpClientFactory.createRestEasyClient(80, 443, 120, 2,
                                          API_ENDPOINT, PayPalOAuthAPI.class, true);
    info = client.requestAccessToken("Basic "+
                                    generateBase64String(PP_API_USER, PP_API_SECRET),
                                    "grant_type=client_credentials");

    if (info == null) {
        throw new RuntimeException(APIResultCodes.REMOTE_UNAUTHORIZED, 
                                   "Could not authenticate with PayPal.");
    }
    return info;
}

This all works correctly and returns me a 200 OK status with the expected JSON response including an access token.

这一切正常工作,并以预期的JSON响应(包括访问令牌)返回200 OK状态。

I then take that token and provide it to my Payment object which uses PayPal's code to communicate with their servers (under the hood I believe it's basic java.lang.net.HttpConnection code) and that returns a 401 Unauthorized.

然后,我将这个令牌并提供给我的支付对象,它使用贝宝的代码与他们的服务器通信(在这个框架下,我相信它是基本的java.lang.net.HttpConnection代码),并返回一个401未经授权的。

Payment call using PayPal's REST API

// get a new token
String accessToken = getOAuthInfo().getAccessToken();

// configProps is a Properties object pre-populated with sdk_conf.properties
// values except service.EndPoint, clientID, and clientSecret
configProps.setProperty("service.EndPoint", API_ENDPOINT);

// ... transaction objects omitted

try {
    Payment payment = new Payment();
    Payment.initConfig(configProps);
    payment.setIntent(Intent.sale.toString());
    payment.setPayer(payer);
    payment.setTransactions(transactions);

    Payment createdPayment = payment.create(accessToken);
} catch (PayPalRESTException ex) {
    LOG.error("Failed to submit donation", ex);
}

Log output

(including HttpClient request/response with IDs redacted)

(包括使用IDs编辑的HttpClient请求/响应)

2013-08-19 16:34:11,077 [qtp1005310362-44] DEBUG:org.apache.http.impl.conn.DefaultClientConnection Sending request: POST /v1/oauth2/token HTTP/1.1
2013-08-19 16:34:11,077 [qtp1005310362-44] DEBUG:org.apache.http.wire >> "POST /v1/oauth2/token HTTP/1.1[\r][\n]"
2013-08-19 16:34:11,077 [qtp1005310362-44] DEBUG:org.apache.http.wire >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"
2013-08-19 16:34:11,077 [qtp1005310362-44] DEBUG:org.apache.http.wire >> "Accept: application/json[\r][\n]"
2013-08-19 16:34:11,077 [qtp1005310362-44] DEBUG:org.apache.http.wire >> "Authorization: Basic QWM1UmNoQ3g3dHB1bWZSZW9rcUR3MW41bHRXaktQU0xRODIyWUJWWXpEdXpZUGJuc0J0eDZYWGlqX1pROkVJVnQ5eERmM2JnQmw1OG5KYlZ2VmtSR3JCaVZVN1BIWGtSV01mQjVqb3NxRTNkbWxCcF9TV05BdU91eA==[\r][\n]"
2013-08-19 16:34:11,077 [qtp1005310362-44] DEBUG:org.apache.http.wire >> "Accept-Encoding: gzip, deflate[\r][\n]"
2013-08-19 16:34:11,077 [qtp1005310362-44] DEBUG:org.apache.http.wire >> "Content-Length: 29[\r][\n]"
2013-08-19 16:34:11,077 [qtp1005310362-44] DEBUG:org.apache.http.wire >> "Host: api.sandbox.paypal.com[\r][\n]"
2013-08-19 16:34:11,077 [qtp1005310362-44] DEBUG:org.apache.http.wire >> "Connection: Keep-Alive[\r][\n]"
2013-08-19 16:34:11,077 [qtp1005310362-44] DEBUG:org.apache.http.wire >> "User-Agent: Apache-HttpClient/4.2 (java 1.5)[\r][\n]"
2013-08-19 16:34:11,078 [qtp1005310362-44] DEBUG:org.apache.http.wire >> "[\r][\n]"
2013-08-19 16:34:11,078 [qtp1005310362-44] DEBUG:org.apache.http.wire >> "grant_type=client_credentials"
2013-08-19 16:34:12,690 [qtp1005310362-44] DEBUG:org.apache.http.wire << "HTTP/1.1 200 OK[\r][\n]"
2013-08-19 16:34:12,690 [qtp1005310362-44] DEBUG:org.apache.http.wire << "Server: Apache-Coyote/1.1[\r][\n]"
2013-08-19 16:34:12,690 [qtp1005310362-44] DEBUG:org.apache.http.wire << "Date: Mon, 19 Aug 2013 20:34:11 GMT[\r][\n]"
2013-08-19 16:34:12,690 [qtp1005310362-44] DEBUG:org.apache.http.wire << "PayPal-Debug-Id: d29c41eb8625a[\r][\n]"
2013-08-19 16:34:12,690 [qtp1005310362-44] DEBUG:org.apache.http.wire << "Content-Type: application/json[\r][\n]"
2013-08-19 16:34:12,690 [qtp1005310362-44] DEBUG:org.apache.http.wire << "Content-Length: 282[\r][\n]"
2013-08-19 16:34:12,690 [qtp1005310362-44] DEBUG:org.apache.http.wire << "[\r][\n]"
2013-08-19 16:34:12,690 [qtp1005310362-44]     2013-08-19 16:34:12,691 [qtp1005310362-44] DEBUG:org.apache.http.impl.client.DefaultHttpClient Connection can be kept alive indefinitely
2013-08-19 16:34:12,691 [qtp1005310362-44] DEBUG:org.apache.http.wire << "{"scope":"https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card https://api.paypal.com/v1/vault/credit-card/.* openid","access_token":"RVATuLOQB0WFX
    keSDZQw4ZnyfIduPCF2j7sMhcfspwo","token_type":"Bearer","app_id":"APP-80W284285Q519543T","expires_in":28800}"
2013-08-19 16:34:12,693 [qtp1005310362-44] DEBUG:org.apache.http.impl.conn.PoolingClientConnectionManager Connection [id: 5][route: {s}->https://api.sandbox.paypal.com] can be kept alive indefinitely
2013-08-19 16:34:12,693 [qtp1005310362-44] DEBUG:org.apache.http.impl.conn.PoolingClientConnectionManager Connection released: [id: 5][route: {s}->https://api.sandbox.paypal.com][total kept alive: 1; route allocated: 1 of 2; total allocated: 1 of 2]
2013-08-19 16:34:15,197 [qtp1005310362-44] ERROR:com.example.gateways.paypal.payments.PayPalPaymentsProREST Failed to submit donation
    com.paypal.core.rest.PayPalRESTException: Error code : 401 with response : Server returned HTTP response code: 401 for URL: https://api.sandbox.paypal.com/v1/payments/payment

I noticed the scope and the URL the API sent me to are two different things. Perhaps I'm missing some configuration to sent the API calls to the sandbox URL?

我注意到API发送给我的范围和URL是两个不同的东西。也许我缺少一些配置来将API调用发送到沙箱URL?

In my code above you can see I'm setting the service.EndPoint to API_ENDPOINT which is set to the https://api.sandbox.paypal.com in my tests. I am also not providing the clientID or clientSecret in my properties object, but even providing them gives me a 401.

在上面的代码中,您可以看到我正在设置服务。端点到API_ENDPOINT,在我的测试中设置为https://api.sandbox.paypal.com。我也没有在我的属性对象中提供clientID或clientSecret,但是即使提供给我一个401。

What else am I missing?

我还漏掉了什么?

1 个解决方案

#1


0  

Came across this question and had a similar problem when trying to make payments for a third party PayPal account.

遇到这个问题,在试图支付第三方PayPal账户时遇到了类似的问题。

Not sure if you're running into the same thing I was, but I was trying to create payments for a third party paypal account to which I had not properly requested permission. Turns out I needed to use the Permissions API to request proper permissions.

我不确定你是否遇到了同样的问题,但我试图为第三方paypal账户支付款项,而我并没有得到我的许可。事实证明,我需要使用权限API来请求适当的权限。

See this link: https://developer.paypal.com/webapps/developer/docs/classic/permissions-service/integration-guide/PermissionsAbout/

看到这个链接:https://developer.paypal.com/webapps/developer/docs/classic/permissions-service/integration-guide/PermissionsAbout/

#1


0  

Came across this question and had a similar problem when trying to make payments for a third party PayPal account.

遇到这个问题,在试图支付第三方PayPal账户时遇到了类似的问题。

Not sure if you're running into the same thing I was, but I was trying to create payments for a third party paypal account to which I had not properly requested permission. Turns out I needed to use the Permissions API to request proper permissions.

我不确定你是否遇到了同样的问题,但我试图为第三方paypal账户支付款项,而我并没有得到我的许可。事实证明,我需要使用权限API来请求适当的权限。

See this link: https://developer.paypal.com/webapps/developer/docs/classic/permissions-service/integration-guide/PermissionsAbout/

看到这个链接:https://developer.paypal.com/webapps/developer/docs/classic/permissions-service/integration-guide/PermissionsAbout/