facebook data deletion callback implementation in laravel using socialite - php

I am implementing facebook data deletion callback but I got really lost and i can't continue on the JSON response that facebook is expecting.
Return a JSON response that contains a URL where the user can check the status of their deletion request and an alphanumeric confirmation code. The JSON response has the following form:
{ url: '<url>', confirmation_code: '<code>' }
that is the part that I got lost and stuck. My question is
what is the URL should do or show.
what is the logic between the confirmation code
so far here is what I did on my controller.
<?php
namespace App\Http\Controllers\User\Auth\Socialite;
use App\Models\User;
use Illuminate\Http\Request;
class FacebookSocialLoginController extends SocialLoginFactory
{
public function provider(): string
{
return 'facebook';
}
public function dataDeletionCallback(Request $request)
{
$signed_request = $request->get('signed_request');
$data = $this->parse_signed_request($signed_request);
$user_id = $data['user_id'];
// here will delete the user base on the user_id from facebook
User::where([
['provider' => 'facebook'],
['provider_id' => $user_id]
])->forceDelete();
// here will check if the user is deleted
$isDeleted = User::withTrashed()->where([
['provider' => 'facebook'],
['provider_id' => $user_id]
])->find();
if ($isDeleted ===null) {
return response()->json([
'url' => '', // <------ i dont know what to put on this or what should it do
'code' => '', // <------ i dont know what is the logic of this code
]);
}
return response()->json([
'message' => 'operation not successful'
], 500);
}
private function parse_signed_request($signed_request) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$secret = config('service.facebook.client_secret'); // Use your app secret here
// decode the data
$sig = $this->base64_url_decode($encoded_sig);
$data = json_decode($this->base64_url_decode($payload), true);
// confirm the signature
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
return null;
}
return $data;
}
private function base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
}

what is the URL should do or show.
The purpose of this URL, is what the documentation said - to provide a way for the user, to check on the status of their deletion request.
Not all apps will be able to delete all personal user data immediately, the moment the user requests it.
Some might need to keep a subset of the data for legal reasons; others might simply need some extra processing time, because the process can not be handled in a totally automated matter, and a human needs to get involved.
So the user is given this status check URL in response to their request – so that they can go visit that URL tomorrow, or two weeks or six months from now, and check on the status of their deletion request - were you able to delete all data by now, will it still take some time, is there some data that won’t be deleted for legal reasons, etc.
what is the logic between the confirmation code
Just a different way to access the same information. Maybe checking the status via the URL you provided is not enough for the user, so they might want to call or send an email to your support staff, to inquire about the status of their deletion request. Then they can give your support people that code, and they can go look up the necessary information via that.
If you check the code examples in the documentation, they are using the same code value in the status check URL, and as the confirmation code. So you can use the same code for both.
Create it, store it in your database, and associate the status of a particular user’s deletion request with that code.

Related

Fetching A Patron Data From Patreon API

