diff --git a/Service/FacebookMessengerService.php b/Service/FacebookMessengerService.php index 53deb6d..038624a 100644 --- a/Service/FacebookMessengerService.php +++ b/Service/FacebookMessengerService.php @@ -6,6 +6,7 @@ use PouleR\FacebookMessengerBundle\Core\Entity\Recipient; use PouleR\FacebookMessengerBundle\Core\Message; use PouleR\FacebookMessengerBundle\Exception\FacebookMessengerException; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; @@ -16,6 +17,11 @@ */ class FacebookMessengerService { + const VERIFY_KEY_HUB_MODE = 'hub_mode'; + const VERIFY_KEY_TOKEN = 'hub_verify_token'; + const VERIFY_KEY_HUB_CHALLENGE = 'hub_challenge'; + const VERIFY_VAL_SUBSCRIBE = 'subscribe'; + const FB_API_URL = 'https://graph.facebook.com/v2.6'; /** @@ -140,6 +146,29 @@ public function getUser($id, array $fields = ['first_name', 'last_name']) return json_decode($this->curlService->get($url, $params), true); } + /** + * Handle a verification token request, check against the given verificationToken. + * Throw an exception when the token is invalid, or return null when the request isn't a verification request. + * + * @param Request $request + * @param string $verificationToken + * @return string|null + * @throws FacebookMessengerException + */ + public function handleVerificationToken(Request $request, $verificationToken) + { + if (!empty($request->get(self::VERIFY_KEY_HUB_MODE))) { + if ($request->get(self::VERIFY_KEY_HUB_MODE) === self::VERIFY_VAL_SUBSCRIBE && + $request->get(self::VERIFY_KEY_TOKEN) === $verificationToken) { + return $request->get(self::VERIFY_KEY_HUB_CHALLENGE); + } + + throw new FacebookMessengerException('Invalid verification token'); + } + + return null; + } + /** * @throws FacebookMessengerException */ diff --git a/Tests/Service/FacebookMessengerServiceTest.php b/Tests/Service/FacebookMessengerServiceTest.php index d927afb..a999fbd 100644 --- a/Tests/Service/FacebookMessengerServiceTest.php +++ b/Tests/Service/FacebookMessengerServiceTest.php @@ -8,6 +8,7 @@ use PouleR\FacebookMessengerBundle\Core\Message; use PouleR\FacebookMessengerBundle\Service\CurlService; use PouleR\FacebookMessengerBundle\Service\FacebookMessengerService; +use Symfony\Component\HttpFoundation\Request; /** * Class FacebookMessengerServiceTest. @@ -123,4 +124,80 @@ public function testGetUser() self::assertEquals('Unit', $result['first_name']); self::assertEquals('Test', $result['last_name']); } + + /** + * Test if null is returned when there is no hub_mode set in the request + */ + public function testEmptyVerificationToken() + { + $request = $this->getMockBuilder(Request::class) + ->disableOriginalConstructor() + ->getMock(); + + $request->expects($this->exactly(1)) + ->method('get') + ->withConsecutive(['hub_mode']) + ->willReturnOnConsecutiveCalls(null); + + $service = new FacebookMessengerService(new CurlService()); + $challenge = $service->handleVerificationToken($request, '12345'); + self::assertNull($challenge); + } + + /** + * Test if an exception is thrown when the verification token is incorrect + * + * @expectedException \PouleR\FacebookMessengerBundle\Exception\FacebookMessengerException + */ + public function testInvalidVerificationToken() + { + $request = $this->getMockBuilder(Request::class) + ->disableOriginalConstructor() + ->getMock(); + + $request->expects($this->exactly(3)) + ->method('get') + ->withConsecutive( + ['hub_mode'], + ['hub_mode'], + ['hub_verify_token'] + ) + ->willReturnOnConsecutiveCalls( + 'subscribe', + 'subscribe', + '12345' + ); + + $service = new FacebookMessengerService(new CurlService()); + $service->handleVerificationToken($request, '98765'); + } + + /** + * Test a valid verification token + */ + public function testValidVerificationToken() + { + $request = $this->getMockBuilder(Request::class) + ->disableOriginalConstructor() + ->getMock(); + + $request->expects($this->exactly(4)) + ->method('get') + ->withConsecutive( + ['hub_mode'], + ['hub_mode'], + ['hub_verify_token'], + ['hub_challenge'] + ) + ->willReturnOnConsecutiveCalls( + 'subscribe', + 'subscribe', + '12345', + 'challenge_code' + ); + + $service = new FacebookMessengerService(new CurlService()); + $challenge = $service->handleVerificationToken($request, '12345'); + self::assertEquals('challenge_code', $challenge); + } }