Closed jannisborgers closed 1 year ago
So we do use different endpoints that those docs suggest:
https://api.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize
https://api.paypal.com/v1/identity/openidconnect/tokenservice
Which are the authorization and token endpoints respectively. It's possible this may be out of date, so I'll need to test. It's also possible it may not like .test
as a TLD, but I'll double check that as well.
Could it be that Consume needs to distinguish between Sandbox and Live API? The domain used in your post and the one in the docs is the most obvious difference here.
I did just post the production endpoints for brevity. Using the sandbox will change those TLDs to api.sandbox.paypal.com
, but you're right that there's no setting in Consume for toggling that. I've just pushed that for the next release.
I'm still investigating what the issue is here
Okay, so looks like it just took a good couple of hours for my redirect to work. I can confirm that .test
domains work. But it's likely that the issue was that I was trying to use the sandbox, but the integration wasn't enabled to allow that.
To get this early, run composer require verbb/consume:"dev-craft-4 as 1.0.2"
Hi @engram-design — thanks a lot! I can successfully connect to the API, and the sandbox toggle is very helpful.
Is it possible that the sandbox toggle only affects the authentication call, but not the API calls itself? When I try to use the client, the consume()
call returns null
. The log shows the following, which indicates that it connects to the live/production API (see POST url):
2023-05-17 05:30:30 [ERROR] Unable to fetch data: “Client error: `POST https://api.paypal.com/v2/checkout/orders` resulted in a `401 Unauthorized` response:
{"error":"invalid_token","error_description":"The token passed in was not found in the system"}
Just pushed this to the auth module, so a composer update
or composer require verbb/auth
should get the latest.
I can confirm that the authentication works and I can connect the PayPal client. Thank you, Josh!
I’m sorry @engram-design, but there still seems to be an issue with the PayPal provider. Since I updated, I at least got a different response from the PayPal REST API than what I got when I opened this issue, but now I get a 403 Forbidden
error PERMISSION_DENIED
with descriptions Authorization failed due to insufficient permissions.
and detail description You do not have permission to access or perform operations on this resource.
I tried back and forth, even created a whole new sandbox account and REST app in the paypal backend, but I can only make it work with a template-side client:
This works:
{% set paypal_client = {
base_uri: "https://api-m.sandbox.paypal.com",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer [Access token manually generated with Postman]",
}
} %}
{% set paypal_query = {
purchase_units: paypal_data.purchase_units,
intent: "CAPTURE",
application_context: {
return_url: getenv("PRIMARY_SITE_URL") ~ "shop/paypal/success",
cancel_url: getenv("PRIMARY_SITE_URL") ~ "shop/paypal/cancel",
}
} %}
{% set paypal_order = consume(paypal_client, "POST", "/v2/checkout/orders", {
json: paypal_query
}) %}
This doesn’t work:
{# PayPal Provider client set up in Consume named with handle "paypal_client" #}
{% set paypal_order = consume("paypal_client", "POST", "/v2/checkout/orders", {
json: paypal_query
}) %}
Also, between these error messages, I also got a couple of expired token errors and had to manually disconnect and reconnect the client for that error to go away. The Consume docs say that providers that support refresh tokens are automatically renewed. Is this the case with the PayPal provider type? Otherwise, the whole auth process wouldn't work without me manually regenerating the token and saving it somewhere… (via a cron?)…
It looks like PayPal doesn't support refresh tokens (you can see in the auth_oauth_tokens
db table, refreshToken
is empty as none is reported back). However, looking at their postman example (I can't find reference in their docs) refresh tokens should be possible. Looks like the client is still using old endpoints, so I'm going to update them all to the current docs.
This is all on the auth module. Run composer require verbb/auth:"dev-craft-4 as 1.0.5"
just so I can ensure that's working for you.
@engram-design That was it, works as expected now!
The database also shows a refreshToken
value now. Am I right to assume that refreshing the token should work via Consume? PayPal’s tokens only work for a couple of hours, so not having to code a token sync mechanism would be a real time saver.
Correct, as long as a refreshToken
exists, Consume can check when it expires and request a new token.
That's wonderful. Thanks Josh!
Describe the bug
I wanted to connect to PayPal’s REST API for processing orders using the steps below.
After clicking the Connect button on the client page, Consume redirects to a URL in this form:
It shows an error page telling me “invalid client_id or redirect_url”. I double checked, it’s all set up correctly:
I found a lot of threads online saying that if the redirect url isn’t an exact match, the Auth fails. I waited overnight because the PayPal app settings page says to wait 3 hours for changes to take effect. Still, nothing. My return uri is a
.test
domain because I work with Laravel Valet locally.Next, I tried following the PayPal docs and set up a Postman account (see Authentication Docs) to try and get an access token that way. Postman has a UI for that, and it seems to work with my client ID and secret. I copied the access token and used it in an ad-hoc Guzzle client with Consume, which works. Of course this would require me to renew the token manually…
Steps to reproduce
Craft CMS version
4.4.10.1
Plugin version
1.0.2
Multi-site?
No
Additional context
I don’t know if this is even an error with Consume or PayPal.