/**
  * refresh OAuth token
  * @param ShopInterface $shop
  * @return TokenInterface
  * @throws Exception
  */
 public function refresh(ShopInterface $shop)
 {
     if (!$this->client) {
         throw new Exception('No client specified');
     }
     $token = $shop->getToken();
     $refreshToken = $token->getRefreshToken();
     try {
         $this->client->setRefreshToken($refreshToken);
         $newToken = $this->client->refreshTokens();
         $token->setExpiresAt(new \DateTime('+' . (int) $newToken['expires_in'] . ' seconds'));
         $token->setAccessToken($newToken['access_token']);
         $token->setRefreshToken($newToken['refresh_token']);
         $this->manager->save($token);
     } catch (ClientException $ex) {
         throw new Exception('', 0, $ex);
     }
     return $token;
 }
 /**
  * shop installed an upgraded version
  * @param UpgradeEvent $event
  * @return bool
  */
 public function onUpgrade(UpgradeEvent $event)
 {
     $shop = $this->getShopByEvent($event);
     if (!$shop) {
         return false;
     }
     // todo: refactor this on major change: push application object thru event
     $appData = $event->getApplication();
     $app = new Application($event->getApplicationName(), $appData['app_id'], $appData['app_secret'], $appData['appstore_secret'], null, $this->skipSsl);
     $app->setUserAgent($appData['user_agent']);
     $this->tokenRefresher->setClient($app->getClient($shop));
     $this->tokenRefresher->refresh($shop);
     $shop->setVersion($event->getPayload()['application_version']);
     $this->objectManager->save($shop);
 }
 /**
  * @param FilterControllerEvent $event
  * @throws HttpException
  */
 public function onKernelController(FilterControllerEvent $event)
 {
     // last event used before token invalid exception is thrown
     $this->lastEvent = $event;
     /**
      * @var $controller ApplicationControllerInterface
      */
     $controller = $event->getController();
     /*
      * $controller passed can be either a class or a Closure.
      * This is not usual in Symfony but it may happen.
      * If it is a class, it comes in array format
      */
     if (!is_array($controller)) {
         return;
     }
     // if latest controller on stack is a filtered instance
     if ($controller[0] instanceof ApplicationControllerInterface) {
         // get current request data
         $request = $event->getRequest();
         $requestValidator = new RequestValidator($request);
         try {
             // get parameters
             $appName = $requestValidator->getApplicationName($this->applications);
             $appData = $this->applications[$appName];
             $requestValidator->setApplication($appData);
             $params = $requestValidator->validateAppRequest();
         } catch (InvalidRequestException $ex) {
             // if request is malformed
             throw new BadRequestHttpException('Invalid request');
         }
         // handle shop arguments on iframe (eg. product list checkboxes)
         if ($request->query->has('id')) {
             $ids = $request->query->get('id');
             $idsList = @json_decode($ids);
             $request->query->set('id', $idsList);
         }
         // search for installed shop instance by app
         /**
          * @var $repo ShopRepositoryInterface
          */
         $repo = $this->objectManager->getRepository('DreamCommerce\\ShopAppstoreBundle\\Model\\ShopInterface');
         $shop = $repo->findOneByNameAndApplication($params['shop'], $appName);
         // not installed - throw an error
         if (!$shop) {
             $this->redirect($event, 'not_installed');
         }
         // verify version requirements
         if ($appData['minimal_version'] > 0) {
             if ($shop->getVersion() < $appData['minimal_version']) {
                 $this->redirect($event, 'upgrade');
             }
         }
         // if an application controller needs to be paid
         if ($controller[0] instanceof PaidControllerInterface) {
             $billing = $shop->getBilling();
             if (empty($billing)) {
                 $this->redirect($event, 'unpaid');
             }
         }
         // need a subscription?
         if ($controller[0] instanceof SubscribedControllerInterface) {
             $subscriptions = $shop->getSubscriptions();
             if (!count($subscriptions)) {
                 $this->redirect($event, 'unsubscribed');
             }
             $newest = $subscriptions[0];
             $expires = $newest->getExpiresAt();
             if ($expires < new \DateTime()) {
                 $this->redirect($event, 'not_installed');
             }
         }
         // get shop token
         $token = $shop->getToken();
         // instantiate a client
         /**
          * @var $client Client\Bearer
          */
         $client = $this->applicationRegistry->get($appName)->getClient($shop);
         // token expired - attempt to refresh
         if ($token->getExpiresAt()->getTimestamp() - (new \DateTime())->getTimestamp() < 86400) {
             $this->refresher->setClient($client);
             $this->refresher->refresh($shop);
         }
         // set token on client
         $client->setAccessToken($token->getAccessToken());
         // action performed on token is invalid
         $client->setOnTokenInvalidHandler(array($this, 'invalidTokenRedirect'));
         // pass shop and client
         $controller[0]->injectClient($client, $shop);
         // save variables
         $event->getRequest()->attributes->set('_dream_commerce_shop_appstore_client', $client);
         $event->getRequest()->attributes->set('_dream_commerce_shop_appstore_shop', $shop);
     }
 }