Created
August 15, 2011 18:21
-
-
Save tecbot/1147357 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Facebook; | |
use Symfony\Component\HttpKernel\Log\LoggerInterface; | |
use Symfony\Component\Security\Core\Util\String; | |
use Symfony\Component\HttpFoundation\Response; | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\Routing\RouterInterface; | |
use JMS\DiExtraBundle\Annotation as DI; | |
/** | |
* @DI\Service("facebook.callback_server") | |
* | |
* @author Johannes M. Schmitt <[email protected]> | |
*/ | |
class CallbackServer | |
{ | |
private $facebook; | |
private $router; | |
private $verifyToken; | |
private $callbackRoute; | |
private $logger; | |
/** | |
* @DI\InjectParams({ | |
* "facebook" = @DI\Inject("fos_facebook.api"), | |
* "verifyToken" = @DI\Inject("%my.facebook_callback_token%"), | |
* "callbackRoute" = @DI\Inject("%my.facebook_callback_route%"), | |
* }) | |
* | |
* @param string $verifyToken | |
*/ | |
public function __construct(\BaseFacebook $facebook, RouterInterface $router, LoggerInterface $logger, $verifyToken, $callbackRoute) | |
{ | |
$this->facebook = $facebook; | |
$this->router = $router; | |
$this->logger = $logger; | |
$this->verifyToken = $verifyToken; | |
$this->callbackRoute = $callbackRoute; | |
} | |
public function setLogger(LoggerInterface $logger) | |
{ | |
$this->logger = $logger; | |
} | |
public function subscribe($object, $fields) | |
{ | |
if (!is_string($object)) { | |
throw new \RuntimeException(sprintf('$object must be a string, but got %s.', gettype($object))); | |
} | |
if (!is_string($fields)) { | |
throw new \RuntimeException(sprintf('$fields must be a string, but got %s.', gettype($fields))); | |
} | |
$callbackUrl = $this->router->generate($this->callbackRoute, array(), true); | |
$this->logger->debug(sprintf('Subscribing to Facebook notifications for object "%s" and fields "%s"...', $object, $fields)); | |
$this->logger->debug(sprintf('Using callback url "%s".', $callbackUrl)); | |
$this->facebook->api($this->facebook->getAppId().'/subscriptions', 'POST', array( | |
'object' => $object, | |
'fields' => $fields, | |
'callback_url' => $callbackUrl, | |
'verify_token' => $this->verifyToken, | |
)); | |
} | |
public function processRequest(Request $request) | |
{ | |
if ('GET' === $request->getMethod()) { | |
return $this->processVerificationRequest($request); | |
} else if ('POST' === $request->getMethod()) { | |
return $this->processSentData($request); | |
} | |
} | |
private function processSentData(Request $request) | |
{ | |
if ('application/json' !== $request->headers->get('Content-Type')) { | |
return new Response('Unsupported content type.', 406); | |
} | |
$payload = $request->getContent(); | |
if (!String::equals('sha1='.hash_hmac('sha1', $payload, $this->facebook->getApiSecret()), $request->headers->get('X-Hub-Signature'))) { | |
return new Response('Invalid signature', 400); | |
} | |
$data = json_decode($payload, true); | |
if (null === $data) { | |
return new Response('Invalid data', 400); | |
} | |
$this->logger->debug(sprintf('Processing data from Facebook: %s', $payload)); | |
// TODO: Process | |
} | |
private function processVerificationRequest(Request $request) | |
{ | |
if ('subscribe' !== $request->query->get('hub_mode')) { | |
return new Response(sprintf('Invalid hub mode "%s".', $request->query->get('hub_mode')), 400); | |
} | |
if (!String::equals($this->verifyToken, $request->query->get('hub_verify_token'))) { | |
return new Response('Invalid token', 400); | |
} | |
return new Response($request->query->get('hub_challenge')); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Tests\Facebook; | |
use Facebook\CallbackServer; | |
use Symfony\Component\HttpFoundation\Request; | |
class CallbackServerTest extends \PHPUnit_Framework_TestCase | |
{ | |
public function testProcessWithCallbackVerification() | |
{ | |
$request = Request::create('/', 'GET', array( | |
'hub_mode' => 'subscribe', | |
'hub_challenge' => 'baz', | |
'hub_verify_token' => 'foobar', | |
)); | |
$response = $this->getServer()->processRequest($request); | |
$this->assertEquals('baz', $response->getContent()); | |
$this->assertEquals(200, $response->getStatusCode()); | |
} | |
public function testProcessWithInvalidCallbackVerification() | |
{ | |
$request = Request::create('/', 'GET', array( | |
'hub_mode' => 'subscribe', | |
'hub_challenge' => 'baz', | |
'hub_verify_token' => 'foo', | |
)); | |
$response = $this->getServer()->processRequest($request); | |
$this->assertEquals(400, $response->getStatusCode()); | |
} | |
private function getServer() | |
{ | |
$facebook = $this->getMock('BaseFacebook'); | |
$router = $this->getMock('Symfony\Component\Routing\RouterInterface'); | |
$logger = $this->getMock('Symfony\Component\HttpKernel\Log\LoggerInterface'); | |
return new CallbackServer($facebook, $router, $logger, 'foobar', ''); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment