Pretty basic question and I am sorry for that but I haven't find the answer to my problem yet
I have an getArticleUrl method that returns $this->urlGenerator->generate($article);
In my function, all I need to do is to append the query params to the articleUrl
public function articleController(Request $request, string $uuid)
{
$queryParams = $request->query->all();
$articleUrl = $this->getArticleUrl($uuid);
$redirectUrl = append somehow the query params;
return new RedirectResponse($redirectUrl, 301);
}
I tried to use the generate method again but it didn't work as I supposed it already has the domain in it and it will duplicate it
$redirectUrl = $this->urlGenerator->generate($articleUrl, $queryParams, UrlGeneratorInterface::ABSOLUTE_URL);
or perhaps I could get only the path from $articleUrl and call the generate for the new path and that could work, but it didn't
public function articleController(Request $request, string $uuid)
{
$queryParams = $request->query->all();
$articleUrl = $this->getArticleUrl($uuid);
$parsed = parse_url($articleUrl);
$path = $parsed['path'];
if ($path) {
$redirectUrl = $this->urlGenerator->generate($path, $queryParams);
} else {
$redirectUrl = $articleUrl;
}
return new RedirectResponse($redirectUrl, 301);
}
You could use http_build_query
public function articleController(Request $request, string $uuid)
{
$queryParams = $request->query->all();
$articleUrl = $this->getArticleUrl($uuid);
$redirectUrl = $articleUrl . '?' . http_build_query($queryParams);
return new RedirectResponse($redirectUrl, 301);
}
More Info: https://www.php.net/manual/en/function.http-build-query.php
Related
I am fairly new to Laravel. This may have an obvious solution but I can't seem to find it so far. Therefore I am asking for help.
Question In Short:
I use Illuminate\Http\Request session ($request->session()) to store some data I get from BigCommerce API. But I can't get them when I need the data.
Context:
I am building a sample app/boilerplate app for BigCommerce platform using Laravel/React. I have built the app using official documentation, semi-official posts released by BigCommerce team and sample codebase provided by them as well.
App works fine with local credentials from a specific store because they are given as environment variables to the app. However I can't read store_hash (which is necessary to fetch data from BigCommerce) and access token. Both I have put in $request->session() object.
I will paste the AppController.php code below, also code is publicly available here:
In the makeBigCommerceAPIRequest method below (as you can see my debugging efforts :)) I can get $this->getAppClientId(), but I can't get anything from $request->session()->get('store_hash') or $request->session()->get('access_token') which returns from $this->getAccessToken($request).
I have tried putting store hash into a global variable, but it didn't work.
From everything I have experienced so far, $request is not working as expected.
Any help appriciated, thanks in advance.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use mysql_xdevapi\Exception;
use Oseintow\Bigcommerce\Bigcommerce;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Bigcommerce\Api\Client as BigcommerceClient;
use Illuminate\Support\Facades\Storage;
use App\Config; //Database Connection
use Bigcommerce\Api\Connection;
class AppController extends Controller
{
protected $bigcommerce;
private $client_id;
private $client_secret;
private $access_token;
private $storehash;
private $redirect_uri;
public function __construct(Bigcommerce $bigcommerce)
{
$this->bigcommerce = $bigcommerce;
$this->client_id = \config('app.clientId');
$this->client_secret = \config('app.clientSecret');
$this->redirect_uri = \config('app.authCallback');
}
public function getAppClientId()
{
if (\config('app.appEnv') === 'local') {
return \config('app.localClientId');
} else {
return \config('app.clientId');
}
}
public function getAppSecret()
{
if (\config('app.appEnv') === 'local') {
return \config('app.localClientSecret');
} else {
return \config('app.clientSecret');
}
}
public function getAccessToken(Request $request)
{
if (\config('app.appEnv') === 'local') {
return \config('app.localAccessToken');
} else {
return $request->session()->get('access_token');
}
}
public function getStoreHash(Request $request)
{
if (\config('app.appEnv') === 'local') {
return \config('app.localStoreHash');
} else {
return $request->session()->get('store_hash');
}
}
public function error(Request $request)
{
$errorMessage = "Internal Application Error";
if ($request->session()->has('error_message')) {
$errorMessage = $request->session()->get('error_message');
}
echo '<h4>An issue has occurred:</h4> <p>' . $errorMessage . '</p> Go back to home';
}
public function load(Request $request)
{
$signedPayload = $request->get('signed_payload');
if (!empty($signedPayload)) {
echo "hello";
$verifiedSignedRequestData = $this->verifySignedRequest($signedPayload);
if ($verifiedSignedRequestData !== null) {
echo "positive return";
$request->session()->put('user_id', $verifiedSignedRequestData['user']['id']);
$request->session()->put('user_email', $verifiedSignedRequestData['user']['email']);
$request->session()->put('owner_id', $verifiedSignedRequestData['owner']['id']);
$request->session()->put('owner_email', $verifiedSignedRequestData['owner']['email']);
$request->session()->put('store_hash', $verifiedSignedRequestData['context']);
echo $request->session()->get('store_hash');
$this->storehash = $verifiedSignedRequestData['context'];
echo ' store hash is at the moment : ' . $this->storehash . ' .....';
} else {
return "The signed request from BigCommerce could not be validated.";
// return redirect()->action([AppController::class, 'error'])->with('error_message', 'The signed request from BigCommerce could not be validated.');
}
} else {
return "The signed request from BigCommerce was empty.";
// return redirect()->action([AppController::class, 'error'])->with('error_message', 'The signed request from BigCommerce was empty.');
}
return redirect(\config('app.appUrl'));
}
public function install(Request $request)
{
// Make sure all required query params have been passed
if (!$request->has('code') || !$request->has('scope') || !$request->has('context')) {
echo 'Not enough information was passed to install this app.';
// return redirect()->action('MainController#error')->with('error_message', 'Not enough information was passed to install this app.');
}
try {
$client = new Client();
$result = $client->request('POST', 'https://login.bigcommerce.com/oauth2/token', [
'json' => [
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'redirect_uri' => $this->redirect_uri,
'grant_type' => 'authorization_code',
'code' => $request->input('code'),
'scope' => $request->input('scope'),
'context' => $request->input('context'),
]
]);
$statusCode = $result->getStatusCode();
$data = json_decode($result->getBody(), true);
if ($statusCode == 200) {
$request->session()->put('store_hash', $data['context']);
$request->session()->put('access_token', $data['access_token']);
$request->session()->put('user_id', $data['user']['id']);
$request->session()->put('user_email', $data['user']['email']);
// $configValue = Config::select('*')->where('storehash', $data['context'])->get()->toArray();
// if (count($configValue) != 0) {
// $id = $configValue[0]['id'];
// $configObj = Config::find($id);
// $configObj->access_token = $data['access_token'];
// $configObj->save();
// } else {
// $configObj = new Config;
// $configObj->email = $data['user']['email'];
// $configObj->storehash = $data['context'];
// $configObj->access_token = $data['access_token'];
// $configObj->save();
// }
// If the merchant installed the app via an external link, redirect back to the
// BC installation success page for this app
if ($request->has('external_install')) {
return redirect('https://login.bigcommerce.com/app/' . $this->getAppClientId() . '/install/succeeded');
}
}
return redirect(\config('app.appUrl'));
} catch (RequestException $e) {
$statusCode = $e->getResponse()->getStatusCode();
echo $statusCode;
$errorMessage = "An error occurred.";
if ($e->hasResponse()) {
if ($statusCode != 500) {
echo "some error other than 500";
// $errorMessage = Psr7\str($e->getResponse());
}
}
// If the merchant installed the app via an external link, redirect back to the
// BC installation failure page for this app
if ($request->has('external_install')) {
return redirect('https://login.bigcommerce.com/app/' . $this->getAppClientId() . '/install/failed');
} else {
echo "fail";
// return redirect()->action('MainController#error')->with('error_message', $errorMessage);
}
}
// return view('index');
}
public function verifySignedRequest($signedRequest)
{
list($encodedData, $encodedSignature) = explode('.', $signedRequest, 2);
// decode the data
$signature = base64_decode($encodedSignature);
$jsonStr = base64_decode($encodedData);
echo $jsonStr;
$data = json_decode($jsonStr, true);
// confirm the signature
$expectedSignature = hash_hmac('sha256', $jsonStr, $this->client_secret, $raw = false);
if (!hash_equals($expectedSignature, $signature)) {
error_log('Bad signed request from BigCommerce!');
return null;
}
return $data;
}
public function makeBigCommerceAPIRequest(Request $request, $endpoint)
{
echo ' ...... trying to make an apiRequest now : with storehash : ' . $this->storehash . ' .............';
echo '...........................................';
echo 'other variables at the moment :::: ............... client ID :' . $this->getAppClientId() . '...................... token : ' . $this->getAccessToken($request) . '...............';
$requestConfig = [
'headers' => [
'X-Auth-Client' => $this->getAppClientId(),
'X-Auth-Token' => $this->getAccessToken($request),
'Content-Type' => 'application/json',
]
];
if ($request->method() === 'PUT') {
$requestConfig['body'] = $request->getContent();
}
$client = new Client();
$result = $client->request($request->method(), 'https://api.bigcommerce.com/' . $this->storehash . '/' . $endpoint, $requestConfig);
return $result;
}
public function proxyBigCommerceAPIRequest(Request $request, $endpoint)
{
if (strrpos($endpoint, 'v2') !== false) {
// For v2 endpoints, add a .json to the end of each endpoint, to normalize against the v3 API standards
$endpoint .= '.json';
}
echo ' asadssada ...... trying to make an apiRequest now : with storehash : ' . $this->storehash . ' .............' . $request->session()->get('store_hash') . ' ............ ';
$result = $this->makeBigCommerceAPIRequest($request, $endpoint);
return response($result->getBody(), $result->getStatusCode())->header('Content-Type', 'application/json');
}
}
Thanks for the detailed info. Though it would help to annotate the debug lines with confirmation of what they output, I am making the assumption that you have narrowed the problem down to the session storage and retrieval lines.
$request->session()->put() and get() are the correct ways to access session.
I would therefore suggest investigating Session configuration: https://laravel.com/docs/8.x/session#configuration
If using file-based sessions, confirm that there are no permissions errors, perhaps. Alternatively try and different session storage mechanism.
I try to post an article to Bexio via the Bexio API: https://docs.bexio.com/resources/article/
There is also a sample for PHP: https://docs.bexio.com/samples/
I updated the scopes in the config.php to allow read and write articles.
I updates the bexioConnector.class.php so i can get Articles (works):
public function getArticles($urlParams = array()) {
return $this->call('article', $urlParams);
}
public function call($ressource, $urlParams = array(), $postParams = array(), $method = Curl::METHOD_GET) {
$url = $this->api_url . "/" . $this->org . "/" . $ressource;
$data = $this->curl->call($url, $urlParams, $postParams, $method, $this->getDefaultHeaders());
return json_decode($data, true);
}
So i can use now this code to get all articles (works):
$bexioProducts = $con->getArticles(array('order_by' => 'id'));
Now i want to create articles with the POST method.
So i added this function to the bexioConnector.class.php
public function postArticle($postParams = array(), $urlParams = array()) {
return $this->call('article', $urlParams, $postParams, Curl::METHOD_POST);
}
So i use this code to create a product:
$con->postArticle(array(
'intern_code' => "SKU-3214"
)
);
But this ends in an error:
{"error_code":415,"message":"Could not parse the data."}
I have tried a lot but i always get the same error message.
What could i have don possibly wrong?
I found the error. I need to encode it as a json first.
So i changed my postArticle function:
public function postArticle($postParams = array(), $urlParams = array()) {
$json = json_encode($postParams);
return $this->call('article', $urlParams, $json, Curl::METHOD_POST);
}
I'm making a toolkit for php applications. I've a made a routing system based on some conventions, it works well but i would like to learn how to make mod_rewrite rules or any other stuff to finally make the url good to see and good for seo.
The route system starts from a config file that set the app and url roots.
$app_root = $_SERVER["DOCUMENT_ROOT"].dirname($_SERVER["PHP_SELF"])."/";
$app_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/';
define("APP_URL",$app_url);
define("APP_ROOT",$app_root);
The route always get start from index.php, wich makes instances of controllers#actions from GET parameters controllers=?&action=?
This is the index.php
<?php
include_once 'controller/Frontend.php';
require 'libraries/Router.php';
$params=array();
if(isset($_GET['controller'])&&isset($_GET['action'])){
$c = $_GET['controller'];
$a = $_GET['action'];
// add all query string additional params to method signature i.e. &id=x&category=y
$queryParams = array_keys($_GET);
$queryValues = array_values($_GET);
for ($i=2;$i<count($queryParams);$i++) {
$params[$queryParams[$i]] = $queryValues[$i];
}
if ($_POST) {
// add all query string additional params to method signature i.e. &id=x&category=y
$queryParams = array_keys($_POST);
$queryValues = array_values($_POST);
for ($i=0;$i<count($_POST);$i++) {
$params[$queryParams[$i]] = $queryValues[$i];
}
}
include_once APP_ROOT."/controller/$c.php";
$controller = new $c();
$controller->$a($params);
} else {
//attiva controller predefinito
$controller = new Frontend();
$controller->index();
}
This allow to select what controller and what action the router must call.
The router function here get the APP URL from settings.php in the root. You give im the two controllers#action params as string and it make the URL like so:
index.php?controller=X&action=Y&[params...]
<?php
require './settings.php';
function router($controller,$action,$query_data="") {
$param = is_array($query_data) ? http_build_query($query_data) : "$query_data";
$url = APP_URL."index.php?controller=$controller&action=$action&$param";
return $url;
}
function relativeRouter ($controller,$action,$query_data=""){
$param = is_array($query_data) ? http_build_query($query_data) : "$query_data";
$url = "index.php?controller=$controller&action=$action&$param";
return $url;
}
function redirectToOriginalUrl() {
$url = $_SERVER['HTTP_REQUEST_URI'];
header("location: $url");
}
function switchAction ($controller, $action) {
$r = router($controller, $action);
header("location:$r", true, 302);
}
In templates file i call router('controller,'action') to retrive url's to actions and also pass GET/POST data (collected from index.php that put's them into the method signature as array).
Don't blame me for using global POST/GET without filtering i'm still developing the thing, security things will be made after ;)
What i would like to ask if someone could share some thoughts on how to make pretty urls like site/page/action....
For example www.site.com/blog/post?id=1
(Actually the N params in the router function ($query_data) works this way, you pass array['id' => '1'] and you get ?id=1)
What are best strategies to make good urls?
Thank you so much, still learning PHP.
If there are best way to do such things just give your feedback.
I found myself an answer to the question, i post here maybe it's useful.
I've added a .htaccess file in the root:
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
This will return each request to the root/index.php file.
Index file collect routes from the HTTP request, check if the route exist in the "routes.json" file.
URL are written in this way:
site.com/controller/action. GET params are written as follows
site.com/controller/action/[params]/[value]...... This output for example site.com/blog/post/id/1
That should be also fine for REST.
Here the index.php
<?php
require 'controller/Frontend.php';
require 'Class/Router.php';
//require 'libraries/Router.php';
/*
* ** ROUTING SETTINGS **
*/
$app_root = $_SERVER["DOCUMENT_ROOT"].dirname($_SERVER["PHP_SELF"])."/";
$app_url = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/';
define("APP_URL",$app_url);
define("APP_ROOT",$app_root);
$basepath = implode('/', array_slice(explode('/', $_SERVER['SCRIPT_NAME']), 0, -1));
$uri = substr($_SERVER['REQUEST_URI'], strlen($basepath));
//echo $uri;
if ($uri == "/") {
$frontend = new Frontend();
$frontend->index();
} else {
$root = ltrim ($uri, '/');
//$paths = explode("/", $uri);
$paths = parse_url($root, PHP_URL_PATH);
$route = explode("/",$paths);
$request = new \PlayPhp\Classes\Request();
// controller
$c = $route[0];
// action
$a = $route[1];
$reverse = Router::inverseRoute($c,$a);
$rest = $_SERVER['REQUEST_METHOD'];
switch ($rest) {
case 'PUT':
//rest_put($request);
break;
case 'POST':
if (Router::checkRoutes($reverse, "POST")) {
foreach ($_POST as $name => $value) {
$request->setPost($name,$value);
}
break;
} else {
Router::notFound($reverse,"POST");
}
case 'GET':
if (Router::checkRoutes($reverse, "GET")) {
for ($i = 2; $i < count($route); $i++) {
$request->setGet($route[$i], $route[++$i]);
}
break;
} else {
Router::notFound($reverse,"GET");
}
break;
case 'HEAD':
//rest_head($request);
break;
case 'DELETE':
//rest_delete($request);
break;
case 'OPTIONS':
//rest_options($request);
break;
default:
//rest_error($request);
break;
}
include_once APP_ROOT.'controller/'.$c.'.php';
$controller = new $c();
$controller->$a($request);
}
The Router class:
<?php
include 'config/app.php';
/*
* Copyright (C) 2015 yuri.blanc
*/
require 'Class/http/Request.php';
class Router {
protected static $routes;
private function __construct() {
Router::$routes = json_decode(file_get_contents(APP_ROOT.'config/routes.json'));
}
public static function getInstance(){
if (Router::$routes==null) {
new Router();
}
return Router::$routes;
}
public static function go($action,$params=null) {
$actions = explode("#", $action);
$c = strtolower($actions[0]);
$a = strtolower($actions[1]);
// set query sting to null
$queryString = null;
if(isset($params)) {
foreach ($params as $name => $value) {
$queryString .= '/'.$name.'//'.$value;
}
return APP_URL."$c/$a$queryString";
}
return APP_URL."$c/$a";
}
public static function checkRoutes($action,$method){
foreach (Router::getInstance()->routes as $valid) {
/* echo $valid->action . ' == ' . $action . '|||';
echo $valid->method . ' == ' . $method . '|||';*/
if ($valid->method == $method && $valid->action == $action) {
return true;
}
}
}
public static function inverseRoute($controller,$action) {
return ucfirst($controller)."#".$action;
}
public static function notFound($action,$method) {
die("Route not found:: $action with method $method");
}
}
I use the json_decode function to parse the json object in stdClass().
The json file looks like this:
{"routes":[
{"action":"Frontend#index", "method":"GET"},
{"action":"Frontend#register", "method":"GET"},
{"action":"Frontend#blog", "method":"GET"}
]}
This way i can whitelist routes with their methods and return 404 errors while not found.
System is still quite basic but gives and idea and works, hope someone will find useful.
Im using a code to separate pages that is HTTPS and HTTP in my website
The problem is: When Im on HTTP, links to HTTPS no have WWW and vice versa.
I did not find the problem in the script.
public function createUrl($route, $params = array(), $ampersand = '&')
{
$url = parent::createUrl($route, $params, $ampersand);
// If already an absolute URL, return it directly
if (strpos($url, 'http') === 0) {
return $url;
}
// Check if the current protocol matches the expected protocol of the route
// If not, prefix the generated URL with the correct host info.
$secureRoute = $this->isSecureRoute($route);
if (Yii::app()->request->isSecureConnection) {
return $secureRoute ? $url : 'http://' . Yii::app()->request->serverName . $url;
} else {
return $secureRoute ? 'https://' . Yii::app()->request->serverName . $url : $url;
}
}
public function parseUrl($request)
{
$route = parent::parseUrl($request);
// Perform a 301 redirection if the current protocol
// does not match the expected protocol
$secureRoute = $this->isSecureRoute($route);
$sslRequest = $request->isSecureConnection;
if ($secureRoute !== $sslRequest) {
$hostInfo = $secureRoute ? 'https://' . Yii::app()->request->serverName : 'http://' . Yii::app()->request->serverName;
if ((strpos($hostInfo, 'https') === 0) xor $sslRequest) {
$request->redirect($hostInfo . $request->url, true, 301);
}
}
return $route;
}
private $_secureMap;
/**
* #param string the URL route to be checked
* #return boolean if the give route should be serviced in SSL mode
*/
protected function isSecureRoute($route)
{
if ($this->_secureMap === null) {
foreach ($this->secureRoutes as $r) {
$this->_secureMap[strtolower($r)] = true;
}
}
$route = strtolower($route);
if (isset($this->_secureMap[$route])) {
return true;
} else {
return ($pos = strpos($route, '/')) !== false
&& isset($this->_secureMap[substr($route, 0, $pos)]);
}
}
}
Code adapted from: http://www.yiiframework.com/wiki/407/url-management-for-websites-with-secure-and-nonsecure-pages/
It's better to manage this at the controller level using filters.
In your components directory setup 2 filters HttpsFilter and HttpFilter as follows:-
class HttpsFilter extends CFilter {
protected function preFilter( $filterChain ) {
if ( !Yii::app()->getRequest()->isSecureConnection ) {
# Redirect to the secure version of the page.
$url = 'https://' .
Yii::app()->getRequest()->serverName .
Yii::app()->getRequest()->requestUri;
Yii::app()->request->redirect($url);
return false;
}
return true;
}
}
and
class HttpFilter extends CFilter {
protected function preFilter( $filterChain ) {
if ( Yii::app()->getRequest()->isSecureConnection ) {
# Redirect to the secure version of the page.
$url = 'http://' .
Yii::app()->getRequest()->serverName .
Yii::app()->getRequest()->requestUri;
Yii::app()->request->redirect($url);
return false;
}
return true;
}
}
then in each controller force https using the filters, optionally by action:
class SiteController extends Controller {
public function filters()
{
return array(
'https +index', // Force https, but only on login page
);
}
}
Edit: if the filters() function above doesn't seem to work for you, instead try
return array(
array('HttpsFilter +index'), // Force https, but only on login page
);
See http://www.yiiframework.com/doc/guide/1.1/en/basics.controller#filter (and comments on it).
I tried to find out gotowebinar api in php but didn't get it. So, I have tried to write a simple class which can be useful. It does authentication which is same for gotowebinar, gotomeeting and rest. It fetches the upcoming webinar, all webinars, single webinar information, registrants fields and also create registrant. Now you all can enhance it as you want. Any suggestion would be much appericiated.
help.txt
1) First change the GOTO_WEBINAR_API_KEY in
gotoWebinarClass.php to your appication key.
2) Then change the
REDIRECT_URL_AFTER_AUTHENTICATION in
authorize.php. It is a url where one should be redirected after
authentication.
3) Execute authorize.php.
4) After you autheticate,
it would take you to
REDIRECT_URL_AFTER_AUTHENTICATION with "code" in the query
string.
5) Copy that code and execute the authorize.php again with ?
code='your_code' in the query string.
6) If everything goes fine, we will get the token and we will set into session and be redirected to get-all-webinars.php
which fetches user's all webinars.
This class is not complete, I have laid down the basic
foundation, now you can keep on adding the other functions. Any
suggestion from your side would be much appriciated. Thanks.
gotoWebinarClass.php
<?php
define('GOTO_WEBINAR_API_KEY','your gotowebinar application key');
class OAuth_En{
protected $_accessToken;
protected $_userId;
protected $_organizerKey;
protected $_refreshToken;
protected $_expiresIn;
public function getAccessToken(){
return $this->_accessToken;
}
public function setAccessToken($token){
$this->_accessToken = $token;
}
public function getUserId(){
return $this->_userId;
}
public function setUserId($id){
$this->_userId = $id;
}
public function getOrganizerKey(){
return $this->_organizerKey;
}
public function setOrganizerKey($key){
$this->_organizerKey = $key;
}
public function getRefreshToken(){
return $this->_refreshToken;
}
public function setRefreshToken($token){
$this->_refreshToken = $token;
}
public function getExpiresIn(){
return $this->_expiresIn;
}
public function setExpiresIn($expiresIn){
$this->_expiresIn = $expiresIn;
}
}
class OAuth_Db{
function getToken(){
}
}
class OAuth{
protected $_redirectUrl;
protected $_OAuthEnObj;
protected $_curlHeader = array();
protected $_apiResponse;
protected $_apiError;
protected $_apiErrorCode;
protected $_apiRequestUrl;
protected $_apiResponseKey;
protected $_accessTokenUrl;
protected $_webinarId;
protected $_registrantInfo = array();
protected $_apiRequestType;
protected $_apiPostData;
public function __construct(OAuth_En $oAuthEn){
$this->_OAuthEnObj = $oAuthEn;
}
public function getOAuthEntityClone(){
return clone $this->_OAuthEnObj;
}
public function getWebinarId(){
return $this->_webinarId;
}
public function setWebinarId($id){
$id = (int)$id;
$this->_webinarId = empty($id) ? 0 : $id;
}
public function setApiErrorCode($code){
$this->_apiErrorCode = $code;
}
public function getApiErrorCode(){
return $this->_apiErrorCode;
}
public function getApiAuthorizationUrl(){
return 'https://api.citrixonline.com/oauth/authorize?client_id='.GOTO_WEBINAR_API_KEY.'&redirect_uri='.$this->getRedirectUrl();
}
public function getApiKey(){
return GOTO_WEBINAR_API_KEY;
}
public function getApiRequestUrl(){
return $this->_apiRequestUrl;
}
public function setApiRequestUrl($url){
$this->_apiRequestUrl = $url;
}
public function setRedirectUrl($url){
$this->_redirectUrl = urlencode($url);
}
public function getRedirectUrl(){
return $this->_redirectUrl;
}
public function setCurlHeader($header){
$this->_curlHeader = $header;
}
public function getCurlHeader(){
return $this->_curlHeader;
}
public function setApiResponseKey($key){
$this->_apiResponseKey = $key;
}
public function getApiResponseKey(){
return $this->_apiResponseKey;
}
public function setRegistrantInfo($arrInfo){
$this->_registrantInfo = $arrInfo;
}
public function getRegistrantInfo(){
return $this->_registrantInfo;
}
public function authorizeUsingResponseKey($responseKey){
$this->setApiResponseKey($responseKey);
$this->setApiTokenUsingResponseKey();
}
protected function setAccessTokenUrl(){
$url = 'https://api.citrixonline.com/oauth/access_token?grant_type=authorization_code&code={responseKey}&client_id={api_key}';
$url = str_replace('{api_key}', $this->getApiKey(), $url);
$url = str_replace('{responseKey}', $this->getApiResponseKey(), $url);
$this->_accessTokenUrl = $url;
}
protected function getAccessTokenUrl(){
return $this->_accessTokenUrl;
}
protected function resetApiError(){
$this->_apiError = '';
}
public function setApiTokenUsingResponseKey(){
//set the access token url
$this->setAccessTokenUrl();
//set the url where api should go for request
$this->setApiRequestUrl($this->getAccessTokenUrl());
//make request
$this->makeApiRequest();
if($this->hasApiError()){
echo $this->getApiError();
}else{
//if api does not have any error set the token
echo $this->getResponseData();
$responseData = json_decode($this->getResponseData());
$this->_OAuthEnObj->setAccessToken($responseData->access_token);
$this->_OAuthEnObj->setOrganizerKey($responseData->organizer_key);
$this->_OAuthEnObj->setRefreshToken($responseData->refresh_token);
$this->_OAuthEnObj->setExpiresIn($responseData->expires_in);
}
}
function hasApiError(){
return $this->getApiError() ? 1 : 0;
}
function getApiError(){
return $this->_apiError;
}
function setApiError($errors){
return $this->_apiError = $errors;
}
function getApiRequestType(){
return $this->_apiRequestType;
}
function setApiRequestType($type){
return $this->_apiRequestType = $type;
}
function getResponseData(){
return $this->_apiResponse;
}
function setApiPostData($data){
return $this->_apiPostData = $data;
}
function getApiPostData(){
return $this->_apiPostData;
}
function makeApiRequest(){
$header = array();
$this->getApiRequestUrl();
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_URL, $this->getApiRequestUrl());
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if($this->getApiRequestType()=='POST'){
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->getApiPostData());
}
if($this->getCurlHeader()){
$headers = $this->getCurlHeader();
}else{
$headers = array(
"HTTP/1.1",
"Content-type: application/json",
"Accept: application/json",
"Authorization: OAuth oauth_token=".$this->_OAuthEnObj->getAccessToken()
);
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$data = curl_exec($ch);
$validResponseCodes = array(200,201,409);
$responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$this->resetApiError();
if (curl_errno($ch)) {
$this->setApiError(array(curl_error($ch)));
} elseif(!in_array($responseCode, $validResponseCodes)){
if($this->isJsonString($data)){
$data = json_decode($data);
}
$this->setApiError($data);
$this->setApiErrorCode($responseCode);
}else {
$this->_apiResponse = $data;
$_SESSION['gotoApiResponse'] = $this->getResponseData();
curl_close($ch);
}
}
function isAuthorizationRequiredAgain(){
$arrAuthorizationRequiredCodes = array(400,401,403,500);
$isAuthRequired = 0;
$error = $this->getApiError();
$responseCode = $this->getApiErrorCode();
//we might have to add more exception in this condition
if(in_array($responseCode, $arrAuthorizationRequiredCodes)){
if($responseCode==400 && is_object($error)){ //because for 400 error sometime one needs to authenticate again
foreach($error as $single){
$pos = strpos($single,'Authorization');
if($pos!==false){
$isAuthRequired = 1;
}
}
}else{
$isAuthRequired = 1;
}
}
return $isAuthRequired;
}
function getWebinars(){
$url = 'https://api.citrixonline.com/G2W/rest/organizers/'.$this->_OAuthEnObj->getOrganizerKey().'/webinars';
$this->setApiRequestUrl($url);
$this->setApiRequestType('GET');
$this->makeApiRequest();
if($this->hasApiError()){
return null;
}
$webinars = json_decode($this->getResponseData());
return $webinars;
}
function getWebinar(){
if(!$this->getWebinarId()){
$this->setApiError(array('Webinar id not provided'));
return null;
}
$this->setApiRequestType('GET');
$url = 'https://api.citrixonline.com/G2W/rest/organizers/'.$this->_OAuthEnObj->getOrganizerKey().'/webinars/'.$this->getWebinarId();
$this->setApiRequestUrl($url);
$this->makeApiRequest();
if($this->hasApiError()){
return null;
}
$webinar = json_decode($this->getResponseData());
return $webinar;
}
function getUpcomingWebinars(){
$url = 'https://api.citrixonline.com/G2W/rest/organizers/'.$this->_OAuthEnObj->getOrganizerKey().'/upcomingWebinars';
$this->setApiRequestUrl($url);
$this->setApiRequestType('GET');
$this->makeApiRequest();
if($this->hasApiError()){
return null;
}
$webinars = json_decode($this->getResponseData());
return $webinars;
}
function createRegistrant(){
if(!$this->getWebinarId()){
$this->setApiError(array('Webinar id not provided'));
return null;
}
if(!$this->getRegistrantInfo()){
$this->setApiError(array('Registrant info not provided'));
return null;
}
$this->setApiRequestType('POST');
$this->setApiPostData(json_encode($this->getRegistrantInfo()));
$url = 'https://api.citrixonline.com/G2W/rest/organizers/'.$this->_OAuthEnObj->getOrganizerKey().'/webinars/'.$this->getWebinarId().'/registrants';
$this->setApiRequestUrl($url);
$this->makeApiRequest();
if($this->hasApiError()){
return null;
}
$webinar = json_decode($this->getResponseData());
return $webinar;
}
function getWebinarRegistrantsFields(){
if(!$this->getWebinarId()){
$this->setApiError(array('Webinar id not provided'));
return null;
}
$url = 'https://api.citrixonline.com/G2W/rest/organizers/'.$this->_OAuthEnObj->getOrganizerKey().'/webinars/'.$this->getWebinarId().'/registrants/fields';
$this->setApiRequestUrl($url);
$this->setApiRequestType('GET');
$this->makeApiRequest();
if($this->hasApiError()){
return null;
}
$registrantFields = json_decode($this->getResponseData());
return $registrantFields;
}
function isJsonString($string){
$isJson = 0;
$decodedString = json_decode($string);
if(is_array($decodedString) || is_object($decodedString))
$isJson = 1;
return $isJson;
}
}
Authorize.php
<?php
include_once "gotoWebinarClass.php";
define('REDIRECT_URL_AFTER_AUTHENTICATION','http://url where we want to redirect'); //this is the url where your get token code would be written.
session_start();
$obj = new OAuth_En();
$oauth = new OAuth($obj);
if(!isset($_GET['code'])){
goForAuthorization();
}else{ //when user authenticates and redirect back to application redirect url, get the token
$oauth->authorizeUsingResponseKey($_GET['code']);
if(!$oauth->hasApiError()){
$objOAuthEn = $oauth->getOAuthEntityClone();
$_SESSION['oauthEn'] = serialize($objOAuthEn);
header('Location: get-all-webinars.php');
}
}
//this function has been used for getting the key using which we can get the access token and organizer key
function goForAuthorization(){
global $oauth;
$oauth->setRedirectUrl(REDIRECT_URL_AFTER_AUTHENTICATION);
$url = $oauth->getApiAuthorizationUrl();
header('Location: '.$url);
}
get-all-webinars.php
<?php
include_once "gotoWebinarClass.php";
session_start();
$obj = unserialize($_SESSION['oauthEn']);
/*
this can be used to fetch the stored access token key and organizer key from database and use it without asking the authetication from user again
$obj = new OAuth_En();
$obj->setAccessToken('token');
$obj->setOrganizerKey('organizer key');
*/
$oauth = new OAuth($obj);
$webinars = $oauth->getWebinars();
echo '<pre>';
if(!$oauth->hasApiError()){
print_r($webinars);
}else{
print_r($oauth->getApiError());
}
exit;
/*$webinars = $oauth->getUpcomingWebinars();
if(!$oauth->hasApiError()){
print_r($webinars);
}else{
print_r($oauth->getApiError());
}
exit;
$registrantInfo = array(
"firstName"=>"ashish",
"lastName"=>"mehta",
"email"=>"test#test.com",
);
$oauth->setWebinarId(525120321);
$oauth->setRegistrantInfo($registrantInfo);
$res = $oauth->createRegistrant();
echo $oauth->getApiErrorCode();
if(!$oauth->hasApiError()){
print_r($res);
}else{
echo 'error';
print_r($oauth->getApiError());
}
exit;
$oauth->setWebinarId(525120321);
$webinar = $oauth->getWebinar();
if(!$oauth->hasApiError()){
print_r($webinar);
}else{
print_r($oauth->getApiError());
echo $oauth->getApiErrorCode();
}
*/
Suggestion #1: AMAZING CLASS! :)
Suggestion #2: Because I didn't really have to do any actual "work" to implement your class, I had some trouble with submitting custom question responses when creating a registrant.
This is because if you use custom fields, you need to add an additional parameter to the header:
Accept: application/vnd.citrix.g2wapi-v1.1+json
Other than that this class is MONEY IN THE BANK! Thanks for this you saved me a TON of time (and only had to focus on one problem instead of 30).
I've been trying this class and it is really helpful and great. :)
The only problem I am encountering is that when it redirects to GotoWebinar, it would first ask me to enter my username and password before it returns the Array containing the upcoming webinars.
Is there a way to auto-login to GotoWebinar by using POST or any other code so that I won't have to manually enter the username and password? Here is my current code for the authorize.php.
I tried the Direct Login, https://developer.citrixonline.com/page/direct-login. However, it would return the information of my user account. But it would not redirect to the page that will generate the webinars.
Thanks a lot!