From aa27e8dfdec914d411f8e3fa35f61d7fd0802936 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 15 Jan 2014 09:37:58 +0100 Subject: [PATCH 1/4] [IMPROVED] jsonRPC Error Handling with CURL * [ADDED] Use curl instead of fopen * [ADDED] Error handling for various connection issues * [MOVED] jsonRPC library into lib folder * [UPDATED] Pools page for proper RPC errors with caching enabled It's using the base RPC class but modified to support CURL. Simplified some code since we won't need those features. Should make maintaining that code a whole lot easier. Fixes #1343 once merged. --- public/include/classes/bitcoin.class.php | 33 +--- public/include/jsonRPCClient.php | 167 ------------------- public/include/lib/jsonRPCClient.php | 125 ++++++++++++++ public/include/pages/statistics/pool.inc.php | 25 +-- 4 files changed, 146 insertions(+), 204 deletions(-) delete mode 100644 public/include/jsonRPCClient.php create mode 100644 public/include/lib/jsonRPCClient.php diff --git a/public/include/classes/bitcoin.class.php b/public/include/classes/bitcoin.class.php index d91d5fc2..a26d05b1 100644 --- a/public/include/classes/bitcoin.class.php +++ b/public/include/classes/bitcoin.class.php @@ -229,24 +229,7 @@ class Bitcoin { } } -/** - * Exception class for BitcoinClient - * - * @author Mike Gogulski - * http://www.gogulski.com/ http://www.nostate.com/ - */ -class BitcoinClientException extends ErrorException { - // Redefine the exception so message isn't optional - public function __construct($message, $code = 0, $severity = E_USER_NOTICE, Exception $previous = null) { - parent::__construct($message, $code, $severity, $previous); - } - - public function __toString() { - return __CLASS__ . ": [{$this->code}]: {$this->message}\n"; - } -} - -require_once(INCLUDE_DIR . "/jsonRPCClient.php"); +require_once(INCLUDE_DIR . "/lib/jsonRPCClient.php"); /** * Bitcoin client class for access to a Bitcoin server via JSON-RPC-HTTP[S] @@ -283,21 +266,21 @@ class BitcoinClient extends jsonRPCClient { * @access public * @throws BitcoinClientException */ - public function __construct($scheme, $username, $password, $address = "localhost", $port = 8332, $certificate_path = '', $debug_level = 0) { + public function __construct($scheme, $username, $password, $address = "localhost", $port = 8332, $certificate_path = '', $debug = true) { $scheme = strtolower($scheme); if ($scheme != "http" && $scheme != "https") - throw new BitcoinClientException("Scheme must be http or https"); + throw new Exception("Scheme must be http or https"); if (empty($username)) - throw new BitcoinClientException("Username must be non-blank"); + throw new Exception("Username must be non-blank"); if (empty($password)) - throw new BitcoinClientException("Password must be non-blank"); + throw new Exception("Password must be non-blank"); $port = (string) $port; if (!$port || empty($port) || !is_numeric($port) || $port < 1 || $port > 65535 || floatval($port) != intval($port)) - throw new BitcoinClientException("Port must be an integer and between 1 and 65535"); + throw new Exception("Port must be an integer and between 1 and 65535"); if (!empty($certificate_path) && !is_readable($certificate_path)) - throw new BitcoinClientException("Certificate file " . $certificate_path . " is not readable"); + throw new Exception("Certificate file " . $certificate_path . " is not readable"); $uri = $scheme . "://" . $username . ":" . $password . "@" . $address . "/"; - parent::__construct($uri); + parent::__construct($uri, $debug); } /** diff --git a/public/include/jsonRPCClient.php b/public/include/jsonRPCClient.php deleted file mode 100644 index 2100578f..00000000 --- a/public/include/jsonRPCClient.php +++ /dev/null @@ -1,167 +0,0 @@ - - -This file is part of JSON-RPC PHP. - -JSON-RPC PHP is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -JSON-RPC PHP is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with JSON-RPC PHP; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/** - * The object of this class are generic jsonRPC 1.0 clients - * http://json-rpc.org/wiki/specification - * - * @author sergio - */ -class jsonRPCClient { - - /** - * Debug state - * - * @var boolean - */ - private $debug; - - /** - * The server URL - * - * @var string - */ - private $url; - /** - * The request id - * - * @var integer - */ - private $id; - /** - * If true, notifications are performed instead of requests - * - * @var boolean - */ - private $notification = false; - - /** - * Takes the connection parameters - * - * @param string $url - * @param boolean $debug - */ - public function __construct($url,$debug = false) { - // server URL - $this->url = $url; - // proxy - empty($proxy) ? $this->proxy = '' : $this->proxy = $proxy; - // debug state - empty($debug) ? $this->debug = false : $this->debug = true; - // message id - $this->id = 1; - } - - /** - * Sets the notification state of the object. In this state, notifications are performed, instead of requests. - * - * @param boolean $notification - */ - public function setRPCNotification($notification) { - empty($notification) ? - $this->notification = false - : - $this->notification = true; - } - - /** - * Performs a jsonRCP request and gets the results as an array - * - * @param string $method - * @param array $params - * @return array - */ - public function __call($method,$params) { - - // check - if (!is_scalar($method)) { - throw new Exception('Method name has no scalar value'); - } - - // check - if (is_array($params)) { - // no keys - $params = array_values($params); - } else { - throw new Exception('Params must be given as array'); - } - - // sets notification or request task - if ($this->notification) { - $currentId = NULL; - } else { - $currentId = $this->id; - } - - // prepares the request - $request = array( - 'method' => $method, - 'params' => $params, - 'id' => $currentId - ); - $request = json_encode($request); - $this->debug && $this->debug.='***** Request *****'."\n".$request."\n".'***** End Of request *****'."\n\n"; - - // performs the HTTP POST - $opts = array ('http' => array ( - 'method' => 'POST', - 'header' => 'Content-type: application/json', - 'content' => $request - )); - $context = stream_context_create($opts); - if ($fp = @fopen($this->url, 'r', false, $context)) { - $response = ''; - while($row = fgets($fp)) { - $response.= trim($row)."\n"; - } - $this->debug && $this->debug.='***** Server response *****'."\n".$response.'***** End of server response *****'."\n"; - $response = json_decode($response,true); - } else { - $error = error_get_last(); - $error = explode(']: ', $error['message']); - throw new Exception('Unable to connect: ' . $error[1]); - } - - // debug output - if ($this->debug) { - echo nl2br($debug); - } - - // final checks and return - if (!$this->notification) { - // check - if ($response['id'] != $currentId) { - throw new Exception('Incorrect response id (request id: '.$currentId.', response id: '.$response['id'].')'); - } - if (!is_null($response['error'])) { - throw new Exception('Request error: '.$response['error']); - } - - return $response['result']; - - } else { - return true; - } - } -} -?> diff --git a/public/include/lib/jsonRPCClient.php b/public/include/lib/jsonRPCClient.php new file mode 100644 index 00000000..5fcb72a2 --- /dev/null +++ b/public/include/lib/jsonRPCClient.php @@ -0,0 +1,125 @@ + + +This file is part of JSON-RPC PHP. + +JSON-RPC PHP is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +JSON-RPC PHP is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with JSON-RPC PHP; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/** + * The object of this class are generic jsonRPC 1.0 clients + * http://json-rpc.org/wiki/specification + * + * @author sergio + */ +class jsonRPCClient { + + /** + * Debug state + * + * @var boolean + */ + private $debug; + private $debug_output; + + /** + * The server URL + * + * @var string + */ + private $url; + /** + * The request id + * + * @var integer + */ + private $id; + + /** + * Takes the connection parameters + * + * @param string $url + * @param boolean $debug + */ + public function __construct($url, $debug = false) { + $this->url = $url; + $this->debug = $debug; + $this->debug_output = ''; + $this->id = rand(1, 100); + } + + /** + * Fetch debug information + * @param none + * @return array Debug data + **/ + public function getDebugData() { + return $this->debug_output; + } + + /** + * Performs a jsonRCP request and gets the results as an array + * + * @param string $method + * @param array $params + * @return array + */ + public function __call($method, $params) { + if (!is_scalar($method)) throw new Exception('Method name has no scalar value'); + + if (is_array($params)) { + // no keys + $params = array_values($params); + } else { + throw new Exception('Params must be given as array'); + } + + // prepares the request + $request = array( + 'method' => $method, + 'params' => $params, + 'id' => $this->id + ); + $request = json_encode($request); + if ($this->debug) $this->debug_output[] = 'Request: '.$request; + + // performs the HTTP POST + // extract information from URL for proper authentication + $url = parse_url($this->url); + $ch = curl_init($url['scheme'].'://'.$url['host'].':'.$url['port'].$url['path']); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json')); + curl_setopt($ch, CURLOPT_USERPWD, $url['user'] . ":" . $url['pass']); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $request); + $response = json_decode(curl_exec($ch), true); + $resultStatus = curl_getinfo($ch); + if ($resultStatus['http_code'] != '200') { + if ($resultStatus['http_code'] == '401') throw new Exception('RPC call did not return 200: Authentication failed'); + throw new Exception('RPC call did not return 200: HTTP error: ' . $resultStatus['http_code']); + } + if (curl_errno($ch)) throw new Exception('RPC call failed: ' . curl_error($ch)); + if ($this->debug) $this->debug_output[] = 'Response: ' . $response; + curl_close($ch); + + // final checks and return + if (!is_null($response['error']) || is_null($response)) throw new Exception('Response error or empty: ' . @$response['error']); + if ($response['id'] != $this->id) throw new Exception('Incorrect response id (request id: ' . $this->id . ', response id: ' . $response['id'] . ')'); + return $response['result']; + } +} diff --git a/public/include/pages/statistics/pool.inc.php b/public/include/pages/statistics/pool.inc.php index 84fb3d54..ae42aebc 100644 --- a/public/include/pages/statistics/pool.inc.php +++ b/public/include/pages/statistics/pool.inc.php @@ -3,20 +3,21 @@ // Make sure we are called from index.php if (!defined('SECURITY')) die('Hacking attempt'); +// Fetch data from wallet, always run this check +if ($bitcoin->can_connect() === true){ + $dDifficulty = $bitcoin->getdifficulty(); + $dNetworkHashrate = $bitcoin->getnetworkhashps(); + $iBlock = $bitcoin->getblockcount(); + is_int($iBlock) && $iBlock > 0 ? $sBlockHash = $bitcoin->getblockhash($iBlock) : $sBlockHash = ''; +} else { + $dDifficulty = 1; + $dNetworkHashrate = 1; + $iBlock = 0; + $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); +} + if (!$smarty->isCached('master.tpl', $smarty_cache_key)) { $debug->append('No cached version available, fetching from backend', 3); - // Fetch data from wallet - if ($bitcoin->can_connect() === true){ - $dDifficulty = $bitcoin->getdifficulty(); - $dNetworkHashrate = $bitcoin->getnetworkhashps(); - $iBlock = $bitcoin->getblockcount(); - is_int($iBlock) && $iBlock > 0 ? $sBlockHash = $bitcoin->getblockhash($iBlock) : $sBlockHash = ''; - } else { - $dDifficulty = 1; - $dNetworkHashrate = 1; - $iBlock = 0; - $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); - } // Top share contributors $aContributorsShares = $statistics->getTopContributors('shares', 15); From c42fc607422c560452bc79cf467d81122e1b4f37 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 15 Jan 2014 14:34:02 +0100 Subject: [PATCH 2/4] [FIX] Proper response string for debug output --- public/include/lib/jsonRPCClient.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/public/include/lib/jsonRPCClient.php b/public/include/lib/jsonRPCClient.php index 5fcb72a2..81f61d70 100644 --- a/public/include/lib/jsonRPCClient.php +++ b/public/include/lib/jsonRPCClient.php @@ -107,14 +107,15 @@ class jsonRPCClient { curl_setopt($ch, CURLOPT_USERPWD, $url['user'] . ":" . $url['pass']); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $request); - $response = json_decode(curl_exec($ch), true); + $response = curl_exec($ch); + if ($this->debug) $this->debug_output[] = 'Response: ' . $response; + $response = json_decode($response, true); $resultStatus = curl_getinfo($ch); if ($resultStatus['http_code'] != '200') { if ($resultStatus['http_code'] == '401') throw new Exception('RPC call did not return 200: Authentication failed'); throw new Exception('RPC call did not return 200: HTTP error: ' . $resultStatus['http_code']); } if (curl_errno($ch)) throw new Exception('RPC call failed: ' . curl_error($ch)); - if ($this->debug) $this->debug_output[] = 'Response: ' . $response; curl_close($ch); // final checks and return From f2f539ef53586ecfdd10050569d6ffc91491b32c Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 15 Jan 2014 15:16:54 +0100 Subject: [PATCH 3/4] [IMPROVED] Payout logging and indent --- cronjobs/payouts.php | 2 +- public/include/lib/jsonRPCClient.php | 149 ++++++++++++++------------- 2 files changed, 76 insertions(+), 75 deletions(-) diff --git a/cronjobs/payouts.php b/cronjobs/payouts.php index 4623b411..4ca52627 100755 --- a/cronjobs/payouts.php +++ b/cronjobs/payouts.php @@ -68,7 +68,7 @@ if ($setting->getValue('disable_manual_payouts') != 1) { try { $txid = $bitcoin->sendtoaddress($aData['coin_address'], $dBalance - $config['txfee_manual']); } catch (Exception $e) { - $log->logError('Failed to send requested balance to coin address, please check payout process. Does the wallet cover the amount?'); + $log->logError('Failed to send requested balance to coin address, please check payout process. Does the wallet cover the amount? Error:' . $e->getMessage()); continue; } diff --git a/public/include/lib/jsonRPCClient.php b/public/include/lib/jsonRPCClient.php index 81f61d70..8385b30e 100644 --- a/public/include/lib/jsonRPCClient.php +++ b/public/include/lib/jsonRPCClient.php @@ -1,6 +1,6 @@ @@ -19,7 +19,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JSON-RPC PHP; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ + */ /** * The object of this class are generic jsonRPC 1.0 clients @@ -28,41 +28,41 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * @author sergio */ class jsonRPCClient { - - /** - * Debug state - * - * @var boolean - */ - private $debug; + + /** + * Debug state + * + * @var boolean + */ + private $debug; private $debug_output; - - /** - * The server URL - * - * @var string - */ - private $url; - /** - * The request id - * - * @var integer - */ - private $id; - - /** - * Takes the connection parameters - * - * @param string $url - * @param boolean $debug - */ - public function __construct($url, $debug = false) { - $this->url = $url; - $this->debug = $debug; + + /** + * The server URL + * + * @var string + */ + private $url; + /** + * The request id + * + * @var integer + */ + private $id; + + /** + * Takes the connection parameters + * + * @param string $url + * @param boolean $debug + */ + public function __construct($url, $debug = false) { + $this->url = $url; + $this->debug = $debug; $this->debug_output = ''; - $this->id = rand(1, 100); - } - + $this->id = rand(1, 100); + } + /** * Fetch debug information * @param none @@ -72,42 +72,43 @@ class jsonRPCClient { return $this->debug_output; } - /** - * Performs a jsonRCP request and gets the results as an array - * - * @param string $method - * @param array $params - * @return array - */ - public function __call($method, $params) { - if (!is_scalar($method)) throw new Exception('Method name has no scalar value'); - - if (is_array($params)) { - // no keys - $params = array_values($params); - } else { - throw new Exception('Params must be given as array'); - } - - // prepares the request - $request = array( - 'method' => $method, - 'params' => $params, - 'id' => $this->id - ); - $request = json_encode($request); - if ($this->debug) $this->debug_output[] = 'Request: '.$request; - - // performs the HTTP POST + /** + * Performs a jsonRCP request and gets the results as an array + * + * @param string $method + * @param array $params + * @return array + */ + public function __call($method, $params) { + if (!is_scalar($method)) throw new Exception('Method name has no scalar value'); + + if (is_array($params)) { + // no keys + $params = array_values($params); + } else { + throw new Exception('Params must be given as array'); + } + + // prepares the request + $request = array( + 'method' => $method, + 'params' => $params, + 'id' => $this->id + ); + $request = json_encode($request); + if ($this->debug) $this->debug_output[] = 'Request: '.$request; + + // performs the HTTP POST // extract information from URL for proper authentication $url = parse_url($this->url); - $ch = curl_init($url['scheme'].'://'.$url['host'].':'.$url['port'].$url['path']); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json')); + $ch = curl_init($url['scheme'].'://'.$url['host'].':'.$url['port'].$url['path']); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json')); curl_setopt($ch, CURLOPT_USERPWD, $url['user'] . ":" . $url['pass']); - curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, $request); - $response = curl_exec($ch); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $request); + $response = curl_exec($ch); + $this->debug = true; if ($this->debug) $this->debug_output[] = 'Response: ' . $response; $response = json_decode($response, true); $resultStatus = curl_getinfo($ch); @@ -116,11 +117,11 @@ class jsonRPCClient { throw new Exception('RPC call did not return 200: HTTP error: ' . $resultStatus['http_code']); } if (curl_errno($ch)) throw new Exception('RPC call failed: ' . curl_error($ch)); - curl_close($ch); + curl_close($ch); - // final checks and return - if (!is_null($response['error']) || is_null($response)) throw new Exception('Response error or empty: ' . @$response['error']); - if ($response['id'] != $this->id) throw new Exception('Incorrect response id (request id: ' . $this->id . ', response id: ' . $response['id'] . ')'); - return $response['result']; - } + // final checks and return + if (!is_null($response['error']) || is_null($response)) throw new Exception('Response error or empty: ' . @$response['error']); + if ($response['id'] != $this->id) throw new Exception('Incorrect response id (request id: ' . $this->id . ', response id: ' . $response['id'] . ')'); + return $response['result']; + } } From 610e564c2f50c01f06e4cd0333c84498e41188c0 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 15 Jan 2014 16:28:26 +0100 Subject: [PATCH 4/4] [IMPROVED] Further improvements on error handling --- public/include/classes/bitcoin.class.php | 5 +---- public/include/classes/bitcoinwrapper.class.php | 9 +++++---- public/include/lib/jsonRPCClient.php | 6 +++--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/public/include/classes/bitcoin.class.php b/public/include/classes/bitcoin.class.php index a26d05b1..f1512c70 100644 --- a/public/include/classes/bitcoin.class.php +++ b/public/include/classes/bitcoin.class.php @@ -266,7 +266,7 @@ class BitcoinClient extends jsonRPCClient { * @access public * @throws BitcoinClientException */ - public function __construct($scheme, $username, $password, $address = "localhost", $port = 8332, $certificate_path = '', $debug = true) { + public function __construct($scheme, $username, $password, $address = "localhost", $certificate_path = '', $debug = false) { $scheme = strtolower($scheme); if ($scheme != "http" && $scheme != "https") throw new Exception("Scheme must be http or https"); @@ -274,9 +274,6 @@ class BitcoinClient extends jsonRPCClient { throw new Exception("Username must be non-blank"); if (empty($password)) throw new Exception("Password must be non-blank"); - $port = (string) $port; - if (!$port || empty($port) || !is_numeric($port) || $port < 1 || $port > 65535 || floatval($port) != intval($port)) - throw new Exception("Port must be an integer and between 1 and 65535"); if (!empty($certificate_path) && !is_readable($certificate_path)) throw new Exception("Certificate file " . $certificate_path . " is not readable"); $uri = $scheme . "://" . $username . ":" . $password . "@" . $address . "/"; diff --git a/public/include/classes/bitcoinwrapper.class.php b/public/include/classes/bitcoinwrapper.class.php index ed4c09a8..b2167611 100644 --- a/public/include/classes/bitcoinwrapper.class.php +++ b/public/include/classes/bitcoinwrapper.class.php @@ -9,15 +9,16 @@ if (!defined('SECURITY')) * some basic caching functionality and some debugging **/ class BitcoinWrapper extends BitcoinClient { - public function __construct($type, $username, $password, $host, $debug, $memcache) { + public function __construct($type, $username, $password, $host, $debug_level, $debug_object, $memcache) { $this->type = $type; $this->username = $username; $this->password = $password; $this->host = $host; // $this->debug is already used - $this->oDebug = $debug; + $this->oDebug = $debug_object; $this->memcache = $memcache; - return parent::__construct($this->type, $this->username, $this->password, $this->host); + $debug_level > 0 ? $debug_level = true : $debug_level = false; + return parent::__construct($this->type, $this->username, $this->password, $this->host, '', $debug_level); } /** * Wrap variouns methods to add caching @@ -75,4 +76,4 @@ class BitcoinWrapper extends BitcoinClient { } // Load this wrapper -$bitcoin = new BitcoinWrapper($config['wallet']['type'], $config['wallet']['username'], $config['wallet']['password'], $config['wallet']['host'], $debug, $memcache); +$bitcoin = new BitcoinWrapper($config['wallet']['type'], $config['wallet']['username'], $config['wallet']['password'], $config['wallet']['host'], DEBUG, $debug, $memcache); diff --git a/public/include/lib/jsonRPCClient.php b/public/include/lib/jsonRPCClient.php index 8385b30e..f25fb0b9 100644 --- a/public/include/lib/jsonRPCClient.php +++ b/public/include/lib/jsonRPCClient.php @@ -35,7 +35,7 @@ class jsonRPCClient { * @var boolean */ private $debug; - private $debug_output; + private $debug_output = NULL; /** * The server URL @@ -69,7 +69,8 @@ class jsonRPCClient { * @return array Debug data **/ public function getDebugData() { - return $this->debug_output; + if ($this->debug) return $this->debug_output; + return false; } /** @@ -108,7 +109,6 @@ class jsonRPCClient { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $request); $response = curl_exec($ch); - $this->debug = true; if ($this->debug) $this->debug_output[] = 'Response: ' . $response; $response = json_decode($response, true); $resultStatus = curl_getinfo($ch);