YE GREAT OAUTH TUTORIAL

<?php /*OAuth is great. It's also complicated. Or rather, it LOOKS complicated. This whole script is just one big long function. It's a really, really ugly function. I broke down everything "Barney-style" to demonstrate all the steps in the process, and because there are some things you have to decide -- how to record the user data, for instance. Let's get this train wreck a rollin'.*/ function oauthRequest($apiPath,$getOrPost,$parameters){ /*You get this info from https://coinbase.com/oauth/applications*/ $clientId = "#####"; $clientSecret = "#####"; $callbackUrl = "http://www.blah.com/oauth.php"; function curling($url,$getpost,$params){ if($params != ""){ $params = http_build_query(json_decode($params), true); } if($getpost == "get"){ $ispost = false; $url .= $params; } $ch = curl_init(); curl_setopt_array($ch, array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true )); if($getpost == "post"){ curl_setopt_array($ch, array( CURLOPT_POST => $ispost, CURLOPT_POSTFIELDS => $params )); } $results = curl_exec($ch); curl_close($ch); return $results; } /*There are two people involved here: the Client (you), and the User (the person accessing your app or site). You'll need 3 pieces of data for each user before your app can access their Coinbase account: a User Code, an Access Token, and a Refresh Token. For the purposes of this demonstration, I'm recording all of the user data in a .txt file on my server. THIS IS PROBABLY A BAD IDEA in real life because .txt files aren't secure at all, and this text file will only store the data for one user (it gets overwritten every time). This is the kind of stuff you'd put in an SQL database if you have one, or maybe in the user's cookies.*/ if(!file_exists("userdata.txt") || file_get_contents("userdata.txt") == ""){ file_put_contents("userdata.txt",json_encode(array( "userCode" => "", "accessToken" => "", "refreshToken" => "" )), LOCK_EX); } $userData = json_decode(file_get_contents("userdata.txt"), true); /*Okay. So. First thing we're going to do is see if we have a User Code for this user. These are big alphanumeric strings that are 64 characters long. If we have one, it'll either be in the URL of this page (the $_GET array), or it'll be in that userdata.txt file.*/ if(array_key_exists("code",$_GET) && $_GET["code"] != ""){ $userCode = $_GET["code"]; }else if(array_key_exists("userCode",$userData) && $userData["userCode"] != ""){ $userCode = $userData["userCode"]; }else{ /*If we don't have a User Code, then this next snippet of code will fire. It'll return the link for a special user-specific Coinbase page to which the user will need to go to authorize your app to access their Coinbase account (by signing into Coinbase and clicking a green "Authorize" button). After authorizing your app, they'll be automatically taken to the Redirect URL you specified, with their User Code added to the end of the URL. So if your Redirect URL is www.blah.com/oauth.php, they'll go to www.blah.com/oauth.php? code=123451234512345 . This User Code never expires, and so theoretically the user should only need to go to the authorization link once. However, if you don't make a way of getting the User Code in the future (my fancy "userdata.txt" in this case) or they de- authorized your app from within their Coinbase account, then they'll need to go to the link again and re-authorize your app from the beginning. I have it set up so my Redirect URL and the rest of my OAuth script are all on the same page: www.blah.com/oauth.php . So the user will just start back at the beginning of this script, and THIS time the script will see the User Code in the URL (the $_GET array), and so will skip this next bit. Whew. You with me so far?*/ return ("https:/*coinbase.com/oauth/authorize?" . http_build_query(array( "response_type" => "code", "client_id" => $clientId, "redirect_uri" => $callbackUrl ))); die; } /*Here I am, recording the User Code for future use in userdata.txt*/ $userData["userCode"] = $userCode; file_put_contents("userdata.txt",json_encode($userData),LOCK_EX); /*Alright, we've got the User Code. Now we need the Access Token -- another 64- character string. The difference is that the Access Token expires every 2 hours (7200 seconds). Let's see if we already have one in the userdata.txt file.*/ if(array_key_exists("accessToken",$userData) && $userData["accessToken"] != ""){ $accessToken = $userData["accessToken"]; $refreshToken = $userData["refreshToken"]; }else{ /*If we're here, it's because we don't have an Access Token for this user. We get one by making this POST request:*/ $authorization = json_decode(curling( "https:/*coinbase.com/oauth/token" . "?" . http_build_query(array( "grant_type" => "authorization_code", "code" => $userCode, "redirect_uri" => $callbackUrl, "client_id" => $clientId, "client_secret" => $clientSecret )), "post", ""), true); if(array_key_exists("error",$authorization)){ /*If something goes wrong here, I'm going to clean out userdata.txt and ask the user to try again.*/ file_put_contents("userdata.txt","",LOCK_EX); die("Something went wrong. Please refresh the page and try again."); } $accessToken = $authorization["access_token"]; $refreshToken = $authorization["refresh_token"]; } /*The Refresh Token is what you use to get a new Access Token once the current Access Token has expired. The Refresh Token never expires, but can only be used once. Anytime you get an Access Token, you'll also be given a Refresh Token. If you don't have the Refresh Token and a working Access Token for the user, they'll need to re-authorize your app all over again. I'm backing up the Access Token and Refresh Token to userdata.txt*/ $userData["accessToken"] = $accessToken; $userData["refreshToken"] = $refreshToken; file_put_contents("userdata.txt",json_encode($userData),LOCK_EX); /*Alright! At this point, we should have the three bits of user data we need: the User Code, the Access Token, and the Refresh Token. So now lets try actually making an API request. This whole script is really just one big function called "oauthRequest". You pass three parameters to the function: the path of the API request (everything after https:/*coinbase.com/api/v1/), whether this API query is a GET or a POST, and any parameters that go along with that GET or POST request. These params first come into play here. Let's make the API request:*/ $results = curling("https:/*coinbase.com/api/v1/" . $apiPath . "?" . http_build_query(array( "access_token" => $accessToken )), $getOrPost, $parameters); /*Now we're going to make sure the request actually worked, and didn't get rejected because the Access Token was expired. If it WAS expired, the results should be blank. (It'll return a 401 if you want to get fancy.)*/ $resultsArray = json_decode($results); if(count($resultsArray) < 1){ /*Looks like it did expire, so now we make a POST request using the Refresh token, which will return a new Access Token AND a new Refresh Token.*/ $reAuthorization = json_decode(curling( "https:/*coinbase.com/oauth/token?" . http_build_query(array( "grant_type" => "refresh_token", "code" => $userCode, "refresh_token" => $refreshToken )), "post", ""), true); $accessToken = $reAuthorization["access_token"]; $refreshToken = $reAuthorization["refresh_token"]; /*Let's back those up to userdata.txt...*/ $userData["accessToken"] = $accessToken; $userData["refreshToken"] = $refreshToken; file_put_contents("userdata.txt",json_encode($userData),LOCK_EX); /*...and try the API request all over again:*/ $results = curling("https:/*coinbase.com/api/v1/" . $apiPath . "?" . http_build_query(array( "access_token" => $accessToken )), $getOrPost, $parameters); /*If it doesn't work THIS time, I'm going to clean out userdata.txt and ask the user to try again. One of the codes probably got all mungled up.*/ $resultsArray = json_decode($results); if(array_key_exists("error",$resultsArray)){ file_put_contents("userdata.txt","",LOCK_EX); die("Something went wrong. Please refresh the page and try again."); } } /*If, however, everything went right, then this function will return the JSON string with the data from the API! Hooray!*/ return $results; } /*Here are 4 different example requests you can make.*/ /* echo oauthRequest("account/generate_receive_address","post",""); echo oauthRequest("buttons","post",'{ "button": { "name": "test", "type": "buy_now", "price_string": ".01", "price_currency_iso": "USD" } }'); echo oauthRequest("prices/buy","get",'{ "qty": 1, "currency": "USD" }'); echo oauthRequest("account/balance","get",""); */ ?>