I'm developing a webpage with Laravel 8 and I have issues with fetching a patron details by id from Patreon API. Here is my use case.
I’ve added "Login with Patreon" option to my webpage, and it works well. When someone login with Patreon successfully, I store her/his Patreon id and set remember token to login the member automatically when she/he visits my page next time.
The first login process is fine. The problem occurs when my Patron visits my page next time. Because I want to check whether I received any payment before I let she/he see all content. That’s why I need to get my patron details from a middleware. To do that I tried:
fetch_user() returns my account details instead of logged-in user.
fetch_user() with the access token that returns from Patreon when
someone login, returns unauthorized.
fetch_member_details() doesn’t work with the id I passed, which is an
integer like 5484646 because it requires a very long string like
55153fds-f45fd5sfs-fds42ds, I don't know what it's.
fetch_page_of_members_from_campaign() and fetch_member_details()
together to get the proper ID, but it takes ages to get data, which
is unacceptable.
So, how can it be done?
https://further-reading.net/2020/06/getting-names-of-your-patreon-patrons-by-tier/
This might be useful. I believe, there is not a direct single API for this, but you can -
First fetch all campaigns/tiers data
And then fetch patrons for each campaign/tier
I like to answer my question for those who need some help.
First of all, I use the official PHP package by Patreon
I've created a middleware to check if the user should be authorized again. In order to prevent the same process every single time, I set timeout to users table and check if it still has time to expire. If it does, no need to do anything. Of course, this is my use case, but without that explanation, some parts of the code can be nonsense to you.
// App\Http\Middleware\AuthenticateMember.php
public function handle(Request $request, Closure $next)
{
if (!Auth::check()) {
return $next($request);
}
if (Carbon::parse(Auth::user()->timeout)->isFuture()) {
return $next($request);
}
$this->refreshCredentials();
return $next($request);
}
If "timeout" isn't in the future, refreshCredentials method will be called. This is a method, which will trigger binding AuthGatewayContract to the service container.
// App\Trait\Users.php
public function refreshCredentials()
{
$gateway = App::make('App\Services\AuthGatewaysContract');
$gateway->ensureUserStillAuthenticated();
}
public function handleUserRecord($user)
{
return User::updateOrCreate([
'email' => $user['email']
], $user);
}
public function attemptToLogin($user, $remember = true)
{
Auth::login($user, $remember);
event(new Registered($user));
}
This is how the binding works:
// App\Providers\AppServiceProvider.php
public function register()
{
$this->app->singleton(AuthGatewaysContract::class, function () {
$routeParts = explode('/', url()->current());
$gateway = array_pop($routeParts); // this is how I know which "Login with ..." button is clicked.
$isGateway = Gateway::where('name', $gateway)->first();
$gateway = $isGateway ? ucfirst($gateway) : ucfirst(Auth::user()->gateway->name);
$class = "\App\Services\AuthGateways\\$gateway";
return new $class();
});
}
So Patreon.php is active gateway now, and ensureUserStillAuthenticated can be called:
// App\Services\AuthGateways\Patreon.php
public function ensureUserStillAuthenticated()
{
$this->authenticate([
'access_token' => Auth::user()->access_token,
'refresh_token' => Auth::user()->refresh_token,
]);
}
private function authenticate($tokens)
{
$patron = $this->fetchUserFromGateway($tokens);
$user = $this->handleResponseData($patron, $tokens);
$user = $this->handleUserRecord($user);
return $this->attemptToLogin($user);
}
private function fetchUserFromGateway($tokens)
{
// This is the only function that communicate with Patreon-php package.
$api_client = new API($tokens['access_token']);
return $api_client->fetch_user();
}
private function handleResponseData($data, $tokens)
{
return [
'name' => $data['data']['attributes']['full_name'],
'email' => $data['data']['attributes']['email'],
'password' => Hash::make(Str::random(24)),
'role_id' => $this->assignRoleId($data),
'payment_id' => Payment::where('name', 'patreon')->first()->id,
'gateway_id' => Gateway::where('name', 'patreon')->first()->id,
'access_token' => $tokens['access_token'],
'refresh_token' => $tokens['refresh_token'],
'timeout' => Carbon::today()->addMonth()->toDateString()
];
}

Finding User with Auth - Laravel

