[PHP] null received from fetch_user

Hi there,

I have successfully received an access token and refresh token. Now I would like to connect and see the user pledge details and thereby control their access on my website.

$api_client = new API($access_code);
 
$patron_response = $api_client->fetch_user();

var_dump($patron_response);

The var_dump returns null ! What am I doing wrong ?

Based on the small amount of code you’ve shared, I can’t see any particular reason the API would be returning null. The API response is supposed to be a JSON, and is converted to a PHP array by the API unless specified otherwise.

I think the only external dependency of the regular Patreon PHP bundle besides PHP is cURL (no idea why they don’t require it in the composer file). Can you confirm you have the current PHP cURL extension installed and enabled?

I just thought about this some more, and if you’ve got a user access token then you’d have to have cURL installed.

Are you using the creator access token or a user access token when you call the API? If you’re using the creator access token, I’d recommend not–I’ve no experience but there are a lot of reports on here of it being… problematic. And from my experience with the API, there’s no reason to use the creator token.

If you are using the creator access token please confirm you have cURL installed and enabled as an extension for PHP.

If you’re using a user access token then you must have cURL installed to complete the OAuth process with Patreon in order to get the access token. As such, I’m not sure how much more I can help without seeing more of the code you’re using to work with the API.

Thanks for the feedback, Zanaras

Below code is more in detail. Using bogus codes/tokens/urls not original ones

My button page code. This is where the user can click on to “Link their Patreon account” :

<form action='https://www.patreon.com/oauth2/authorize' method='GET' enctype='application/x-www-form-urlencoded'>

	<input type='hidden' name='response_type' value='code'/>
	<input type='hidden' name='client_id' value='QPOEVaQOWE-PNVQEqVQPRVfBQRPQzVWERQPhWjORVQPWRkVQP_iORVMVPPEU_QTV'/>
	<input type='hidden' name='redirect_uri' value='https://mywebsite.com/buttonpage.php'/>
	<input type='hidden' name='state' value='$useremail'/>
	
	<tr>
		<th><b>Link your Patreon account</b></th>
		<td>
			<input type='submit' name='PButton' value='Link' class='SButton'/>
		</td>			
	</tr>				
		
</form>

If the user clicks on the above button, they are taken to a Patreon page, where they can confirm/deny. Let’s assume they click on confirm. As per the redirect specified both on the Patreon Client API and the Form, it sends the user back to the website above, which receives a GET request:

<?php 
include('path/API.php');
include('path/OAuth.php');

use Patreon\API;
use Patreon\OAuth;

if ($_GET['code'])
{	
	$the_code_raw = $_GET['code'];
	$the_client_id="QPOEVaQOWE-PNVQEqVQPRVfBQRPQzVWERQPhWjORVQPWRkVQP_iORVMVPPEU_QTV";
	$the_client_secret="YWz4PELwGMEtOEFPy5WMBZ-3EQ_j8a7OWPlL2GnjM6VNc1B_z0WOW9UEn4413YRH";
	$the_re_url = "https://mywebsite.com/buttonpage.php";

	$oauth_client = new OAuth($the_client_id, $the_client_secret);	
	$tokens = $oauth_client->get_tokens($the_code_raw, $the_re_url);

	$access_token = $tokens['access_token'];
	$refresh_token = $tokens['refresh_token'];
}
?>

The above will provide the access token and the refresh token. In the next code, I attempt to access or retrieve user info, with new API using the access token obtained above. Imho, it should last 30-31 days therefore using it should yield a result:

<?php 			

include('path/API.php');
include('path/OAuth.php');

use Patreon\API;
use Patreon\OAuth;

$api_client = new API("P7QLF2OWMJ-VNEBDSOIF14MKEO6ER2KJEO0GO8QQLSP"); //access token

$patron_response = $api_client->fetch_user();

var_dump($patron_response);

?>

The API Result should by default return an array. At least, that’s what it described in the documentation.

Curl is enabled and on 7.66

I am using the user access token and not the creator access token.

I see no reason that it wouldn’t work. The access token is good for 30 days, expressed in seconds as part of the same return as the tokens from Patreon. I’m guess this is happening immediately though, so that’s not the issue.

I don’t think the API can return null if you send something to it. Either it returns what you asked or it returns an error explaining why it didn’t.

So, either your request isn’t getting sent to the API or returned by it, or it’s getting dropped somewhere in the bundle. And since the OAuth is working, that would lead me to believe that your server can communicate just fine with the Patreon API.

