I've tried to implement the PHP Dropbox Uploader to my website, (located here: https://github.com/jakajancar/DropboxUploader) and I can't seem to get it working correctly. The error I keep getting is:
Fatal error: Class name must be a valid object or a string in [document name] on line 51.
First is my php code on my upload page:
<?php
if ($_POST) {
require 'DropboxUploader.php';
try {
if ($_FILES['file']['error'] !== UPLOAD_ERR_OK)
throw new Exception('File was not successfully uploaded from your computer.');
if ($_FILES['file']['name'] === "")
throw new Exception('File name not supplied by the browser.');
// Upload
$uploader = new DropboxUploader($_POST['user#email.com'], $_POST['mypassword']);
$uploader->upload($_FILES['file']['tmp_name'], $_POST['NEWFORMS, INC'], $_FILES['file']['name']);
echo '<span style="color: green">File successfully uploaded to your Dropbox!</span>';
} catch (Exception $e) {
// Handle Upload Exceptions
$label = ($e->getCode() & $uploader::FLAG_DROPBOX_GENERIC) ? 'DropboxUploader' : 'Exception';
$error = sprintf("[%s] #%d %s", $label, $e->getCode(), $e->getMessage());
echo '<span style="color: red">Error: ' . htmlspecialchars($error) . '</span>';
}
}
?>
And the HTML from the upload page:
<div class="cell-9">
<h1 class="block-head"> Upload Files to our Dropbox </h1>
<form method="POST" enctype="multipart/form-data">
<dl>
<dt><label for="email">Dropbox e-mail</label></dt>
<dd><input type="text" id="email" name="email"></dd>
<dt><label for="password">Dropbox password</label></dt>
<dd><input type="password" id="password" name="password"></dd>
<dt><label for="destination">Destination directory (optional)</label></dt>
<dd><input type="text" id="destination" name="destination"> e.g. "dir/subdirectory", will be created if it doesn't exist</dd>
<dt><label for="file"></label>File</dt>
<dd><input type="file" id="file" name="file"></dd>
<dd><input type="submit" value="Upload the file to my Dropbox!"></dd>
</dl>
</form>
</div>
Here is the PHP from my DropboxUploader PHP File :
<?php
final class DropboxUploader {
/**
* Certificate Authority Certificate source types
*/
const CACERT_SOURCE_SYSTEM = 0;
const CACERT_SOURCE_FILE = 1;
const CACERT_SOURCE_DIR = 2;
/**
* Dropbox configuration
*/
const DROPBOX_UPLOAD_LIMIT_IN_BYTES = 314572800;
const HTTPS_DROPBOX_COM_HOME = 'https://www.dropbox.com/home';
const HTTPS_DROPBOX_COM_LOGIN = 'https://www.dropbox.com/login';
const HTTPS_DROPBOX_COM_LOGINACTION = 'https://www.dropbox.com/ajax_login';
const HTTPS_DROPBOX_COM_UPLOAD = 'https://dl-web.dropbox.com/upload';
const HTTPS_DROPBOX_COM_LOGOUT = 'https://www.dropbox.com/logout';
/**
* DropboxUploader Error Flags and Codes
*/
const FLAG_DROPBOX_GENERIC = 0x10000000;
const FLAG_LOCAL_FILE_IO = 0x10010000;
const CODE_FILE_READ_ERROR = 0x10010101;
const CODE_TEMP_FILE_CREATE_ERROR = 0x10010102;
const CODE_TEMP_FILE_WRITE_ERROR = 0x10010103;
const FLAG_PARAMETER_INVALID = 0x10020000;
const CODE_PARAMETER_TYPE_ERROR = 0x10020101;
const CODE_FILESIZE_TOO_LARGE = 0x10020201;
const FLAG_REMOTE = 0x10040000;
const CODE_CURL_ERROR = 0x10040101;
const CODE_LOGIN_ERROR = 0x10040201;
const CODE_UPLOAD_ERROR = 0x10040401;
const CODE_SCRAPING_FORM = 0x10040801;
const CODE_SCRAPING_LOGIN = 0x10040802;
const CODE_CURL_EXTENSION_MISSING = 0x10080101;
private $email;
private $password;
private $caCertSourceType = self::CACERT_SOURCE_SYSTEM;
private $caCertSource;
private $loggedIn = FALSE;
private $cookies = array();
/**
* Constructor
*
* #param string $email
* #param string $password
* #throws Exception
*/
public function __construct($email, $password) {
// Check requirements
if (!extension_loaded('curl'))
throw new Exception('DropboxUploader requires the cURL extension.', self::CODE_CURL_EXTENSION_MISSING);
if (empty($email) || empty($password)) {
throw new Exception((empty($email) ? 'Email' : 'Password') . ' must not be empty.', self::CODE_PARAMETER_TYPE_ERROR);
}
$this->email = $email;
$this->password = $password;
}
public function setCaCertificateDir($dir) {
$this->caCertSourceType = self::CACERT_SOURCE_DIR;
$this->caCertSource = $dir;
}
public function setCaCertificateFile($file) {
$this->caCertSourceType = self::CACERT_SOURCE_FILE;
$this->caCertSource = $file;
}
public function upload($source, $remoteDir = '/', $remoteName = NULL) {
if (!is_file($source) or !is_readable($source))
throw new Exception("File '$source' does not exist or is not readable.", self::CODE_FILE_READ_ERROR);
$filesize = filesize($source);
if ($filesize < 0 or $filesize > self::DROPBOX_UPLOAD_LIMIT_IN_BYTES) {
throw new Exception("File '$source' too large ($filesize bytes).", self::CODE_FILESIZE_TOO_LARGE);
}
if (!is_string($remoteDir))
throw new Exception("Remote directory must be a string, is " . gettype($remoteDir) . " instead.", self::CODE_PARAMETER_TYPE_ERROR);
if (is_null($remoteName)) {
# intentionally left blank
} else if (!is_string($remoteName)) {
throw new Exception("Remote filename must be a string, is " . gettype($remoteDir) . " instead.", self::CODE_PARAMETER_TYPE_ERROR);
}
if (!$this->loggedIn)
$this->login();
$data = $this->request(self::HTTPS_DROPBOX_COM_HOME);
$file = $this->curlFileCreate($source, $remoteName);
$token = $this->extractFormValue($data, 't');
$subjectUid = $this->extractFormValue($data, '_subject_uid');
$postData = array(
'plain' => 'yes',
'file' => $file,
'dest' => $remoteDir,
't' => $token,
'_subject_uid' => $subjectUid,
'mtime_utc' => filemtime($source),
);
$data = $this->request(self::HTTPS_DROPBOX_COM_UPLOAD, $postData);
if (strpos($data, 'HTTP/1.1 302 FOUND') === FALSE)
throw new Exception('Upload failed!', self::CODE_UPLOAD_ERROR);
}
private function curlFileCreate($source, $remoteName) {
if (function_exists('curl_file_create')) {
return curl_file_create($source, NULL, $remoteName);
}
if ($remoteName !== NULL) {
$source .= ';filename=' . $remoteName;
}
return '#' . $source;
}
public function uploadString($string, $remoteName, $remoteDir = '/') {
$exception = NULL;
$file = tempnam(sys_get_temp_dir(), 'DBUploadString');
if (!is_file($file))
throw new Exception("Can not create temporary file.", self::CODE_TEMP_FILE_CREATE_ERROR);
$bytes = file_put_contents($file, $string);
if ($bytes === FALSE) {
unlink($file);
throw new Exception("Can not write to temporary file '$file'.", self::CODE_TEMP_FILE_WRITE_ERROR);
}
try {
$this->upload($file, $remoteDir, $remoteName);
} catch (Exception $exception) {
# intentionally left blank
}
unlink($file);
if ($exception)
throw $exception;
}
private function login() {
$data = $this->request(self::HTTPS_DROPBOX_COM_LOGIN);
$token = $this->extractTokenFromLoginForm($data);
$postData = array(
'login_email' => (string) $this->email,
'login_password' => (string) $this->password,
't' => $token
);
$data = $this->request(self::HTTPS_DROPBOX_COM_LOGINACTION, http_build_query($postData));
if (stripos($data, '{"status": "OK", "csrf_token": "') === FALSE)
throw new Exception('Login unsuccessful.', self::CODE_LOGIN_ERROR);
$this->loggedIn = TRUE;
}
private function logout() {
$data = $this->request(self::HTTPS_DROPBOX_COM_LOGOUT);
if (!empty($data) && strpos($data, 'HTTP/1.1 302 FOUND') !== FALSE) {
$this->loggedIn = FALSE;
}
}
private function request($url, $postData = NULL) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, (string) $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
switch ($this->caCertSourceType) {
case self::CACERT_SOURCE_FILE:
curl_setopt($ch, CURLOPT_CAINFO, (string) $this->caCertSource);
break;
case self::CACERT_SOURCE_DIR:
curl_setopt($ch, CURLOPT_CAPATH, (string) $this->caCertSource);
break;
}
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if (NULL !== $postData) {
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
}
// Send cookies
$rawCookies = array();
foreach ($this->cookies as $k => $v)
$rawCookies[] = "$k=$v";
$rawCookies = implode(';', $rawCookies);
curl_setopt($ch, CURLOPT_COOKIE, $rawCookies);
$data = curl_exec($ch);
$error = sprintf('Curl error: (#%d) %s', curl_errno($ch), curl_error($ch));
curl_close($ch);
if ($data === FALSE) {
throw new Exception($error, self::CODE_CURL_ERROR);
}
// Store received cookies
preg_match_all('/Set-Cookie: ([^=]+)=(.*?);/i', $data, $matches, PREG_SET_ORDER);
foreach ($matches as $match)
$this->cookies[$match[1]] = $match[2];
return $data;
}
private function extractFormValue($html, $name) {
$action = self::HTTPS_DROPBOX_COM_UPLOAD;
$pattern = sprintf(
'/<form [^>]*%s[^>]*>.*?(?:<input [^>]*name="%s" [^>]*value="(.*?)"[^>]*>).*?<\/form>/is'
, preg_quote($action, '/')
, preg_quote($name, '/')
);
if (!preg_match($pattern, $html, $matches))
throw new Exception(sprintf("Cannot extract '%s'! (form action is '%s')", $name, $action), self::CODE_SCRAPING_FORM);
return $matches[1];
}
private function extractTokenFromLoginForm($html) {
// , "TOKEN": "gCvxU6JVukrW0CUndRPruFvY",
if (!preg_match('#, "TOKEN": "([A-Za-z0-9_-]+)", #', $html, $matches))
throw new Exception('Cannot extract login CSRF token.', self::CODE_SCRAPING_LOGIN);
return $matches[1];
}
public function __destruct() {
if ($this->loggedIn) {
$this->logout();
}
}
}
I removed my email and password for obvious reasons but in my actual file I do have them entered. Any ideas as to what is causing my error and how I could fix it?
($e->getCode() & $uploader::FLAG_DROPBOX_GENERIC) to ($e->getCode() && DropboxUploader::FLAG_DROPBOX_GENERIC)
This was the fix. Thank you #u_mulder for the answer.Cheers!
Related
I have a class that login to a coffee machine. I have a laravel app that "scan" all the coffee machines given in a range of IP address.
The problem is that Curl stops after 39, 128 or even 90 requests. So, I don't know what is the problem or if is a memory leak because PHP and Curl doesn't show any error.
I need advice or tips how to achieve this type of problem. Below is my code.
CoffeeMachine class
<?php
namespace Starbucks\CoffeeMachine;
class CoffeeMachine
{
private $url = '';
private $username = '';
private $password = '';
private $session;
private $response;
private $responses;
private $lastMessage = '';
private $lastStatus = FALSE;
private $authenticated = FALSE;
private function setFailStatus($message = '')
{
$this->lastStatus = FALSE;
$this->lastMessage = $message;
return FALSE;
}
private function setSuccessStatus($message = '')
{
$this->lastStatus = TRUE;
$this->lastMessage = $message;
return TRUE;
}
public function __construct($url = '', $username = 'admin', $password = 'admin')
{
$this->boot();
$this->url = $url;
$this->username = $username;
$this->password = $password;
$this->session = curl_init();
curl_setopt($this->session, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($this->session, CURLOPT_FAILONERROR, 1);
curl_setopt($this->session, CURLOPT_FORBID_REUSE, 1);
curl_setopt($this->session, CURLOPT_FRESH_CONNECT, 1);
}
public function getResponse()
{
return $this->response;
}
public function login()
{
curl_setopt($this->session, CURLOPT_URL, $this->url . '/cgi-bin/dologin');
curl_setopt($this->session, CURLOPT_POST, 1);
curl_setopt($this->session, CURLOPT_POSTFIELDS, array(
'username' => $this->username,
'password' => $this->password
)
);
curl_setopt($this->session, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($this->session, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($this->session, CURLOPT_HEADER, 0);
$response = curl_exec($this->session);
$response = json_decode($response, 1);
if (!isset($response['response'])) return $this->setFailStatus('Auth with no data...');
if ($response['response'] != 'success') return $this->setFailStatus('Access denied...');
$this->response = $response;
$this->lastStatus = TRUE;
$this->lastMessage = 'OK';
$this->authenticated = TRUE;
return TRUE;
}
public function getDeviceInfo()
{
}
public function logout()
{
curl_close($this->session);
}
}
Discover method in a range of IP
<?php
public function discover(Request $request)
{
$from = ip2long($request->input('from', '0.0.0.0'));
$to = ip2long($request->input('to', '255.255.255.255'));
$ips = array();
// CHUNK IN GROUPS OF 10 FOR WAIT 60 SECONDS, BUT NOT WORK
for($i = $from; $i < $to; $i++) $ips[] = long2ip($i);
$group_of_ips = array_chunk($ips, 10);
// TESTED THIS AND NOT WORK
$default_max_execution_time = ini_get('max_execution_time');
ini_set('max_execution_time', ((abs($from - $to) * 5) + (count($group_of_ips) * 60)) );
$machine_ips = array();
foreach($group_of_ips as $index => $row) {
foreach($row as $ip) {
$gs = new CoffeeMachine($ip, 'admin', 'admin');
if ($gs->login()) {
$machine_ips[] = $ip;
}
$gs->logout();
}
sleep(60); // TESTED THIS AND NOT WORK
}
ini_set('max_execution_time', $default_max_execution_time);
/* RETURN THE COFFEE MACHINE IP ADDRESS */
return $machine_ips;
}
add more error checking. some snippets from my curl wrapper, hhb_curl:
$this->curlh = curl_init ( '' ); // why empty string? PHP Fatal error: Uncaught TypeError: curl_init() expects parameter 1 to be string, null given
if (! $this->curlh) {
throw new RuntimeException ( 'curl_init failed!' );
}
here i verify that curl_init managed to create a curl resource, if it didn't, i throw a RuntimeException. you should do the same.
$ret = curl_exec ( $this->curlh );
if ($this->errno ()) {
throw new RuntimeException ( 'curl_exec failed. errno: ' . var_export ( $this->errno (), true ) . ' error: ' . var_export ( $this->error (), true ) );
}
here, i verify that curl_exec didn't register any errors, else i throw a RuntimeException. you should do the same. (it uses curl_errno($ch) )
function setopt_array(array $options): bool {
foreach ( $options as $option => $value ) {
$this->setopt ( $option, $value );
}
return true;
}
here i make sure my setopt_array doesn't actually use curl_setopt_array, but my own curl_setopt wrapper, you should do the same, for reasons explained below.
private function _setopt(int $option, $value): bool {
$ret = curl_setopt ( $this->curlh, $option, $value );
if (! $ret) {
throw new InvalidArgumentException ( 'curl_setopt failed. errno: ' . $this->errno () . '. error: ' . $this->error () . '. option: ' . var_export ( $this->_curlopt_name ( $option ), true ) . ' (' . var_export ( $option, true ) . '). value: ' . var_export ( $value, true ) );
}
$this->curloptions [$option] = $value;
return $ret; // true...
}
here i verify that curl_setopt succeeded, if it didn't, i throw an InvalidArgumentException, you should do the same (or at least throw some kind of exception, rather than the silent ignore your current code does.), and unlike curl_setopt_array, you can actually easily determine which option couldn't be set.
and when debugging curl code, always set CURLOPT_VERBOSE. (hhb_curl always does this, and gives curl a CURLOPT_STDERR tempfile() to put the verbose/error logs in, and gives you the logs through $hc->getStdErr() ), you should at least add some form of CURLOPT_VERBOSE support for debugging. my curl wrapper, hhb_curl, is available here https://github.com/divinity76/hhb_.inc.php/blob/master/hhb_.inc.php
Adding a timeout to the curl execution solves the problem. You need to monitor the response time for each device you want to reach. for me, 10 seconds for CONNECTTIMEOUT and TIMEOUT works fine.
<?php
namespace Starbucks\CoffeeMachine;
class CoffeeMachine
{
private $url = '';
private $username = '';
private $password = '';
private $session;
private $response;
private $responses;
private $lastMessage = '';
private $lastStatus = FALSE;
private $authenticated = FALSE;
private function setFailStatus($message = '')
{
$this->lastStatus = FALSE;
$this->lastMessage = $message;
return FALSE;
}
private function setSuccessStatus($message = '')
{
$this->lastStatus = TRUE;
$this->lastMessage = $message;
return TRUE;
}
public function __construct($url = '', $username = 'admin', $password = 'admin')
{
$this->boot();
$this->url = $url;
$this->username = $username;
$this->password = $password;
$this->session = curl_init();
curl_setopt($this->session, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($this->session, CURLOPT_TIMEOUT, 10);
curl_setopt($this->session, CURLOPT_FAILONERROR, 1);
curl_setopt($this->session, CURLOPT_FORBID_REUSE, 1);
curl_setopt($this->session, CURLOPT_FRESH_CONNECT, 1);
}
public function getResponse()
{
return $this->response;
}
public function login()
{
curl_setopt($this->session, CURLOPT_URL, $this->url . '/cgi-bin/dologin');
curl_setopt($this->session, CURLOPT_POST, 1);
curl_setopt($this->session, CURLOPT_POSTFIELDS, array(
'username' => $this->username,
'password' => $this->password
)
);
curl_setopt($this->session, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($this->session, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($this->session, CURLOPT_HEADER, 0);
$response = curl_exec($this->session);
if (curl_errno($this->session)) {
$msg = $this->url . "\n" . curl_errno($this->session) . "\n" . curl_error($this->session);
return $this->setFailStatus($msg);
}
$response = json_decode($response, 1);
if (!isset($response['response'])) return $this->setFailStatus('Auth with no data...');
if ($response['response'] != 'success') return $this->setFailStatus('Access denied...');
$this->response = $response;
$this->lastStatus = TRUE;
$this->lastMessage = 'OK';
$this->authenticated = TRUE;
return TRUE;
}
public function getDeviceInfo()
{
}
public function logout()
{
curl_close($this->session);
}
}
Now I can loop and reach CoffeeMachines =)
I am working on a payment gateway payfort, here I want to pass my dynamic price public $amount = 7150.00; by Url request, but it's not working.
I am new on OOPS so please any one help me.
Static value are working fine.
confirm-order.php
<?php include('header.php') ?>
<?php
$data = $_REQUEST;
$itemname = $data['startfrom'].' - '. $data['stopto'].', Distance : '. $data['distance'].' Km , Duration : '.$data['duration'].' Minutes';
require_once 'PayfortIntegration.php';
$objFort = new PayfortIntegration();
$amount = $objFort->amount;
$currency = $objFort->currency;
$totalAmount = $data['amount'];
$paymentMethod = $_REQUEST['payment_method'];
$objFort->itemName = $itemname;
$objFort->customerEmail = 'abc#gmail.com';
?>
<section class="nav">
<ul>
<li class="lead" >Payment Method</li>
<li class="lead active" > Pay</li>
<li class="lead" > Done</li>
</ul>
</section>
<section class="confirmation">
<label>Confirm Your Order</label>
</section>
<section class="order-info">
<ul class="items">
<span>
<i class="icon icon-bag"></i>
<label class="lead" for="">Your Booking</label>
</span>
<li><?php echo $objFort->itemName ?></li>
</ul>
<ul>
<li>
<div class="v-seperator"></div>
</li>
</ul>
<ul class="price">
<span>
<i class="icon icon-tag"></i>
<label class="lead" for="">price</label>
</span>
<li><span class="curreny">AED</span> <?php echo sprintf("%.2f",$totalAmount);?> </li>
</ul>
<ul class="items">
<span>
<i class="icon icon-bag"></i>
<label class="lead" for="">Payment Method</label>
</span>
<li><?php echo $objFort->getPaymentOptionName($paymentMethod) ?></li>
</ul>
</section>
<?php if($paymentMethod == 'cc_merchantpage') ://merchant page iframe method ?>
<section class="merchant-page-iframe">
<?php
$merchantPageData = $objFort->getMerchantPageData();
$postData = $merchantPageData['params'];
$gatewayUrl = $merchantPageData['url'];
?>
<p>Test card: 4005550000000001<br/>05/17<br/>123</p>
<div class="cc-iframe-display">
<div id="div-pf-iframe" style="display:none">
<div class="pf-iframe-container">
<div class="pf-iframe" id="pf_iframe_content">
</div>
</div>
</div>
</div>
</section>
<?php endif; ?>
<div class="h-seperator"></div>
<section class="actions">
<a class="back" id="btn_back" href="index.php">Back</a>
</section>
<script type="text/javascript" src="vendors/jquery.min.js"></script>
<script type="text/javascript" src="assets/js/checkout.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var paymentMethod = '<?php echo $paymentMethod?>';
//load merchant page iframe
if(paymentMethod == 'cc_merchantpage') {
getPaymentPage(paymentMethod);
}
});
</script>
<?php include('footer.php') ?>
and configuration file is:
PayfortIntegration.php
<?php
/**
* #copyright Copyright PayFort 2012-2016
*
*/
class PayfortIntegration
{
public $gatewayHost = 'https://checkout.payfort.com/';
public $gatewaySandboxHost = 'https://sbcheckout.payfort.com/';
public $language = 'en';
/**
* #var string your Merchant Identifier account (mid)
*/
public $merchantIdentifier = 'XXXXXXXXXXXXXX';
/**
* #var string your access code
*/
public $accessCode = 'XXXXXXXXXXX';
/**
* #var string SHA Request passphrase
*/
public $SHARequestPhrase = 'XXXXXXXXX';
/**
* #var string SHA Response passphrase
*/
public $SHAResponsePhrase = 'XXXXXXXXXX';
/**
* #var string SHA Type (Hash Algorith)
* expected Values ("sha1", "sha256", "sha512")
*/
public $SHAType = 'sha256';
/**
* #var string command
* expected Values ("AUTHORIZATION", "PURCHASE")
*/
public $command = 'AUTHORIZATION';
/**
* #var decimal order amount
*/
public $amount = 7150.00;
/**
* #var string order currency
*/
public $currency = 'AED';
/**
* #var string item name
*/
public $itemName = 'Apple iPhone 6s Plus';
/**
* #var string you can change it to your email
*/
public $customerEmail = 'shiv#srapsware.com';
/**
* #var boolean for live account change it to false
*/
public $sandboxMode = true;
/**
* #var string project root folder
* change it if the project is not on root folder.
*/
public $projectUrlPath = '/pay';
public function __construct()
{
}
public function processRequest($paymentMethod)
{
if ($paymentMethod == 'cc_merchantpage' || $paymentMethod == 'cc_merchantpage2') {
$merchantPageData = $this->getMerchantPageData();
$postData = $merchantPageData['params'];
$gatewayUrl = $merchantPageData['url'];
}
else{
$data = $this->getRedirectionData($paymentMethod);
$postData = $data['params'];
$gatewayUrl = $data['url'];
}
$form = $this->getPaymentForm($gatewayUrl, $postData);
echo json_encode(array('form' => $form, 'url' => $gatewayUrl, 'params' => $postData, 'paymentMethod' => $paymentMethod));
exit;
}
public function getRedirectionData($paymentMethod) {
$merchantReference = $this->generateMerchantReference();
if ($this->sandboxMode) {
$gatewayUrl = $this->gatewaySandboxHost . 'FortAPI/paymentPage';
}
else {
$gatewayUrl = $this->gatewayHost . 'FortAPI/paymentPage';
}
if ($paymentMethod == 'sadad') {
$this->currency = 'SAR';
}
$postData = array(
'amount' => $this->convertFortAmount($this->amount, $this->currency),
'currency' => strtoupper($this->currency),
'merchant_identifier' => $this->merchantIdentifier,
'access_code' => $this->accessCode,
'merchant_reference' => $merchantReference,
'customer_email' => 'test#payfort.com',
//'customer_name' => trim($order_info['b_firstname'].' '.$order_info['b_lastname']),
'command' => $this->command,
'language' => $this->language,
'return_url' => $this->getUrl('route.php?r=processResponse'),
);
if ($paymentMethod == 'sadad') {
$postData['payment_option'] = 'SADAD';
}
elseif ($paymentMethod == 'naps') {
$postData['payment_option'] = 'NAPS';
$postData['order_description'] = $this->itemName;
}
elseif ($paymentMethod == 'installments') {
$postData['installments'] = 'STANDALONE';
$postData['command'] = 'PURCHASE';
}
$postData['signature'] = $this->calculateSignature($postData, 'request');
$debugMsg = "Fort Redirect Request Parameters \n".print_r($postData, 1);
$this->log($debugMsg);
return array('url' => $gatewayUrl, 'params' => $postData);
}
public function getMerchantPageData()
{
$merchantReference = $this->generateMerchantReference();
$returnUrl = $this->getUrl('route.php?r=merchantPageReturn');
if(isset($_GET['3ds']) && $_GET['3ds'] == 'no') {
$returnUrl = $this->getUrl('route.php?r=merchantPageReturn&3ds=no');
}
$iframeParams = array(
'merchant_identifier' => $this->merchantIdentifier,
'access_code' => $this->accessCode,
'merchant_reference' => $merchantReference,
'service_command' => 'TOKENIZATION',
'language' => $this->language,
'return_url' => $returnUrl,
);
$iframeParams['signature'] = $this->calculateSignature($iframeParams, 'request');
if ($this->sandboxMode) {
$gatewayUrl = $this->gatewaySandboxHost . 'FortAPI/paymentPage';
}
else {
$gatewayUrl = $this->gatewayHost . 'FortAPI/paymentPage';
}
$debugMsg = "Fort Merchant Page Request Parameters \n".print_r($iframeParams, 1);
$this->log($debugMsg);
return array('url' => $gatewayUrl, 'params' => $iframeParams);
}
public function getPaymentForm($gatewayUrl, $postData)
{
$form = '<form style="display:none" name="payfort_payment_form" id="payfort_payment_form" method="post" action="' . $gatewayUrl . '">';
foreach ($postData as $k => $v) {
$form .= '<input type="hidden" name="' . $k . '" value="' . $v . '">';
}
$form .= '<input type="submit" id="submit">';
return $form;
}
public function processResponse()
{
$fortParams = array_merge($_GET, $_POST);
$debugMsg = "Fort Redirect Response Parameters \n".print_r($fortParams, 1);
$this->log($debugMsg);
$reason = '';
$response_code = '';
$success = true;
if(empty($fortParams)) {
$success = false;
$reason = "Invalid Response Parameters";
$debugMsg = $reason;
$this->log($debugMsg);
}
else{
//validate payfort response
$params = $fortParams;
$responseSignature = $fortParams['signature'];
$merchantReference = $params['merchant_reference'];
unset($params['r']);
unset($params['signature']);
unset($params['integration_type']);
$calculatedSignature = $this->calculateSignature($params, 'response');
$success = true;
$reason = '';
if ($responseSignature != $calculatedSignature) {
$success = false;
$reason = 'Invalid signature.';
$debugMsg = sprintf('Invalid Signature. Calculated Signature: %1s, Response Signature: %2s', $responseSignature, $calculatedSignature);
$this->log($debugMsg);
}
else {
$response_code = $params['response_code'];
$response_message = $params['response_message'];
$status = $params['status'];
if (substr($response_code, 2) != '000') {
$success = false;
$reason = $response_message;
$debugMsg = $reason;
$this->log($debugMsg);
}
}
}
if(!$success) {
$p = $params;
$p['error_msg'] = $reason;
$return_url = $this->getUrl('error.php?'.http_build_query($p));
}
else{
$return_url = $this->getUrl('success.php?'.http_build_query($params));
}
echo "<html><body onLoad=\"javascript: window.top.location.href='" . $return_url . "'\"></body></html>";
exit;
}
public function processMerchantPageResponse()
{
$fortParams = array_merge($_GET, $_POST);
$debugMsg = "Fort Merchant Page Response Parameters \n".print_r($fortParams, 1);
$this->log($debugMsg);
$reason = '';
$response_code = '';
$success = true;
if(empty($fortParams)) {
$success = false;
$reason = "Invalid Response Parameters";
$debugMsg = $reason;
$this->log($debugMsg);
}
else{
//validate payfort response
$params = $fortParams;
$responseSignature = $fortParams['signature'];
unset($params['r']);
unset($params['signature']);
unset($params['integration_type']);
unset($params['3ds']);
$merchantReference = $params['merchant_reference'];
$calculatedSignature = $this->calculateSignature($params, 'response');
$success = true;
$reason = '';
if ($responseSignature != $calculatedSignature) {
$success = false;
$reason = 'Invalid signature.';
$debugMsg = sprintf('Invalid Signature. Calculated Signature: %1s, Response Signature: %2s', $responseSignature, $calculatedSignature);
$this->log($debugMsg);
}
else {
$response_code = $params['response_code'];
$response_message = $params['response_message'];
$status = $params['status'];
if (substr($response_code, 2) != '000') {
$success = false;
$reason = $response_message;
$debugMsg = $reason;
$this->log($debugMsg);
}
else {
$success = true;
$host2HostParams = $this->merchantPageNotifyFort($fortParams);
$debugMsg = "Fort Merchant Page Host2Hots Response Parameters \n".print_r($fortParams, 1);
$this->log($debugMsg);
if (!$host2HostParams) {
$success = false;
$reason = 'Invalid response parameters.';
$debugMsg = $reason;
$this->log($debugMsg);
}
else {
$params = $host2HostParams;
$responseSignature = $host2HostParams['signature'];
$merchantReference = $params['merchant_reference'];
unset($params['r']);
unset($params['signature']);
unset($params['integration_type']);
$calculatedSignature = $this->calculateSignature($params, 'response');
if ($responseSignature != $calculatedSignature) {
$success = false;
$reason = 'Invalid signature.';
$debugMsg = sprintf('Invalid Signature. Calculated Signature: %1s, Response Signature: %2s', $responseSignature, $calculatedSignature);
$this->log($debugMsg);
}
else {
$response_code = $params['response_code'];
if ($response_code == '20064' && isset($params['3ds_url'])) {
$success = true;
$debugMsg = 'Redirect to 3DS URL : '.$params['3ds_url'];
$this->log($debugMsg);
echo "<html><body onLoad=\"javascript: window.top.location.href='" . $params['3ds_url'] . "'\"></body></html>";
exit;
//header('location:'.$params['3ds_url']);
}
else {
if (substr($response_code, 2) != '000') {
$success = false;
$reason = $host2HostParams['response_message'];
$debugMsg = $reason;
$this->log($debugMsg);
}
}
}
}
}
}
if(!$success) {
$p = $params;
$p['error_msg'] = $reason;
$return_url = $this->getUrl('error.php?'.http_build_query($p));
}
else{
$return_url = $this->getUrl('success.php?'.http_build_query($params));
}
echo "<html><body onLoad=\"javascript: window.top.location.href='" . $return_url . "'\"></body></html>";
exit;
}
}
public function merchantPageNotifyFort($fortParams)
{
//send host to host
if ($this->sandboxMode) {
$gatewayUrl = $this->gatewaySandboxHost . 'FortAPI/paymentPage';
}
else {
$gatewayUrl = $this->gatewayHost . 'FortAPI/paymentPage';
}
$postData = array(
'merchant_reference' => $fortParams['merchant_reference'],
'access_code' => $this->accessCode,
'command' => $this->command,
'merchant_identifier' => $this->merchantIdentifier,
'customer_ip' => $_SERVER['REMOTE_ADDR'],
'amount' => $this->convertFortAmount($this->amount, $this->currency),
'currency' => strtoupper($this->currency),
'customer_email' => $this->customerEmail,
'customer_name' => 'John Doe',
'token_name' => $fortParams['token_name'],
'language' => $this->language,
'return_url' => $this->getUrl('route.php?r=processResponse'),
);
if(isset($fortParams['3ds']) && $fortParams['3ds'] == 'no') {
$postData['check_3ds'] = 'NO';
}
//calculate request signature
$signature = $this->calculateSignature($postData, 'request');
$postData['signature'] = $signature;
$debugMsg = "Fort Host2Host Request Parameters \n".print_r($postData, 1);
$this->log($debugMsg);
if ($this->sandboxMode) {
$gatewayUrl = 'https://sbpaymentservices.payfort.com/FortAPI/paymentApi';
}
else {
$gatewayUrl = 'https://paymentservices.payfort.com/FortAPI/paymentApi';
}
$array_result = $this->callApi($postData, $gatewayUrl);
$debugMsg = "Fort Host2Host Response Parameters \n".print_r($array_result, 1);
$this->log($debugMsg);
return $array_result;
}
/**
* Send host to host request to the Fort
* #param array $postData
* #param string $gatewayUrl
* #return mixed
*/
public function callApi($postData, $gatewayUrl)
{
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
$useragent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0";
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json;charset=UTF-8',
//'Accept: application/json, application/*+json',
//'Connection:keep-alive'
));
curl_setopt($ch, CURLOPT_URL, $gatewayUrl);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_ENCODING, "compress, gzip");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // allow redirects
//curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // return into a variable
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); // The number of seconds to wait while trying to connect
//curl_setopt($ch, CURLOPT_TIMEOUT, Yii::app()->params['apiCallTimeout']); // timeout in seconds
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postData));
$response = curl_exec($ch);
//$response_data = array();
//parse_str($response, $response_data);
curl_close($ch);
$array_result = json_decode($response, true);
if (!$response || empty($array_result)) {
return false;
}
return $array_result;
}
/**
* calculate fort signature
* #param array $arrData
* #param string $signType request or response
* #return string fort signature
*/
public function calculateSignature($arrData, $signType = 'request')
{
$shaString = '';
ksort($arrData);
foreach ($arrData as $k => $v) {
$shaString .= "$k=$v";
}
if ($signType == 'request') {
$shaString = $this->SHARequestPhrase . $shaString . $this->SHARequestPhrase;
}
else {
$shaString = $this->SHAResponsePhrase . $shaString . $this->SHAResponsePhrase;
}
$signature = hash($this->SHAType, $shaString);
return $signature;
}
/**
* Convert Amount with dicemal points
* #param decimal $amount
* #param string $currencyCode
* #return decimal
*/
public function convertFortAmount($amount, $currencyCode)
{
$new_amount = 0;
$total = $amount;
$decimalPoints = $this->getCurrencyDecimalPoints($currencyCode);
$new_amount = round($total, $decimalPoints) * (pow(10, $decimalPoints));
return $new_amount;
}
public function castAmountFromFort($amount, $currencyCode)
{
$decimalPoints = $this->getCurrencyDecimalPoints($currencyCode);
//return $amount / (pow(10, $decimalPoints));
$new_amount = round($amount, $decimalPoints) / (pow(10, $decimalPoints));
return $new_amount;
}
/**
*
* #param string $currency
* #param integer
*/
public function getCurrencyDecimalPoints($currency)
{
$decimalPoint = 2;
$arrCurrencies = array(
'JOD' => 3,
'KWD' => 3,
'OMR' => 3,
'TND' => 3,
'BHD' => 3,
'LYD' => 3,
'IQD' => 3,
);
if (isset($arrCurrencies[$currency])) {
$decimalPoint = $arrCurrencies[$currency];
}
return $decimalPoint;
}
public function getUrl($path)
{
$url = 'http://' . $_SERVER['HTTP_HOST'] . $this->projectUrlPath .'/'. $path;
return $url;
}
public function generateMerchantReference()
{
return rand(0, 9999999999);
}
/**
* Log the error on the disk
*/
public function log($messages) {
$messages = "========================================================\n\n".$messages."\n\n";
$file = __DIR__.'/trace.log';
if (filesize($file) > 907200) {
$fp = fopen($file, "r+");
ftruncate($fp, 0);
fclose($fp);
}
$myfile = fopen($file, "a+");
fwrite($myfile, $messages);
fclose($myfile);
}
/**
*
* #param type $po payment option
* #return string payment option name
*/
function getPaymentOptionName($po) {
switch($po) {
case 'creditcard' : return 'Credit Cards';
case 'cc_merchantpage' : return 'Credit Cards (Merchant Page)';
case 'installments' : return 'Installments';
case 'sadad' : return 'SADAD';
case 'naps' : return 'NAPS';
default : return '';
}
}
}
?>
To access (read, modify) an instance variable (which $amount is), you have to use $this->amount from within a method.
For example.
$this->amount = 1000.00
This is not the same as:
$amount = 1000.00
It would be a very good idea to find a book on OOP, and review the top 10 list from owasp.org for security best practices. Specifically, your code needs to be validating user input as strictly as possible before using it in redirects or sending it on to other services. Also, it looks like you may have posted some access credentials so you might want to change those.
I am up and running my E-Commerce website on a server. I use Paypal IPN notifications to send customers with notifications about payments made by them.
I am currently using Paypal sandbox for testing.
I proceed to checkout => paypal developer account => make payment => i receive message in my paypal account as ipn request is sent but i don't get the values of ipn request in my orders table in the database.
What could be the reason for this ?
I have set my IPN details as in the screenshot below.
and
I also have the screenshot of IPN history of my Paypal developer account.
Can anyone please help me and tell me the reason why the values in my database are not updated ?
Following is my code:
classes/Paypal.php
<?php
class PayPal {
private $_environment = 'sandbox';
private $_url_production = 'https://www.paypal.com/cgi-bin/webscr';
private $_url_sandbox = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
private $_url;
private $_cmd;
private $_products = array();
private $_fields = array();
private $_business = 'xxx-xxx#gmail.com';
private $_page_style = 'null';
private $_return;
private $_cancel_payment;
private $_notify_url;
private $_currency_code = 'GBP';
public $_tax_cart = 0;
public $_tax = 0;
public $_populate = array();
private $_ipn_data = array();
private $_log_file = null;
private $_ipn_result;
public function __construct($cmd = '_cart') {
$this->_url = $this->_environment == 'sandbox' ?
$this->_url_sandbox :
$this->_url_production;
$this->_cmd = $cmd;
$this->_return = SITE_URL."/?page=return";
$this->_cancel_payment = SITE_URL."/?page=cancel";
$this->_notify_url = SITE_URL."/?page=ipn";
$this->_log_file = ROOT_PATH.DS."log".DS."ipn.log";
}
public function addProduct($number, $name, $price = 0, $qty = 1) {
switch($this->_cmd) {
case '_cart':
$id = count($this->_products) + 1;
$this->_products[$id]['item_number_'.$id] = $number;
$this->_products[$id]['item_name_'.$id] = $name;
$this->_products[$id]['amount_'.$id] = $price;
$this->_products[$id]['quantity_'.$id] = $qty;
break;
case '_xclick':
if (empty($this->_products)) {
$this->_products[0]['item_number'] = $number;
$this->_products[0]['item_name'] = $name;
$this->_products[0]['amount'] = $price;
$this->_products[0]['quantity'] = $qty;
}
break;
}
}
private function addField($name = null, $value = null) {
if (!empty($name) && !empty($value)) {
$field = '<input type="hidden" name="'.$name.'" ';
$field .= 'value="'.$value.'" />';
$this->_fields[] = $field;
}
}
private function standardFields() {
$this->addField('cmd', $this->_cmd);
$this->addField('business', $this->_business);
if ($this->_page_style != null) {
$this->addField('page_style', $this->_page_style);
}
$this->addField('return', $this->_return);
$this->addField('notify_url', $this->_notify_url);
$this->addField('cancel_payment', $this->_cancel_payment);
$this->addField('currency_code', $this->_currency_code);
$this->addField('rm', 2);
switch($this->_cmd) {
case '_cart':
if ($this->_tax_cart != 0) {
$this->addField('tax_cart', $this->_tax_cart);
}
$this->addField('upload', 1);
break;
case '_xclick':
if ($this->_tax != 0) {
$this->addField('tax', $this->_tax);
}
break;
}
}
private function prePopulate() {
if (!empty($this->_populate)) {
foreach($this->_populate as $key => $value) {
$this->addField($key, $value);
}
}
}
private function processFields() {
$this->standardFields();
if (!empty($this->_products)) {
foreach($this->_products as $product) {
foreach($product as $key => $value) {
$this->addField($key, $value);
}
}
}
$this->prePopulate();
}
private function getFields() {
$this->processFields();
if (!empty($this->_fields)) {
return implode("", $this->_fields);
}
}
private function render() {
$out = '<form action="'.$this->_url.'" method="post" id="frm_paypal">';
$out .= $this->getFields();
$out .= '<input type="submit" value="Submit" />';
$out .= '</form>';
return $out;
}
public function run($transaction_id = null) {
if (!empty($transaction_id)) {
$this->addField('custom', $transaction_id);
}
return $this->render();
}
private function validateIpn() {
$hostname = gethostbyaddr($_SERVER['REMOTE_ADDR']);
if (!preg_match('/paypal\.com$/', $hostname)) {
return false;
}
$objForm = new Form();
$this->_ipn_data = $objForm->getPostArray();
if (
!empty($this->_ipn_data) &&
array_key_exists('receiver_email', $this->_ipn_data) &&
strtolower($this->_ipn_data['receiver_email']) !=
strtolower($this->_business)
) {
return false;
}
return true;
}
private function getReturnParams() {
$out = array('cmd=_notify-validate');
if (!empty($this->_ipn_data)) {
foreach($this->_ipn_data as $key => $value) {
$value = function_exists('get_magic_quotes_gpc') ?
urlencode(stripslashes($value)) :
urlencode($value);
$out[] = "{$key}={$value}";
}
}
return implode("&", $out);
}
private function sendCurl() {
$response = $this->getReturnParams();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $response);
curl_setopt($ch, T_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-Type: application/x-www-form-urlencoded",
"Content-Length: " . strlen($response)
));
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$this->_ipn_result = curl_exec($ch);
curl_close($ch);
}
public function ipn() {
if ($this->validateIpn()) {
$this->sendCurl();
if (strcmp($this->_ipn_result, "VERIFIED") == 0) {
$objOrder = new Order();
if (!empty($this->_ipn_data)) {
$objOrder->approve(
$this->_ipn_data,
$this->_ipn_result
);
}
}
}
}
}
mod/paypal.php
<?php
require_once('../inc/autoload.php');
$token2 = Session::getSession('token2');
$objForm = new Form();
$token1 = $objForm->getPost('token');
if ($token2 == Login::string2hash($token1)) {
// create order
$objOrder = new Order();
if ($objOrder->createOrder()) {
// populate order details
$order = $objOrder->getOrder();
$items = $objOrder->getOrderItems();
if (!empty($order) && !empty($items)) {
$objBasket = new Basket();
$objCatalogue = new Catalogue();
$objPayPal = new PayPal();
foreach($items as $item) {
$product = $objCatalogue->getProduct($item['product']);
$objPayPal->addProduct(
$item['product'],
$product['name'],
$item['price'],
$item['qty']
);
}
$objPayPal->_tax_cart = $objBasket->_vat;
// populate client's details
$objUser = new User();
$user = $objUser->getUser($order['client']);
if (!empty($user)) {
$objCountry = new Country();
$country = $objCountry->getCountry($user['country']);
$objPayPal->_populate = array(
'address1' => $user['address_1'],
'address2' => $user['address_2'],
'city' => $user['town'],
'state' => $user['county'],
'zip' => $user['post_code'],
'country' => $country['code'],
'email' => $user['email'],
'first_name' => $user['first_name'],
'last_name' => $user['last_name']
);
// redirect client to PayPal
echo $objPayPal->run($order['id']);
}
}
}
}
IPN settings
IPN Details
Please help me with this .
IPN is not related to your return URL. If you're adding your code that you expect to run when IPNs are triggered to your return URL you will not get the expected result.
To get data to your return URL you would need to use PDT which is very similar to IPN but is intended to be sent to the return URL. IPN goes to your notify URL, which should not match your return URL.
updated shopify.php
<?php
include('shopify_api_config.php');
class ShopifyClient {
public $shop_domain;
private $token;
private $api_key;
private $secret;
private $last_response_headers = null;
public function __construct($shop_domain, $token, $api_key, $secret) {
$this->name = "ShopifyClient";
$this->shop_domain = 'https://#4ef34cd22b136c1a7b869e77c8ce8b3c:#fb2b17c283a27c65e4461d0ce8e5871b#discountshop-8.myshopify.com';
$this->token = $token;
$this->api_key = '4ef34cd22b136c1a7b869e77c8ce8b3c';
$this->secret = '28cdbeb0b925bba5b8c9a60cfbb8c3cb';
$client = new ShopifyClient($shop_domain, $token, $api_key, $secret);
}
// Get the URL required to request authorization
public function getAuthorizeUrl($scope, $redirect_url='') {
$url = "http://{$this->shop_domain}/admin/oauth/authorize?client_id={$this->api_key}&scope=" . urlencode($scope);
if ($redirect_url != '')
{
$url .= "&redirect_uri=" . urlencode($redirect_url);
}
return $url;
}
// Once the User has authorized the app, call this with the code to get the access token
public function getAccessToken($code) {
// POST to POST https://SHOP_NAME.myshopify.com/admin/oauth/access_token
$url = "https://{$this->shop_domain}/admin/oauth/access_token";
$payload = "client_id={$this->api_key}&client_secret={$this->secret}&code=$code";
$response = $this->curlHttpApiRequest('POST', $url, '', $payload, array());
$response = json_decode($response, true);
if (isset($response['access_token']))
return $response['access_token'];
return '';
}
public function callsMade()
{
return $this->shopApiCallLimitParam(0);
}
public function callLimit()
{
return $this->shopApiCallLimitParam(1);
}
public function callsLeft($response_headers)
{
return $this->callLimit() - $this->callsMade();
}
public function call($method, $path, $params=array())
{
$baseurl = "https://{$this->shop_domain}/";
$url = $baseurl.ltrim($path, '/');
$query = in_array($method, array('GET','DELETE')) ? $params : array();
$payload = in_array($method, array('POST','PUT')) ? stripslashes(json_encode($params)) : array();
$request_headers = in_array($method, array('POST','PUT')) ? array("Content-Type: application/json; charset=utf-8", 'Expect:') : array();
// add auth headers
$request_headers[] = 'X-Shopify-Access-Token: ' . $this->token;
$response = $this->curlHttpApiRequest($method, $url, $query, $payload, $request_headers);
$response = json_decode($response, true);
if (isset($response['errors']) or ($this->last_response_headers['http_status_code'] >= 400))
throw new ShopifyApiException($method, $path, $params, $this->last_response_headers, $response);
return (is_array($response) and (count($response) > 0)) ? array_shift($response) : $response;
}
public function validateSignature($query)
{
if(!is_array($query) || empty($query['signature']) || !is_string($query['signature']))
return false;
foreach($query as $k => $v) {
if($k == 'signature') continue;
$signature[] = $k . '=' . $v;
}
sort($signature);
$signature = md5($this->secret . implode('', $signature));
return $query['signature'] == $signature;
}
private function curlHttpApiRequest($method, $url, $query='', $payload='', $request_headers=array())
{
$url = $this->curlAppendQuery($url, $query);
$ch = curl_init($url);
$this->curlSetopts($ch, $method, $payload, $request_headers);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
curl_close($ch);
if ($errno) throw new ShopifyCurlException($error, $errno);
list($message_headers, $message_body) = preg_split("/\r\n\r\n|\n\n|\r\r/", $response, 2);
$this->last_response_headers = $this->curlParseHeaders($message_headers);
return $message_body;
}
private function curlAppendQuery($url, $query)
{
if (empty($query)) return $url;
if (is_array($query)) return "$url?".http_build_query($query);
else return "$url?$query";
}
private function curlSetopts($ch, $method, $payload, $request_headers)
{
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_USERAGENT, 'ohShopify-php-api-client');
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, $method);
if (!empty($request_headers)) curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
if ($method != 'GET' && !empty($payload))
{
if (is_array($payload)) $payload = http_build_query($payload);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $payload);
}
}
private function curlParseHeaders($message_headers)
{
$header_lines = preg_split("/\r\n|\n|\r/", $message_headers);
$headers = array();
list(, $headers['http_status_code'], $headers['http_status_message']) = explode(' ', trim(array_shift($header_lines)), 3);
foreach ($header_lines as $header_line)
{
list($name, $value) = explode(':', $header_line, 2);
$name = strtolower($name);
$headers[$name] = trim($value);
}
return $headers;
}
private function shopApiCallLimitParam($index)
{
if ($this->last_response_headers == null)
{
throw new Exception('Cannot be called before an API call.');
}
$params = explode('/', $this->last_response_headers['http_x_shopify_shop_api_call_limit']);
return (int) $params[$index];
}
}
class ShopifyCurlException extends Exception { }
class ShopifyApiException extends Exception
{
protected $method;
protected $path;
protected $params;
protected $response_headers;
protected $response;
function __construct($method, $path, $params, $response_headers, $response)
{
$this->method = $method;
$this->path = $path;
$this->params = $params;
$this->response_headers = $response_headers;
$this->response = $response;
parent::__construct($response_headers['http_status_message'], $response_headers['http_status_code']);
}
function getMethod() { return $this->method; }
function getPath() { return $this->path; }
function getParams() { return $this->params; }
function getResponseHeaders() { return $this->response_headers; }
function getResponse() { return $this->response; }
}
?>
I installed one private app in my shopify store for download csv file, after installed, when click download button, it will display like
Fatal error: Uncaught exception 'ShopifyCurlException' with message 'Could not
resolve host: http:; Host not found' in C:\xampp\htdocs\cat\lib\shopify.php:102
Stack trace: #0 C:\xampp\htdocs\cat\lib\shopify.php(67): ShopifyClient->curlHttpApiRequest('GET', 'https://http://...', Array, Array, Array)
#1 C:\xampp\htdocs\cat\index-oauth.php(26): ShopifyClient->call('GET', 'admin/orders.js...', Array)
#2 {main} thrown in C:\xampp\htdocs\cat\lib\shopify.php on line 102.
I dont know how to fix. If anybody know, please help.
Thank you!.
I had the same problem. Try this.
In your constructor pass the following argument as the $shop_domain.
https:// #apikey:#password#hostname
Replace #apiKey, #password and hostname with your values. Also leave '#' in hostname.
I.e. #yourshop.com
$shop_domain = 'https://#apikey:#password#hostname';
$token = 'your token';
$key = 'your key';
$secret = 'your secret';
$client = new ShopifyClient($shop_domain, $token, $api_key, $secret);
I am making a simple twitter based login/signup system using the tutorial here. I get the oauth_token as well as oauth token secret every time I get the user to login. However, even when the user is already logged in, he is being asked to login again. I just wanted to know how do I check if the user is already logged in?
Do I need to store the oauth_token and oauth token secret in session? If I do store these in a session, how do i authenticate if they are valid?
The library used has something like this:
<?php
session_start();
class EpiOAuth
{
public $version = '1.0';
protected $requestTokenUrl;
protected $accessTokenUrl;
protected $authorizeUrl;
protected $consumerKey;
protected $consumerSecret;
protected $token;
protected $tokenSecret;
protected $signatureMethod;
public function getAccessToken()
{
$resp = $this->httpRequest('GET', $this->accessTokenUrl);
return new EpiOAuthResponse($resp);
}
public function getAuthorizationUrl()
{
$retval = "{$this->authorizeUrl}?";
$token = $this->getRequestToken();
return $this->authorizeUrl . '?oauth_token=' . $token->oauth_token;
}
public function getRequestToken()
{
$resp = $this->httpRequest('GET', $this->requestTokenUrl);
return new EpiOAuthResponse($resp);
}
public function httpRequest($method = null, $url = null, $params = null)
{
if(empty($method) || empty($url))
return false;
if(empty($params['oauth_signature']))
$params = $this->prepareParameters($method, $url, $params);
switch($method)
{
case 'GET':
return $this->httpGet($url, $params);
break;
case 'POST':
return $this->httpPost($url, $params);
break;
}
}
public function setToken($token = null, $secret = null)
{
$params = func_get_args();
$this->token = $token;
$this->tokenSecret = $secret;
}
public function encode($string)
{
return rawurlencode(utf8_encode($string));
}
protected function addOAuthHeaders(&$ch, $url, $oauthHeaders)
{
$_h = array('Expect:');
$urlParts = parse_url($url);
$oauth = 'Authorization: OAuth realm="' . $urlParts['path'] . '",';
foreach($oauthHeaders as $name => $value)
{
$oauth .= "{$name}=\"{$value}\",";
}
$_h[] = substr($oauth, 0, -1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $_h);
}
protected function generateNonce()
{
if(isset($this->nonce)) // for unit testing
return $this->nonce;
return md5(uniqid(rand(), true));
}
protected function generateSignature($method = null, $url = null, $params = null)
{
if(empty($method) || empty($url))
return false;
// concatenating
$concatenatedParams = '';
foreach($params as $k => $v)
{
$v = $this->encode($v);
$concatenatedParams .= "{$k}={$v}&";
}
$concatenatedParams = $this->encode(substr($concatenatedParams, 0, -1));
// normalize url
$normalizedUrl = $this->encode($this->normalizeUrl($url));
$method = $this->encode($method); // don't need this but why not?
$signatureBaseString = "{$method}&{$normalizedUrl}&{$concatenatedParams}";
return $this->signString($signatureBaseString);
}
protected function httpGet($url, $params = null)
{
if(count($params['request']) > 0)
{
$url .= '?';
foreach($params['request'] as $k => $v)
{
$url .= "{$k}={$v}&";
}
$url = substr($url, 0, -1);
}
$ch = curl_init($url);
$this->addOAuthHeaders($ch, $url, $params['oauth']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resp = $this->curl->addCurl($ch);
return $resp;
}
protected function httpPost($url, $params = null)
{
$ch = curl_init($url);
$this->addOAuthHeaders($ch, $url, $params['oauth']);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params['request']));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resp = $this->curl->addCurl($ch);
return $resp;
}
protected function normalizeUrl($url = null)
{
$urlParts = parse_url($url);
$scheme = strtolower($urlParts['scheme']);
$host = strtolower($urlParts['host']);
$port = intval($urlParts['port']);
$retval = "{$scheme}://{$host}";
if($port > 0 && ($scheme === 'http' && $port !== 80) || ($scheme === 'https' && $port !== 443))
{
$retval .= ":{$port}";
}
$retval .= $urlParts['path'];
if(!empty($urlParts['query']))
{
$retval .= "?{$urlParts['query']}";
}
return $retval;
}
protected function prepareParameters($method = null, $url = null, $params = null)
{
if(empty($method) || empty($url))
return false;
$oauth['oauth_consumer_key'] = $this->consumerKey;
$oauth['oauth_token'] = $this->token;
$oauth['oauth_nonce'] = $this->generateNonce();
$oauth['oauth_timestamp'] = !isset($this->timestamp) ? time() : $this->timestamp; // for unit test
$oauth['oauth_signature_method'] = $this->signatureMethod;
$oauth['oauth_version'] = $this->version;
// encoding
array_walk($oauth, array($this, 'encode'));
if(is_array($params))
array_walk($params, array($this, 'encode'));
$encodedParams = array_merge($oauth, (array)$params);
// sorting
ksort($encodedParams);
// signing
$oauth['oauth_signature'] = $this->encode($this->generateSignature($method, $url, $encodedParams));
return array('request' => $params, 'oauth' => $oauth);
}
protected function signString($string = null)
{
$retval = false;
switch($this->signatureMethod)
{
case 'HMAC-SHA1':
$key = $this->encode($this->consumerSecret) . '&' . $this->encode($this->tokenSecret);
$retval = base64_encode(hash_hmac('sha1', $string, $key, true));
break;
}
return $retval;
}
public function __construct($consumerKey, $consumerSecret, $signatureMethod='HMAC-SHA1')
{
$this->consumerKey = $consumerKey;
$this->consumerSecret = $consumerSecret;
$this->signatureMethod = $signatureMethod;
$this->curl = EpiCurl::getInstance();
}
}
class EpiOAuthResponse
{
private $__resp;
public function __construct($resp)
{
$this->__resp = $resp;
}
public function __get($name)
{
if($this->__resp->code < 200 || $this->__resp->code > 299)
return false;
parse_str($this->__resp->data, $result);
foreach($result as $k => $v)
{
$this->$k = $v;
}
return $result[$name];
}
}
The normal flow dictates that applications send request tokens to oauth/authorize in Twitter's implementation of the OAuth Specification. To take advantage of "Sign in with Twitter", applications should send request tokens received in the oauth_token parameter to oauth/authenticate instead.
(c) https://dev.twitter.com/docs/auth/sign-in-with-twitter
So find where their library (or your code) performs request to /authorize endpoint and replace it with /authenticate
About tokens: as long as you've received user tokens - store it in some persistent storage (database, file, etc) since that tokens are permanent (they will be valid until user haven't revoked them manually).
Enable option "Sign in with Twitter" for application OAuth Settings