I am trying to find the logged in user in my application using Auth but i get trying to get property of non-object which i understand clearly that it is returning null.
In my code below, an event triggers my webhook and post is sent to the address below. The function orderCreateWebhook triggers but that is where the error comes from..
The line $get_template = Order::where('id', Auth::user()->id);. Why is Auth returning null please? I am logged as well because i use auth in this same controller for another function which works fine.
Is it because it a webhook ?
Controller
public function registerOrderCreateWebhook(Request $request)
{
$shop = "feas.myshopify.com";
$token = "8f43d89a64e922d7d343c1173f6d";
$shopify = Shopify::setShopUrl($shop)->setAccessToken($token);
Shopify::setShopUrl($shop)->setAccessToken($token)->post("admin/webhooks.json", ['webhook' =>
['topic' => 'orders/create',
'address' => 'https://larashop.domain.com/order-create-webhook',
'format' => 'json'
]
]);
}
public function orderCreateWebhook(Request $request)
{
$get_template = Order::where('id', Auth::user()->id);
$baseurl = "https://apps.domain.net/smsapi";
$query = "?key=7e3e4d4a6cfebc08eadc&to=number&msg=message&sender_id=Shopify";
$final_uri = $baseurl.$query;
$response = file_get_contents($final_uri);
header ("Content-Type:text/xml");
}
In your function registerOrderCreateWebhook you appear to be making a request to shopify api and providing your webhook as the address which shopify will redirect the user to upon success. If this is correct, that request does not know about the user who generated the original request that made the api request since the request is coming from a completely different origin.
You would need to pass some key along with the url and then obtain the user within orderCreateWebhook. Something like:
Shopify::setShopUrl($shop)->setAccessToken($token)->post("admin/webhooks.json",
['webhook' =>
['topic' => 'orders/create',
'address' => 'https://larashop.domain.com/order-create-webhook/some-unique-key',
'format' => 'json'
]
]);
My suggestion would be to have a unique hash stored somewhere that relates back to the user in your system, perhaps a column in your users table. I wouldn't use the user_id for security reasons. So you would end up with something like:
//route
Route::get('/order-create-webhook/{uniqueKey}', 'YourController#orderCreateWebhook');
//or
Route::post('/order-create-webhook/{uniqueKey}', 'YourController#orderCreateWebhook');
// depending on the request type used by api which calls this endpoint
// controller function
public function orderCreateWebhook($uniqueKey, Request $request)
{
$user = User::where('unique_key', $uniqueKey)->first();
$get_template = Order::where('id', Auth::user()->id);
$baseurl = "https://apps.domain.net/smsapi";
$query = "?key=7e3e4d4a6cfebc08eadc&to=number&msg=message&sender_id=Shopify";
$final_uri = $baseurl.$query;
$response = file_get_contents($final_uri);
header ("Content-Type:text/xml");
}
Is it because it a webhook ?
Yes, you can't use sessions in a webhook. It's the shopify server which is making the call. You should read the doc, it may exist a way to give an unique identifier in your call to shopify api and get it back in the webhook to find your user associated.
just use this to get authenticated user
use the facade in your class/Controller
use Illuminate\Support\Facades\Auth
public function getAuthUser(){
$user = Auth::user()
if(!is_null($user)
{
//user is authenticated
}
else
{
// no user
}
}

Laravel 5 Creating Custom Tokens And Parsing Back Using JWT

I am a newbie to JWT Token System in laravel 5 and using tymon JWT Auth
I managed to create my custom JWT token and my code as follows
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Tymon\JWTAuth\JWTManager as JWT;
use JWTAuth;
use JWTFactory;
use Tymon\JWTAuth\Exceptions\JWTException;
public function login(Request $request)
{
$customClaims = ['foo' => 'bar', 'baz' => 'bob'];
$payload = JWTFactory::make($customClaims);
$token = JWTAuth::encode($payload);
// return response()->json(compact('token')); // This didnt work?Why?
return response()->json(compact($token))->header('Authorization','Bearer '.$token);
}
public function getUser(){
$token = JWTAuth::parseToken();
echo $token;
}
Here are my following clarifications required
// return response()->json(compact('token'));
Why this gave me an empty json object as {"token":{}}
Is it the right way, i could send my custom data in token and get it back the foo and baz values from the same token?
The output of my code while testing with postman is an empty array. as []. But my headers are added with Authorization →Bearer eyJ0eXAiOiJKV1QiLCJhbG...
Is this correct?
3a. Instead of a simple blank array, i need a success message as 'authorized':true. How can i achieve it?
How should i pass this token back to test. Where should this token be passed using postman. I passed it through Headers as shown in the image
How could i parse this token using laravel and get the custom data i.e foo and baz sent as a token. The method i called is getUser here.
I dont think the token creation is being built properly. Below is working code for login token creation. For this, make sure that the 'user' model under your config/jwt.php is the correct eloquent user model for your application.
$user = array(
'user' => $request->input('email'),
'password' => $request->input('pass')
);
$customClaims= ['usr' => $user['user']];
if(!$token = JWTAuth::attempt($user, $customClaims)){
abort(401);
}
else{
return response()->json(compact('token'));
}
Also included in the above code with the custom claims variable, you were on the right track with that just needs to be passed as a second parameter in the attempt function.
Only the client needs to send the authorization: Bearertoken header to prove that they are who they say they are (I am coming from an android client/server jwt background. So sorry if this doesnt apply to your application).
3a. For any subsequent pages that the user browses to, you simply add an if statement like this
if(!$user = JWTAuth::parseToken()->authenticate()){
abort(401);
}
else{
// Code allowing the user to see protected content
}
See answer to question 3. include an http header with authorization BearerToken
To extract the data from the JWT Payload, you will need to decode the base64 encoded text from the text after the first period in the token and send that to a string. Then run that string through the base64_decode($string) function. That should start to give you some of the payload data.
Hope this helps.
I had the same problem here and i got the following solution:
public function whatEver()
{
$token = JWTAuth::parseToken();
$response = $token->getPayload()->get('foo');
return $response
}
this should return bar.
you can use this method in your user model :
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [
'perms' => '
'
];
}