I wonder if it isn’t something to do with modern PHP not liking the Patreon PHP bundle’s cache, because it’s about the only place you can get a null (because the cache starts as a declared v. Can you do a var_dump call against $return before this line patreon-php/API.php at master · Patreon/patreon-php · GitHub and see if that has the user data?

Alternatively, adding var_dump(json_decode($json_string)) at patreon-php/API.php at master · Patreon/patreon-php · GitHub could return information to assist troubleshooting. Because that’d also capture any errors returned by the API.

If those are both null, then we know the request isn’t even getting sent to Patreon’s API. If they aren’t null, then it’s probably the caching issue, in which case I’ll provide instructions for using my fork which implements bypassing the bundle’s cache because I had an issue with it myself for my own PHP application.

I would really enjoy moving forward with this but now I am stuck with an unexpected “invalid_grant” error, so I will move my attention to other things, as I really can’t waste my time with errors that come out of no where, when absolutely no code has been changed. this also makes this API and setup extremely unstable and I don’t know if I can trust this system and framework moving forward.

I wouldn’t say the API is unstable, and trust me when I say i went through my own frustrations getting my app to work with it.

If anything I’d say it’s very stable, just poorly documented. The API format they use isn’t something they’ve made themselves–it uses the JSON API specification here: https://jsonapi.org/ which is how I figured out how to do a lot of things with it.

It’s also wrapped with an OAuth2 authentication system to validate requests to it, to ensure that only those that have access are supposed to.

Invalid Grant to me would tell me that I’m either using a token that doesn’t have access to what I’m requesting or that the token is no longer valid. Either because the token expired or the end user disconnected the app in their profile settings on Patreon. Just my guesses though.

Thanks Zanaras,

How can an access Token expire when I have access to both endpoints and when I did not change any code. I just came back to check and test/investigate the things you mentioned and there it was. I then even deleted and then recreated the entire Client API and it gave me the same result.

It works now ; I am receiving the access token and refresh token. What I changed : adding scope to the parameter list inside the form for the “Link to Patreon” button. Here I do not understand, as it was working fine before and it required this now all of a sudden.

Okay, so it seems like everything works fine now. I managed to get the details that I needed. What I changed : I made a API v2 instead of V1. I then also added the correct scopes to the params as stated above.

Thanks Zanaras for the help a

I would like to make a note here on scopes and somethings I discovered, as it might be relevant to your resolution:

If you log in as a user to your own application (generating a user access token vs a creator access token), regardless of what scoping you setup for that request, your token will have all scopes granted.

This also means you can do fetch_user on a member access token to a campaign that you aren’t a member of. Or worded so that makes sense: even though it isn’t expressed in the API you are always a member of your own campaign for access purposes. The API will tell you that your user is the creator of the campaign though, for what it’s worth, if you request it.

This can return… interesting results. My app for instance only asks for identity, because I have my own user auth system. When I then link my account in my app to my patreon using the user method, I can see other campaign memberships I have, even though my app doesn’t request that scope when I initially authenticate.

If the access_code there pertains to the code that api returns after authorization, it cannot be used to initiate an api connection. Access code is just for your app to contact the api using that code in order to ask for the token. Token is what is used for contacting the api using the api class.

no, it does to pertain to the authorization code. I retrieve and make use of the access token and the refresh token.

I see. Are you still getting null for that user?

If I understand correctly: No I do not log onto the system with my own account and I don’t log in as a user to my own application. I have two separate, individual accounts. The one is my main account as a creator, the other is a user account for testing the user access.

Today, I came back to see that my access returned unauthorized. Again, something that I do not understand, as I was under the impression that the access_token would be valid for a month. I have given up on the solution, as I really don’t see the logic in something that changes without there being actual changes.

Thanks again for all the help Zanaras. I saw I didn’t post this response. Hence the delayed response…

no, I am no longer receiving null for that user.

I have recreated everything and it seems to be working as of now. I have obtained the user access_token and refresh_token and I am using this now to obtain user data to “authenticate” users that are pledged on my website.

My question here would be : Do any of the above tokens change, before the “month” validity of the token has expired ? What would I do if it would change, randomly ? Would I then need to simply request a new access_token and refresh_token from the system by using the user refresh_token ? What I mean is, the next day after I had implemented this, things stopped working - without me making any changes to the setup…

The tokens can only change if one of three things happen:

  1. The user logs in with Patreon again or,
  2. The user disconnects your app from their account in their patreon settings or,
  3. Your application refreshes the tokens after they expire.

For situation #1 your app should capture this as part of the login process and just overwrite the old data. Situation #2, the tokens just stop working altogether and you get an access not authorized error. And for Situation #3, well, your app invoked it, so hopefully you were expecting it.

I’ve had my own application using the Patreon API successfully for a couple months now, with a few users going through a couple token refreshes without issues. My app has a subscription model and it’s own user authentication so I just ask that existing users connect their patreon account to it (log in with patreon) after they’ve logged in to my site, grab the relevant details, and then when my app checks for users that need subscription payments it’ll check to see if the user is using the patron subscription, update the tokens if needed, then request fresh patron identity info to confirm they are still a patron, and proceed accordingly.

I later added a means for my users to request my app do an update check against Patreon in order to capture patron changes as well.

  1. Does this mean that every time the user logs into Patreon itself, irrespective of my website login, the access_token and refresh_tokens change ? If true, this is then the reason why I had problems before.

I implemented the refresh functionality, which I guess is working as well now. did not have any errors as of late. My new test account just got flagged for being suspicious. How do you go about creating test accounts to see if your Patreon → website authentications are working properly, without getting flagged for suspicious activity ?

Only when they log in to patreon with your application do the tokens refresh. The tokens you get are unique to their login to your application–their logins elsewhere shouldn’t affect them.

As for suspicious activity, I actually setup three different “clients” for patreon to recognize: my live application, the semi-public test instance of that application, and a developer instance that just accepts 127.0.01 as a the redirect URL. From there I used my own account to log into it to make sure the process was working, and then to make sure I knew what user activity would look like asked a patron to log into the test instance.

All three apps have their own client registrations and tokens.

As for why your account got marked as suspicious, if you just made it and immediately logged into some random site, that’d probably not match the trend of most users on Patreon. I only used legitimate Patreon user accounts for testing, so this isn’t something I encountered.

I switched from per post to monthly, test to live. The user account I cleared up with support and was able to conclude testing. I checked my test users access and everything was working (revoked) as needed, as soon as I cancelled the patreon sub. I also tested normal user of just getting “Link to Patreon”, but not actually being subbed. So far, I did not notice anything strange or broken.

Thanks Zanaras for all the help and advise. I think we can conclude this as resolved.