Я получаю эту странную ошибку, когда я загружаю свой код Cakephp на сервер Site5. Я пытаюсь подключиться к магазину Shopify с плагином частного приложения. Я не уверен, но я думаю, что проблема может заключаться в ограничении серверов Site5 в отношении вызовов curl. Я взял код со страницы общедоступного git-хаба и не внес в него никаких изменений. Когда я подключаюсь через плагин на моем локальном хосте, он работает нормально, но когда я пытаюсь подключиться, сделайте то же самое на сервере, он выдаст ошибку. Код для частного приложения следующий:
class PrivateAPI {
const _LOGIN_URL = 'auth/login';
const _REPORT_CENTER = 'https://reportcenter.shopify.com/';
const _COOKIE_STORE = '/tmp/shopify_cookie.txt';
const _USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17';
protected $ch = null,
$ci = null;
private $inputs = false,
$username = false,
$password = false,
$store = false,
$_token = false,
$_dashboardToken = false;
public function __construct($user, $pass, $store) {
if (!preg_match('/\:\/\//', $store)) {
$store = 'https://' . $store;
}
if (!filter_var($store, FILTER_VALIDATE_URL)) {
throw new \Exception('Invalid store URL');
}
$this->store = $store . (substr($store, -1) == '/' ? '' : '/');
$this->username = $user;
$this->password = $pass;
}
public function __destruct() {
if (is_resource($this->ch)) {
curl_close($this->ch);
}
}
public function isLoggedIn() {
return !is_array($this->getFields());
}
public function dashboardToken() {
return $this->_dashboardToken;
}
public function login() {
$fields = $this->inputs ?: $this->getFields();
$fields['login'] = $this->username;
$fields['password'] = $this->password;
if (isset($fields['_method'])) {
unset($fields['_method']);
}
$url = $this->store . self::_LOGIN_URL;
$this->ch = curl_init($url);
$this->setOpts(array(
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($fields),
CURLOPT_HTTPHEADER => array('Shopify-Auth-Mechanisms:password')
));
$data = curl_exec($this->ch);
$http_code = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
return ($http_code == 200 && $this->setToken($data));
}
public function doRequest($method, $function, $parameters) {
$this->ch = curl_init();
$reportCenter = false;
if (isset($parameters['reportcenter'])) {
$url = self::_REPORT_CENTER . $function;
$reportCenter = true;
$parameters['callback'] = 'fake_function';
$parameters['token'] = $this->dashboardToken();
unset($parameters['reportcenter']);
} else {
$url = (!filter_var($function, FILTER_VALIDATE_URL) ? $this->store : '') . $function;
}
switch ($method) {
case 'POST':
$this->setOpts(array(
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($parameters),
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => array(
'X-Shopify-Api-Features: pagination-headers',
'X-CSRF-Token: ' . $this->_token,
'X-Requested-With: XMLHttpRequest',
'Content-Type: application/json',
'Accept: application/json'
)
));
break;
case 'GET':
default:
$this->setOpts(array(
CURLOPT_HTTPGET => true,
CURLOPT_URL => $url . (count($parameters) ? '?' . urldecode(http_build_query($parameters)) : '')
));
}
$response = curl_exec($this->ch);
if (curl_errno($this->ch)) {
throw new \Exception('Shopify Private API exception: ' . curl_error($this->ch));
}
if ($reportCenter) {
if (strpos($response, 'fake_function') !== FALSE) {
$response = substr($response, strpos($response, '{'));
$response = substr($response, 0, -2);
}
}
$data = json_decode($response);
return is_object($data) ? $data : $response;
}
public function setToken($input) {
$data = filter_var($input, FILTER_VALIDATE_URL) ? $this->initGetData($input) : $input;
if (preg_match('/<meta content="(.*)" name="csrf-token" \/>/i', $data, $token)) {
$this->_token = $token[1];
if (preg_match('/Shopify.set\(\'controllers.dashboard.token\', "(.*)"\)/i', $data, $dashboardToken)) {
$this->_dashboardToken = $dashboardToken[1];
}
return true;
}
throw new \Exception('Failed to set token');
}
private function initGetData($url, $opts = array()) {
if (!filter_var($url, FILTER_VALIDATE_URL)) {
throw new \Exception('Invalid URL: ' . $url);
}
$this->ch = curl_init($url);
$this->setOpts($opts);
if (($http_code = curl_getinfo($this->ch, CURLINFO_HTTP_CODE)) > 300) {
throw new \Exception('Failed to fetch ' . $url . ' (' . $http_code . ')');
}
$data = curl_exec($this->ch);
return $data;
}
private function setOpts($extra = array()) {
$default = array(
CURLOPT_USERAGENT => self::_USER_AGENT,
CURLOPT_COOKIEJAR => self::_COOKIE_STORE,
CURLOPT_COOKIEFILE => self::_COOKIE_STORE,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true
);
$options = $default + array_filter($extra, function($v) {
return !is_null($v);
});
curl_setopt_array($this->ch, $options);
}
private function getFields($data = false) {
$data = $data ?: $this->initGetData($this->store);
if (preg_match('/(<form.*?.*?<\/form>)/is', $data, $matches)) {
$this->inputs = $this->getInputs($matches[1]);
}
return is_array($this->inputs) ? $this->inputs : false;
}
private function getInputs($form, $inputs = array()) {
if (!($els = preg_match_all('/(<input[^>]+>)/is', $form, $matches))) {
return false;
}
for ($i = 0; $i < $els; $i++) {
$el = preg_replace('/\s{2,}/', ' ', $matches[1][$i]);
if (preg_match('/name=(?:["\'])?([^"\'\s]*)/i', $el, $name)
&& preg_match('/value=(?:["\'])?([^"\'\s]*)/i', $el, $value)) {
$inputs[$name[1]] = $value[1];
}
}
return $inputs;
}
}
И ошибка, которую я получаю, очень длинная, но первые несколько ошибок — следующие.
|Exception Object
(
[message:protected] => Failed to set token
[string:Exception:private] =>
[code:protected] => 0
[file:protected] => /home/bebe2goc/public_html/facturas.bebe2go.com/app/Controller/SamplesController.php
[line:protected] => 215
[trace:Exception:private] => Array
(
[0] => Array
(
[file] => /home/bebe2goc/public_html/facturas.bebe2go.com/app/Controller/SamplesController.php
[line] => 157
[function] => setToken
[class] => PrivateAPI
[type] => ->
[args] => Array
(
[0] =>
Очевидно, что соединение с shopify по какой-то причине не может быть завершено. Я хочу знать, есть ли проблема в моем коде или сервер может ограничивать вызовы curl, которые плагин делает для shopify. Ошибка приходит на setToken()
метод. Может кто-нибудь, по крайней мере, указать мне правильное направление: P Я не могу найти проблему по этому поводу.
ОБНОВИТЬ:
Похоже, что призыв к шопификации сделан очень хорошо. Я использовал curl_getinfo, чтобы увидеть, что он возвращает после exec, и это возвращение:
Array (
[url] => https://bebe2go.myshopify.com/admin/auth/login
[content_type] => text/html; charset=utf-8
[http_code] => 200
[header_size] => 2774
[request_size] => 611
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.253468
[namelookup_time] => 3.8E-5
[connect_time] => 0.040116
[pretransfer_time] => 0.138109
[size_upload] => 210
[size_download] => 21475
[speed_download] => 84724
[speed_upload] => 828
[download_content_length] => -1
[upload_content_length] => 210
[starttransfer_time] => 0.253146
[redirect_time] => 0
[certinfo] => Array ( )
[primary_ip] => 23.227.38.68
[primary_port] => 443
[local_ip] => 174.120.252.82
[local_port] => 33288
[redirect_url] => )
По какой-то причине функция входа не работает на сервере, она возвращает пароль или имя пользователя неверно. Но в моем localhost это работает просто отлично. D: есть идеи?
Задача ещё не решена.
Других решений пока нет …