How do I interact with Coinbase's API? Why does it always fail?

Accessing the Coinbase API used to be really simple: all you needed was an API key. Now you need something called a "nonce" and a "signature". I pass my new API "Secret", the nonce, and the Key in my request, but it returns an "invalid_key" error. What gives?
EDIT March 12th: Added a tutorial on interacting with the API via OAuth.
The fact that the API used to be so simple -- only needing a Key -- means it was pretty insecure. So they beefed up the security a week-ish ago. Here's the blog post:
http://blog.coinbase.com/post/75936737678/more-security-and-granular-control-with-the-new-api
Everyone now gets an API "Secret" in addition to an API Key. Whenever you make a request to the API, you have to include three parameters:
Your API Key.
A "nonce", which is a unique number that you use to identify something. In this case, every single request you make needs to have a new number, and each request's nonce has to be bigger than the one before it.
Your API "Signature". This is NOT your API "Secret".
The Signature is your nonce followed immediately by the full URL to which you're posting your request, parameters and all. This URL also contains the nonce, so the whole thing all together would look something like this:
12345https://coinbase.com/api/v1/buttons?nonce=12345&name=Socks&price=9.95
Then you take that whole thing and encode it as a "SHA256" hash. If you don't know what that means, don't panic -- you can do it in one line using a function PHP already has built in.
At any rate, I was having some trouble figuring all this out, so I spent a little while on it and put together this script, which makes GETing and POSTing to the API really easy. I'd love to hear people's thoughts!
<?php
function coinbaseRequest($what,$getOrPost,$parameters){
//Obviously, your API Key and Secret go here.
$apikey = "blahblahblah";
$apisecret = "blahblahblahblah";
$nonce = file_get_contents("nonce.txt") + 1;
file_put_contents("nonce.txt", $nonce, LOCK_EX);
$url = "https://coinbase.com/api/v1/" . $what . "?nonce=" . $nonce;
if($parameters != ""){
$parameters = http_build_query(json_decode($parameters), true);
}
//Here I go, hashing the Signature! Thanks, PHP, for making this easy!
$signature = hash_hmac("sha256", $nonce . $url . $parameters, $apisecret);
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array(
"ACCESS_KEY: " . $apikey,
"ACCESS_NONCE: " . $nonce,
"ACCESS_SIGNATURE: " . $signature
)));
if($getOrPost == "post"){
curl_setopt_array($ch, array(
CURLOPT_POSTFIELDS => $parameters,
CURLOPT_POST => true,
));
}
$results = curl_exec($ch);
curl_close($ch);
echo $results;
}
//This is a POST example.
coinbaseRequest("buttons", "post", '{
"button": {
"name": "test",
"price_string": "1.23",
"price_currency_iso": "USD",
"variable_price": true
}
}');
//This is a GET example.
coinbaseRequest("account/balance", "get", false);
?>
Notes:
I tried using (microtime(true)*100) for my nonces. The problem is it makes a decimal number, and the last few digits kept getting dropped or rounded off so it didn't work. Then I thought, "Screw this", made a blank nonce.txt file, and wrote 1 in it, and to get nonces I just got the contents of that file, added 1, and replaced the file with the new number. It served a second purpose as a counter showing how many total requests I've made.
But then someone pointed out to me PHP's "uniqid" function, which generates an ID based on the current microtime. So you can also try this:
$nonce = hexdec(uniqid());
This has the advantage of not accessing an external file. I actually really like being able to see how many requests I've made, and so will probably stick with the (bad) nonce.txt method.
The coinbaseRequest() function has three parameters. The first is the directory to which you're making your request -- that is, whatever's supposed to come after "https://coinbase.com/api/v1/". The second parameter is "get" or "post", depending on whether it's a GET or a POST request. (Make sense?)
The third parameter is all the queries you're passing in your request. This should be formatted as JSON, unless it's a GET request that doesn't take any parameters (besides the Key, Nonce, and Signature which the function includes for you), in which case you should leave this as false.
EDIT, March 3rd:
I made a little function for taking whatever's returned by coinbaseRequest and turning it into a button:
function makebutt($data){
$data = json_decode($data,true);
$buttoncode = $data["button"]["code"];
return ("<a class=\"coinbase-button\" data-code=\"" . $buttoncode . "\" href=\"https://coinbase.com/checkouts/" . $buttoncode . "\">Pay With Bitcoin</a><script src=\"https://coinbase.com/assets/button.js\" type=\"text/javascript\"></script>");
}
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","");
*/
?>
It's not working because Coinbase recently implemented the OAuth2 protocol. This ensures the personal information of your user is transmitted securely. I referred to this implementation several months ago when writing my own OAuth class on another project:

