<?php
namespace App\Controller;
use App\Utils\BigCommerceConfig;
use Guzzle\Http\Client;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class BigCommerceController extends AbstractController
{
private $logger;
public function __construct(LoggerInterface $devdebugLogger) {
$this->logger = $devdebugLogger;
}
public function load(Request $request, BigCommerceConfig $config)
{
// ensure app has minimum configuration
$client_id = $config->getClientId();
if(empty($client_id)) {
return $this->render('/bigcommerce/error.html.twig', array(
'message' => "Missing CLIENT_ID in .env"
));
}
$client_secret = $config->getClientSecret();
if(empty($client_secret)) {
return $this->render('/bigcommerce/error.html.twig', array(
'message' => "Missing CLIENT_SECRET in .env"
));
}
// Ensure request is from BigCommerce environment, or store hash is known in cookie
$cookie_store_hash = $config->getStoreHash();
$signed_payload = $request->query->get('signed_payload');
if(empty($signed_payload)) {
$this->logger->debug('Invalid to request outside of BigCommerce.');
return $this->render('/bigcommerce/error.html.twig', array(
'message' => "Invalid to request outside of BigCommerce"
));
}
$data = $this->verifySignedRequest($signed_payload, $client_secret);
if (empty($data)) {
$this->logger->debug('Invalid signed_payload.');
return $this->render('/bigcommerce/error.html.twig', array(
'message' => "Invalid signed_payload. Is request from BigCommerce?"
));
}
// Don't load the app if not configured completely
$store_hash = $data['store_hash'];
if(!$config->hasAuthToken($store_hash)) {
return $this->render('/bigcommerce/error.html.twig', array(
'message' => "BigCommerce application is not configured completely"
));
}
// Populate the data for the view
$user_email = $data['user']['email'];
$welcome_name = $this->getWelcomeName($user_email, $config);
$view = array(
"welcome_name" => $welcome_name
);
// Render view, and attach critical elements for user-application context
$response = $this->render('/bigcommerce/load.html.twig', $view);
// ! Save the storehash for future loads
$response->headers->setCookie(new Cookie('storehash', $store_hash));
$response->headers->setCookie(new Cookie('user-email', $user_email));
return $response;
}
/**
* Primary Index Page after App is loaded in BigCommerce
*
* @param Request $request
* @param BigCommerceConfig $config
* @return Response
*/
public function home(Request $request, BigCommerceConfig $config)
{
// Get the current user's email
$user_email = '';
$user_email = $request->cookies->get('user-email');
$welcome_name = $this->getWelcomeName($user_email, $config);
$view = array(
"welcome_name" => $welcome_name
);
$cookies = $request->cookies;
$cookies->has('storehash') ? $hash = $cookies->get('storehash') : $hash = null;
if($hash !== null && $hash === $config->getStoreHash()) {
$response = $this->render('/bigcommerce/load.html.twig', $view);
} else {
$this->logger->debug('Invalid to request outside of BigCommerce for /home.');
$response = $this->render('/bigcommerce/error.html.twig', array(
'message' => "Invalid to request outside of BigCommerce"
));
}
// $response = $this->render('/bigcommerce/load.html.twig', $view);
return $response;
}
private function getWelcomeName($user_email, BigCommerceConfig $config) {
// Find a Customer record using the email
// TODO: use the BigCommerce API client
$api_url = $config->get_api_url();
$api_url = $api_url.'/v2/customers?email='.urlencode($user_email);
$data_string = "";
$customrequest = "GET";
$welcome_name = $user_email ?: "John Doe";
$customer = $config->curl($api_url, $data_string, $customrequest);
if(count($customer) > 0)
{
$first_name = $customer[0]['first_name'];
$last_name = $customer[0]['last_name'];
$welcome_name = $first_name . " " . $last_name;
}
return $welcome_name;
}
/**
* BigCommerce application install app auth
*
* @param Request $request
* @param BigCommerceConfig $config
* @return void
*/
public function auth(Request $request, BigCommerceConfig $config)
{
$code = $request->query->get('code');
$scope = $request->query->get('scope');
$context = $request->query->get('context');
if(empty($code)) {
$this->logger->warning('Missing code.');
return $this->render('/bigcommerce/error.html.twig', array(
'message' => "Missing code"
));
}
if(empty($scope)) {
$this->logger->warning('Missing scope.');
return $this->render('/bigcommerce/error.html.twig', array(
'message' => "Missing scope"
));
}
if(empty($code)) {
$this->logger->warning('Missing context.');
return $this->render('/bigcommerce/error.html.twig', array(
'message' => "Missing context"
));
}
$payload = array(
'client_id' => $config->getClientId(),
'client_secret' => $config->getClientSecret(),
'redirect_uri' => $config->getRedirectUri(),
'grant_type' => 'authorization_code',
'code' => $code,
'scope' => $scope,
'context' => $context
);
$client = new Client(getenv('BC_AUTH_SERVICE'));
$req = $client->post('/oauth2/token', array(), $payload, array(
'exceptions' => false
));
$resp = $req->send();
if ($resp->getStatusCode() == 200) {
$data = $resp->json();
list($context, $storehash) = explode('/', $data['context'], 2);
$config->set_app_detail($storehash, $data['access_token']);
$view = array(
"email" => $data['user']['email']
);
return $this->render('/bigcommerce/load.html.twig', $view);
} else {
$this->logger->warning('Something went wrong... [' . $resp->getStatusCode() . '] ' . $resp->getBody());
$view = array("error" => 'Something went wrong... [' . $resp->getStatusCode() . '] ' . $resp->getBody());
return $this->render('error.html.twig', $view);
}
}
/*
* BigCommerce application install app auth
*/
public function remove_user(Request $request)
{
$client_secret=$_ENV['CLIENT_SECRET'];
$data = $this->verifySignedRequest($request->query->get('signed_payload'), $client_secret, $logger);
if (empty($data)) {
$this->logger->warning('Invalid signed_payload.');
return 'Invalid signed_payload.';
}
return '[Remove User] ' . $data['user']['email'];
}
function verifySignedRequest($signedRequest, $client_secret)
{
list($encodedData, $encodedSignature) = explode('.', $signedRequest, 2);
// decode the data
$signature = base64_decode($encodedSignature);
$jsonStr = base64_decode($encodedData);
$data = json_decode($jsonStr, true);
// confirm the signature
$expectedSignature = hash_hmac('sha256', $jsonStr, $client_secret, $raw = false);
if (!hash_equals($expectedSignature, $signature)) {
$this->logger->warning('Bad signed request from BigCommerce!');
return null;
}
return $data;
}
/**
* Configure the static BigCommerce API client with the authorized app's auth token, the client ID from the environment
* and the store's hash as provided.
* @param string $storeHash Store hash to point the BigCommece API to for outgoing requests.
*/
function configureBCApi($storeHash)
{
Bigcommerce::configure(array(
'client_id' => clientId(),
'auth_token' => getAuthToken($storeHash),
'store_hash' => $storeHash
));
}
/**
* @return string Get the app's client ID from the environment vars
*/
function clientId()
{
$clientId = getenv('CLIENT_ID');
return $clientId ?: '';
}
/**
* @return string Get the app's client secret from the environment vars
*/
function clientSecret()
{
$clientSecret = getenv('CLIENT_SECRET');
return $clientSecret ?: '';
}
/**
* @return string Get auth service URL from the environment vars
*/
function bcAuthService()
{
$bcAuthService = getenv('BC_AUTH_SERVICE');
return $bcAuthService ?: '';
}
/**
* @return string Get the callback URL from the environment vars
*/
function callbackUrl()
{
$callbackUrl = getenv('CALLBACK_URL');
return $callbackUrl ?: '';
}
}