Facebook user deauthorizes the app

when user accepts the facebook application from my website, I am storing the user details and facebook details(access token) in database.
when he removes my application from facebook i want to remove the detail from database. how to do this?
I can give Deauthorize Callback url. if some one removes application, it will redirect to this page. but, wt should be the code here to delete the data from db? I means, when it redirect, will it post the access token details, so that i can charge fro access token and delete that row.
It's clearly stated in the authentication document:
App Deauthorization
When a user of your app removes it in
the App Dashboard or blocks the app in
the News Feed, your app can be
notified by specifying a Deauthorize
Callback URL in the Developer App.
During app removal we will send an
HTTP POST request containing a single
parameter, signed_request, which
contains the user id (UID) of the user
that just removed your app. You will
not receive an user access token in
this request and all existing user
access tokens will be automatically
expired.
So using the signed_request function on its own docuement:
<?php
function parse_signed_request($signed_request, $secret) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
// decode the data
$sig = base64_url_decode($encoded_sig);
$data = json_decode(base64_url_decode($payload), true);
if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
error_log('Unknown algorithm. Expected HMAC-SHA256');
return null;
}
// check sig
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
return null;
}
return $data;
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
$result = parse_signed_request($_REQUEST['signed_request'],"APP_SECRET");
$myFile = "deauthorize.txt";
$fh = fopen($myFile, 'w') or die("can't open file");
fwrite($fh, $result["user_id"] . "\n");
fclose($fh);
?>
So all you need to do is get the $result["user_id"] query your DB and remove the record.
P.S: I would recommend adding a new field called active and just deactivate the user instead of removing the record all together.
EDIT:
Facebook will NOT redirect the user to the deauthorize URL! it'll ping it only:
Facebook pings this URL when a user
deauthorizes your app
This code is not working, although it gets called when a user deauthorizes the app the only data passed into the function is a "1" (Tested with test user and my own FB account when app is live)
file_put_contents("test.txt",$fbUserId . " ". print_r($_REQUEST['signed_request']));
in test.txt file " 1"

Categories