PageRenderTime 65ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/wp-lister-for-ebay/includes/EbatNs/EbatNs_Client.php

https://bitbucket.org/sanders_nick/my-maxi-skirt
PHP | 1125 lines | 830 code | 182 blank | 113 comment | 88 complexity | a99eaee722cddbe092d2dd800b9a909e MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, AGPL-1.0, GPL-3.0, LGPL-2.1
  1. <?php
  2. // $Id: EbatNs_Client.php,v 1.14 2008-10-08 10:31:19 carsten Exp $
  3. // $Log: EbatNs_Client.php,v $
  4. // Revision 1.14 2008-10-08 10:31:19 carsten
  5. // changed the way the meta data is stored for schema objects. Now the information is helt in a static array (in EbatNs_ComplexType) for ALL schema classes.
  6. // Beside changes in the Core and the ComplexType class this will also need a different way how the schema-information is stored within the constructors of all generated schema-classes.
  7. //
  8. // Revision 1.13 2008/10/02 13:54:15 carsten
  9. // added batched operation via curl multi
  10. //
  11. // Revision 1.12 2008/09/29 13:37:04 michael
  12. // added $this->_incrementApiUsage($method) to callShoppingApiStyle()
  13. //
  14. // Revision 1.11 2008/06/13 08:51:56 michael
  15. // added method getSession()
  16. //
  17. // Revision 1.10 2008/06/13 06:59:17 michael
  18. // fixed php5 issue
  19. //
  20. // Revision 1.9 2008/06/09 13:55:56 michael
  21. // *** empty log message ***
  22. //
  23. //
  24. // Revision 1.5 2008/06/05 08:22:12 michael
  25. // added sandbox support for shopping api
  26. //
  27. // Revision 1.4 2008/05/29 07:38:11 michael
  28. // - adapted correct sandbox url for shopping api
  29. // - use setter for token for PHP5 version
  30. //
  31. // Revision 1.3 2008/05/28 16:53:18 michael
  32. // fixed and moved method getErrorsToString() to Client
  33. //
  34. // Revision 1.2 2008/05/02 15:04:05 carsten
  35. // Initial, PHP5
  36. //
  37. //
  38. require_once 'UserIdPasswordType.php';
  39. require_once 'EbatNs_RequesterCredentialType.php';
  40. require_once 'EbatNs_RequestHeaderType.php';
  41. require_once 'EbatNs_ResponseError.php';
  42. require_once 'EbatNs_ResponseParser.php';
  43. require_once 'EbatNs_DataConverter.php';
  44. class EbatNs_Client
  45. {
  46. // endpoint for call
  47. protected $_ep;
  48. protected $_session;
  49. protected $_currentResult;
  50. protected $_parser = null;
  51. // callback-methods/functions for data-handling
  52. protected $_hasCallbacks = false;
  53. protected $_callbacks = null;
  54. // EbatNs_DataConverter object
  55. protected $_dataConverter = null;
  56. protected $_logger = null;
  57. protected $_parserOptions = null;
  58. protected $_paginationElementCounter = 0;
  59. protected $_paginationMaxElements = -1;
  60. protected $_transportOptions = array();
  61. protected $_loggingOptions = array();
  62. protected $_callUsage = array();
  63. //
  64. // timepoint-tracing
  65. //
  66. protected $_timePoints = null;
  67. protected $_timePointsSEQ = null;
  68. protected $_selectorModels = array();
  69. protected $_activeSelectorModel = null;
  70. /**
  71. * Curl MultiHandle
  72. *
  73. * @var mixed
  74. */
  75. protected $mh;
  76. protected $useCurlBatch = false;
  77. protected $chMultiHandles = array();
  78. protected $nextMultiIndex = 0;
  79. protected $resultMethods = array();
  80. protected $responseData = array();
  81. public function startBatchOperation()
  82. {
  83. $this->mh = curl_multi_init();
  84. $this->useCurlBatch = true;
  85. $this->nextMultiIndex = 0;
  86. }
  87. public function cleanBatchOperation()
  88. {
  89. $this->responseData = array();
  90. $this->nextMultiIndex = 0;
  91. $this->mh = null;
  92. }
  93. /**
  94. * Add the given curl-handle to an internal list and returns the index we added it to
  95. *
  96. * @param mixed $ch
  97. * @return number
  98. */
  99. protected function saveCurlMultiHandle($ch)
  100. {
  101. $this->chMultiHandles[$this->nextMultiIndex] = $ch;
  102. $ret = $this->nextMultiIndex;
  103. $this->nextMultiIndex++;
  104. return $ret;
  105. }
  106. public function executeBatchOperation()
  107. {
  108. // not using a batch-operation
  109. if (!$this->useCurlBatch)
  110. return null;
  111. $this->_startTp('executeBatchOperation');
  112. // lets execute the batch-operation
  113. $running = null;
  114. do {
  115. curl_multi_exec($this->mh, $running);
  116. } while($running > 0);
  117. foreach ($this->chMultiHandles as $id => $ch)
  118. {
  119. $responseRaw = curl_multi_getcontent( $ch );
  120. if ( !$responseRaw )
  121. {
  122. $currentResult = new EbatNs_ResponseError();
  123. $currentResult->raise( 'curl_error ' . curl_errno( $ch ) . ' ' . curl_error( $ch ), 80000 + 1, EBAT_SEVERITY_ERROR );
  124. $this->responseData[$id] = $currentResult;
  125. }
  126. else
  127. {
  128. $responseBody = null;
  129. if ( preg_match( "/^(.*?)\r?\n\r?\n(.*)/s", $responseRaw, $match ) )
  130. {
  131. $responseBody = $match[2];
  132. $headerLines = split( "\r?\n", $match[1] );
  133. foreach ( $headerLines as $line )
  134. {
  135. if ( strpos( $line, ':' ) === false )
  136. {
  137. $responseHeaders[0] = $line;
  138. continue;
  139. }
  140. list( $key, $value ) = split( ':', $line );
  141. $responseHeaders[strtolower( $key )] = trim( $value );
  142. }
  143. }
  144. if ($responseBody)
  145. $this->logXml( $responseBody, 'Response' );
  146. else
  147. $this->logXml( $responseRaw, 'ResponseRaw' );
  148. $this->responseData[$id] = $this->decodeMessage(
  149. $this->resultMethods[$id],
  150. $responseBody,
  151. EBATNS_PARSEMODE_CALL );
  152. }
  153. curl_multi_remove_handle($this->mh, $ch);
  154. }
  155. curl_multi_close($this->mh);
  156. $this->chMultiHandles = array();
  157. $this->resultMethods = array();
  158. $this->useCurlBatch = false;
  159. $this->_stopTp('executeBatchOperation');
  160. $this->_logTp();
  161. print_r($this->_loggingOptions);
  162. // makes sense to clean this up
  163. // so use cleanBatchOperation once the result is proceeded
  164. return $this->responseData;
  165. }
  166. function getVersion()
  167. {
  168. return EBAY_WSDL_VERSION;
  169. }
  170. function __construct($session, $converter = 'EbatNs_DataConverterIso' )
  171. {
  172. $this->_session = $session;
  173. if ($converter)
  174. $this->_dataConverter = new $converter();
  175. $this->_parser = null;
  176. $timeout = $session->getRequestTimeout();
  177. if (!$timeout)
  178. $timeout = 300;
  179. $httpCompress = $session->getUseHttpCompression();
  180. $this->setTransportOptions(
  181. array(
  182. 'HTTP_TIMEOUT' => $timeout,
  183. 'HTTP_COMPRESS' => $httpCompress));
  184. if ($session->getUseStandardLogger())
  185. $this->useStandardLogger();
  186. }
  187. function useStandardLogger()
  188. {
  189. require_once 'EbatNs_Logger.php';
  190. $this->attachLogger(new EbatNs_Logger(true, 'stdout', true, true));
  191. }
  192. function resetPaginationCounter($maxElements = -1)
  193. {
  194. $this->_paginationElementCounter = 0;
  195. if ($maxElements > 0)
  196. $this->_paginationMaxElements = $maxElements;
  197. else
  198. $this->_paginationMaxElements = -1;
  199. }
  200. function incrementPaginationCounter()
  201. {
  202. $this->_paginationElementCounter++;
  203. if ($this->_paginationMaxElements > 0 && ($this->_paginationElementCounter > $this->_paginationMaxElements))
  204. return false;
  205. else
  206. return true;
  207. }
  208. function getPaginationCounter()
  209. {
  210. return $this->_paginationElementCounter;
  211. }
  212. function setParserOption($name, $value = true)
  213. {
  214. $this->_parserOptions[$name] = $value;
  215. }
  216. function log( $msg, $subject = null )
  217. {
  218. if ( $this->_logger )
  219. $this->_logger->log( $msg, $subject );
  220. }
  221. function logXml( $xmlMsg, $subject = null )
  222. {
  223. if ( $this->_logger )
  224. $this->_logger->logXml( $xmlMsg, $subject );
  225. }
  226. function attachLogger($logger)
  227. {
  228. $this->_logger = $logger;
  229. }
  230. // HTTP_TIMEOUT: default 300 s
  231. // HTTP_COMPRESS: default true
  232. function setTransportOptions($options)
  233. {
  234. $this->_transportOptions = array_merge($this->_transportOptions, $options);
  235. }
  236. // LOG_TIMEPOINTS: true/false
  237. // LOG_API_USAGE: true/false
  238. function setLoggingOptions($options)
  239. {
  240. $this->_loggingOptions = array_merge($this->_loggingOptions, $options);
  241. }
  242. protected function _getMicroseconds()
  243. {
  244. list( $ms, $s ) = explode( ' ', microtime() );
  245. return floor( $ms * 1000 ) + 1000 * $s;
  246. }
  247. protected function _getElapsed( $start )
  248. {
  249. return $this->_getMicroseconds() - $start;
  250. }
  251. protected function _startTp( $key )
  252. {
  253. if (!$this->_loggingOptions['LOG_TIMEPOINTS'])
  254. return;
  255. if ( isset( $this->_timePoints[$key] ) )
  256. $tp = $this->_timePoints[$key];
  257. $tp['start_tp'] = time();
  258. $tp['start'] = $this->_getMicroseconds();
  259. $this->_timePoints[$key] = $tp;
  260. }
  261. protected function _stopTp( $key )
  262. {
  263. if (!$this->_loggingOptions['LOG_TIMEPOINTS'])
  264. return;
  265. if ( isset( $this->_timePoints[$key]['start'] ) )
  266. {
  267. $tp = $this->_timePoints[$key];
  268. $tp['duration'] = $this->_getElapsed( $tp['start'] ) . 'ms';
  269. unset( $tp['start'] );
  270. $this->_timePoints[$key] = $tp;
  271. }
  272. }
  273. protected function _logTp()
  274. {
  275. if (!$this->_loggingOptions['LOG_TIMEPOINTS'])
  276. return;
  277. // log the timepoint-information
  278. ob_start();
  279. echo "<pre><br>\n";
  280. print_r($this->_timePoints);
  281. print_r("</pre><br>\n");
  282. $msg = ob_get_clean();
  283. $this->log($msg, '_EBATNS_TIMEPOINTS');
  284. }
  285. //
  286. // end timepoint-tracing
  287. //
  288. // callusage
  289. protected function _incrementApiUsage($apiCall)
  290. {
  291. if (!$this->_loggingOptions['LOG_API_USAGE'])
  292. return;
  293. $this->_callUsage[$apiCall] = $this->_callUsage[$apiCall] + 1;
  294. }
  295. function getApiUsage()
  296. {
  297. return $this->_callUsage;
  298. }
  299. function getParser($tns = 'urn:ebay:apis:eBLBaseComponents', $parserOptions = null, $recreate = true)
  300. {
  301. if ($recreate)
  302. $this->_parser = null;
  303. if (!$this->_parser)
  304. {
  305. if ($parserOptions)
  306. $this->_parserOptions = $parserOptions;
  307. $this->_parser = new EbatNs_ResponseParser( $this, $tns, $this->_parserOptions );
  308. }
  309. return $this->_parser;
  310. }
  311. // should return true if the data should NOT be included to the
  312. // response-object !
  313. function _handleDataType( $typeName, $value, $mapName )
  314. {
  315. if ( $this->_hasCallbacks )
  316. {
  317. if (isset($this->_callbacks[strtolower( $typeName )]))
  318. $callback = $this->_callbacks[strtolower( $typeName )];
  319. else
  320. $callback = null;
  321. if ( $callback )
  322. {
  323. if ( is_object( $callback['object'] ) )
  324. {
  325. return call_user_method( $callback['method'], $callback['object'], $typeName, & $value, $mapName, & $this );
  326. }
  327. else
  328. {
  329. return call_user_func( $callback['method'], $typeName, & $value, $mapName, & $this );
  330. }
  331. }
  332. }
  333. return false;
  334. }
  335. // $typeName as defined in Schema
  336. // $method (callback, either string or array with object/method)
  337. function setHandler( $typeName, $method )
  338. {
  339. $this->_hasCallbacks = true;
  340. if ( is_array( $method ) )
  341. {
  342. $callback['object'] = $method[0];
  343. $callback['method'] = $method[1];
  344. }
  345. else
  346. {
  347. $callback['object'] = null;
  348. $callback['method'] = $method;
  349. }
  350. $this->_callbacks[strtolower( $typeName )] = $callback;
  351. }
  352. function _makeSessionHeader()
  353. {
  354. $cred = new UserIdPasswordType();
  355. $cred->setAppId($this->_session->getAppId());
  356. $cred->setDevId($this->_session->getDevId());
  357. $cred->setAuthCert($this->_session->getCertId());
  358. if ( $this->_session->getTokenMode() == 0 )
  359. {
  360. $cred->setUsername($this->_session->getRequestUser());
  361. $cred->setPassword($this->_session->getRequestPassword());
  362. }
  363. $reqCred = new EbatNs_RequesterCredentialType();
  364. $reqCred->setCredentials($cred);
  365. if ( $this->_session->getTokenMode() == 1 )
  366. {
  367. $this->_session->ReadTokenFile();
  368. $reqCred->setEBayAuthToken($this->_session->getRequestToken());
  369. }
  370. $header = new EbatNs_RequestHeaderType();
  371. $header->setRequesterCredentials($reqCred);
  372. return $header;
  373. }
  374. function call( $method, $request, $parseMode = EBATNS_PARSEMODE_CALL )
  375. {
  376. if
  377. (
  378. $this->_activeSelectorModel
  379. && $this->_selectorModels[$this->_activeSelectorModel][$method]
  380. )
  381. {
  382. $request->setOutputSelector
  383. (
  384. $this->_selectorModels[$this->_activeSelectorModel][$method]->getSelectorArray()
  385. );
  386. }
  387. $this->_startTp('API call ' . $method);
  388. $this->_incrementApiUsage($method);
  389. $this->_startTp('Encoding SOAP Message');
  390. $body = $this->encodeMessage( $method, $request );
  391. $header = $this->_makeSessionHeader();
  392. $message = $this->buildMessage( $body, $header );
  393. $ep = $this->_session->getApiUrl();
  394. $ep .= '?callname=' . $method;
  395. $ep .= '&siteid=' . $this->_session->getSiteId();
  396. $ep .= '&appid=' . $this->_session->getAppId();
  397. $ep .= '&version=' . $this->getVersion();
  398. $ep .= '&routing=default';
  399. $this->_ep = $ep;
  400. $this->_stopTp('Encoding SOAP Message');
  401. $this->_startTp('Sending SOAP Message');
  402. $responseMsg = $this->sendMessage( $message );
  403. $this->_stopTp('Sending SOAP Message');
  404. if ( $responseMsg )
  405. {
  406. $this->_startTp('Decoding SOAP Message');
  407. $ret = & $this->decodeMessage( $method, $responseMsg, $parseMode );
  408. $this->_stopTp('Decoding SOAP Message');
  409. }
  410. else
  411. {
  412. $ret = & $this->_currentResult;
  413. }
  414. $this->_stopTp('API call ' . $method);
  415. $this->_logTp();
  416. return $ret;
  417. }
  418. // should return a serialized XML of the outgoing message
  419. function encodeMessage( $method, $request )
  420. {
  421. return $request->serialize( $method . 'Request', $request, null, true, null, $this->_dataConverter );
  422. }
  423. // should transform the response (body) to a PHP object structure
  424. function decodeMessage( $method, $msg, $parseMode )
  425. {
  426. $this->_parser = &new EbatNs_ResponseParser( $this, 'urn:ebay:apis:eBLBaseComponents', $this->_parserOptions );
  427. return $this->_parser->decode( $method . 'Response', $msg, $parseMode );
  428. }
  429. // should generate a complete SOAP-envelope for the request
  430. function buildMessage( $body, $header )
  431. {
  432. $soap = '<?xml version="1.0" encoding="utf-8"?>';
  433. $soap .= '<soap:Envelope';
  434. $soap .= ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"';
  435. $soap .= ' xmlns:xsd="http://www.w3.org/2001/XMLSchema"';
  436. $soap .= ' xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"';
  437. $soap .= ' encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"';
  438. $soap .= ' xmlns="urn:ebay:apis:eBLBaseComponents"';
  439. $soap .= ' >';
  440. if ( $header )
  441. $soap .= $header->serialize( 'soap:Header', $header, null, true, null, null );
  442. $soap .= '<soap:Body>';
  443. $soap .= $body;
  444. $soap .= '</soap:Body>';
  445. $soap .= '</soap:Envelope>';
  446. return $soap;
  447. }
  448. // this method will generate a notification-style message body
  449. // out of a response from a call
  450. function _buildNotificationMessage($response, $simulatedMessageName, $tns, $addData = null)
  451. {
  452. if ($addData)
  453. {
  454. foreach($addData as $key => $value)
  455. {
  456. $response->{$key} = $value;
  457. }
  458. }
  459. $response->setTypeAttribute('xmlns', $tns);
  460. $msgBody = $response->serialize( $simulatedMessageName, $response, isset($response->attributeValues) ? $response->attributeValues : null, true, null, $this->_dataConverter );
  461. $soap = '<?xml version="1.0" encoding="utf-8"?>';
  462. $soap .= '<soapenv:Envelope';
  463. $soap .= ' xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"';
  464. $soap .= ' xmlns:xsd="http://www.w3.org/2001/XMLSchema"';
  465. $soap .= ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"';
  466. $soap .= '>';
  467. $soap .= '<soapenv:Header>';
  468. $soap .= '<ebl:RequesterCredentials soapenv:mustUnderstand="0" xmlns:ns="urn:ebay:apis:eBLBaseComponents" xmlns:ebl="urn:ebay:apis:eBLBaseComponents">';
  469. $soap .= '<ebl:NotificationSignature xmlns:ebl="urn:ebay:apis:eBLBaseComponents">invalid_simulation</ebl:NotificationSignature>';
  470. $soap .= '</ebl:RequesterCredentials>';
  471. $soap .= '</soapenv:Header>';
  472. $soap .= '<soapenv:Body>';
  473. $soap .= $msgBody;
  474. $soap .= '</soapenv:Body>';
  475. $soap .= '</soapenv:Envelope>';
  476. return $soap;
  477. }
  478. // should send the message to the endpoint
  479. // the result should be parsed out of the envelope and return as the plain
  480. // response-body.
  481. function sendMessage( $message )
  482. {
  483. $this->_currentResult = null;
  484. $this->log( $this->_ep, 'RequestUrl' );
  485. $this->logXml( $message, 'Request' );
  486. $timeout = $this->_transportOptions['HTTP_TIMEOUT'];
  487. if (!$timeout || $timeout <= 0)
  488. $timeout = 300;
  489. $soapaction = 'dummy';
  490. $ch = curl_init();
  491. $reqHeaders[] = 'Content-Type: text/xml;charset=utf-8';
  492. if ($this->_transportOptions['HTTP_COMPRESS'])
  493. {
  494. $reqHeaders[] = 'Accept-Encoding: gzip, deflate';
  495. curl_setopt( $ch, CURLOPT_ENCODING, "gzip");
  496. curl_setopt( $ch, CURLOPT_ENCODING, "deflate");
  497. }
  498. $reqHeaders[] = 'SOAPAction: "' . $soapaction . '"';
  499. curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false);
  500. curl_setopt( $ch, CURLOPT_HTTPHEADER, $reqHeaders );
  501. curl_setopt( $ch, CURLOPT_USERAGENT, 'ebatns;1.0' );
  502. curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
  503. curl_setopt( $ch, CURLOPT_POSTFIELDS, $message );
  504. curl_setopt( $ch, CURLOPT_URL, $this->_ep );
  505. curl_setopt( $ch, CURLOPT_POST, 1 );
  506. curl_setopt( $ch, CURLOPT_FAILONERROR, 0 );
  507. curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 );
  508. curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
  509. curl_setopt( $ch, CURLOPT_HEADER, 1 );
  510. curl_setopt( $ch, CURLOPT_HTTP_VERSION, 1 );
  511. // added support for multi-threaded clients
  512. if (isset($this->_transportOptions['HTTP_CURL_MULTITHREADED']))
  513. {
  514. curl_setopt( $ch, CURLOPT_DNS_USE_GLOBAL_CACHE, 0 );
  515. // be aware of the following:
  516. // - CURLOPT_NOSIGNAL is NOT defined in the standard-PHP cURL ext (PHP 4.x)
  517. // so the usage need a patch and rebuild of the curl.so or "inline" PHP Version
  518. // Not using CURLOPT_NOSIGNAL might break if any signal-handlers are installed. So
  519. // the usage might be recommend but it is not must.
  520. // curl_setopt( $ch, CURLOPT_NOSIGNAL, true);
  521. // - using cURL together with OpenSSL absolutely needs the multi-threading
  522. // looking functions for OpenSSL (see http://curl.haxx.se/libcurl/c/libcurl-tutorial.html#Multi-threading)
  523. // As these callbacks are NOT implemented in PHP 4.x BUT in PHP 5.x you have to do the implementation
  524. // for your own in PHP 4.x or switch to PHP 5.x
  525. }
  526. if ($this->_transportOptions['HTTP_VERBOSE'])
  527. {
  528. curl_setopt( $ch, CURLOPT_VERBOSE, 1 );
  529. ob_start();
  530. }
  531. // if running in batched mode just add the call to the multi-handle
  532. if ($this->useCurlBatch)
  533. {
  534. curl_multi_add_handle($this->mh, $ch);
  535. return $this->saveCurlMultiHandle($ch);
  536. }
  537. $responseRaw = curl_exec( $ch );
  538. if ( !$responseRaw )
  539. {
  540. $this->_currentResult = new EbatNs_ResponseError();
  541. $this->_currentResult->raise( 'curl_error ' . curl_errno( $ch ) . ' ' . curl_error( $ch ), 80000 + 1, EBAT_SEVERITY_ERROR );
  542. curl_close( $ch );
  543. return null;
  544. }
  545. else
  546. {
  547. curl_close( $ch );
  548. $responseBody = null;
  549. if ( preg_match( "/^(.*?)\r?\n\r?\n(.*)/s", $responseRaw, $match ) )
  550. {
  551. $responseBody = $match[2];
  552. $headerLines = split( "\r?\n", $match[1] );
  553. foreach ( $headerLines as $line )
  554. {
  555. if ( strpos( $line, ':' ) === false )
  556. {
  557. $responseHeaders[0] = $line;
  558. continue;
  559. }
  560. list( $key, $value ) = split( ':', $line );
  561. $responseHeaders[strtolower( $key )] = trim( $value );
  562. }
  563. }
  564. if ($responseBody)
  565. $this->logXml( $responseBody, 'Response' );
  566. else
  567. $this->logXml( $responseRaw, 'ResponseRaw' );
  568. }
  569. return $responseBody;
  570. }
  571. function callShoppingApiStyle($method, $request, $parseMode = EBATNS_PARSEMODE_CALL)
  572. {
  573. if ($this->_session->getAppMode() == 1)
  574. $ep = 'http://open.api.sandbox.ebay.com/shopping';
  575. else
  576. $ep = 'http://open.api.ebay.com/shopping';
  577. $this->_incrementApiUsage($method);
  578. // place all data into theirs header
  579. $reqHeaders[] = 'X-EBAY-API-VERSION: ' . $this->getVersion();
  580. $reqHeaders[] = 'X-EBAY-API-APP-ID: ' . $this->_session->getAppId();
  581. $reqHeaders[] = 'X-EBAY-API-CALL-NAME: ' . $method;
  582. $siteId = $this->_session->getSiteId();
  583. if (empty($siteId))
  584. $reqHeaders[] = 'X-EBAY-API-SITE-ID: 0';
  585. else
  586. $reqHeaders[] = 'X-EBAY-API-SITE-ID: ' . $siteId;
  587. $reqHeaders[] = 'X-EBAY-API-REQUEST-ENCODING: XML';
  588. $body = $this->encodeMessageXmlStyle( $method, $request );
  589. $message = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
  590. $message .= $body;
  591. $this->_ep = $ep;
  592. $responseMsg = $this->sendMessageShoppingApiStyle( $message, $reqHeaders );
  593. if ( $responseMsg )
  594. {
  595. $this->_startTp('Decoding SOAP Message');
  596. $ret = & $this->decodeMessage( $method, $responseMsg, $parseMode );
  597. $this->_stopTp('Decoding SOAP Message');
  598. }
  599. else
  600. {
  601. $ret = & $this->_currentResult;
  602. }
  603. return $ret;
  604. }
  605. function sendMessageShoppingApiStyleNonCurl( $message, $extraXmlHeaders )
  606. {
  607. // this is the part for systems that are not have cURL installed
  608. $transport = new EbatNs_HttpTransport();
  609. if (is_array($extraXmlHeaders))
  610. $reqHeaders = array_merge((array)$reqHeaders, $extraXmlHeaders);
  611. $responseRaw = $transport->Post($this->_ep, $message, $reqHeaders);
  612. if (!$responseRaw)
  613. {
  614. $this->_currentResult = new EbatNs_ResponseError();
  615. $this->_currentResult->raise( 'transport error (none curl) ', 90000 + 1, EBAT_SEVERITY_ERROR );
  616. return null;
  617. }
  618. else
  619. {
  620. if (isset($responseRaw['errors']))
  621. {
  622. $this->_currentResult = new EbatNs_ResponseError();
  623. $this->_currentResult->raise( 'transport error (none curl) ' . $responseRaw['errors'], 90000 + 2, EBAT_SEVERITY_ERROR );
  624. return null;
  625. }
  626. $responseBody = $responseRaw['data'];
  627. if ($responseBody)
  628. $this->logXml( $responseBody, 'Response' );
  629. else
  630. $this->logXml( $responseRaw, 'ResponseRaw' );
  631. return $responseBody;
  632. }
  633. }
  634. function sendMessageShoppingApiStyle( $message, $extraXmlHeaders )
  635. {
  636. $this->_currentResult = null;
  637. $this->log( $this->_ep, 'RequestUrl' );
  638. $this->logXml( $message, 'Request' );
  639. $timeout = $this->_transportOptions['HTTP_TIMEOUT'];
  640. if (!$timeout || $timeout <= 0)
  641. $timeout = 300;
  642. // if we have a special HttpTransport-class defined use it !
  643. if (class_exists('EbatNs_HttpTransport'))
  644. return $this->sendMessageShoppingApiStyleNonCurl($message, $extraXmlHeaders);
  645. // continue with curl support !
  646. $ch = curl_init();
  647. $reqHeaders[] = 'Content-Type: text/xml;charset=utf-8';
  648. if ($this->_transportOptions['HTTP_COMPRESS'])
  649. {
  650. $reqHeaders[] = 'Accept-Encoding: gzip, deflate';
  651. curl_setopt( $ch, CURLOPT_ENCODING, "gzip");
  652. curl_setopt( $ch, CURLOPT_ENCODING, "deflate");
  653. }
  654. if (is_array($extraXmlHeaders))
  655. $reqHeaders = array_merge((array)$reqHeaders, $extraXmlHeaders);
  656. ob_start();
  657. print_r($reqHeaders);
  658. $this->log(ob_get_clean(), 'Request headers');
  659. curl_setopt( $ch, CURLOPT_URL, $this->_ep );
  660. // curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0);
  661. // curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 0);
  662. curl_setopt( $ch, CURLOPT_HTTPHEADER, $reqHeaders );
  663. curl_setopt( $ch, CURLOPT_USERAGENT, 'ebatns;shapi;1.0' );
  664. curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
  665. curl_setopt( $ch, CURLOPT_POST, 1 );
  666. curl_setopt( $ch, CURLOPT_POSTFIELDS, $message );
  667. curl_setopt( $ch, CURLOPT_FAILONERROR, 0 );
  668. curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 );
  669. curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
  670. curl_setopt( $ch, CURLOPT_HEADER, 1 );
  671. curl_setopt( $ch, CURLOPT_HTTP_VERSION, 1 );
  672. // added support for multi-threaded clients
  673. if (isset($this->_transportOptions['HTTP_CURL_MULTITHREADED']))
  674. {
  675. curl_setopt( $ch, CURLOPT_DNS_USE_GLOBAL_CACHE, 0 );
  676. }
  677. $responseRaw = curl_exec( $ch );
  678. if ( !$responseRaw )
  679. {
  680. $this->_currentResult = new EbatNs_ResponseError();
  681. $this->_currentResult->raise( 'curl_error ' . curl_errno( $ch ) . ' ' . curl_error( $ch ), 80000 + 1, EBAT_SEVERITY_ERROR );
  682. curl_close( $ch );
  683. return null;
  684. }
  685. else
  686. {
  687. curl_close( $ch );
  688. $responseBody = null;
  689. if ( preg_match( "/^(.*?)\r?\n\r?\n(.*)/s", $responseRaw, $match ) )
  690. {
  691. $responseBody = $match[2];
  692. $headerLines = split( "\r?\n", $match[1] );
  693. foreach ( $headerLines as $line )
  694. {
  695. if ( strpos( $line, ':' ) === false )
  696. {
  697. $responseHeaders[0] = $line;
  698. continue;
  699. }
  700. list( $key, $value ) = split( ':', $line );
  701. $responseHeaders[strtolower( $key )] = trim( $value );
  702. }
  703. }
  704. if ($responseBody)
  705. $this->logXml( $responseBody, 'Response' );
  706. else
  707. $this->logXml( $responseRaw, 'ResponseRaw' );
  708. }
  709. return $responseBody;
  710. }
  711. function callXmlStyle( $method, $request, $parseMode = EBATNS_PARSEMODE_CALL )
  712. {
  713. // Inject the Credentials into the request here !
  714. $request->_elements['RequesterCredentials'] =
  715. array(
  716. 'required' => false,
  717. 'type' => 'EbatNs_RequesterCredentialType',
  718. 'nsURI' => 'urn:ebay:apis:eBLBaseComponents',
  719. 'array' => false,
  720. 'cardinality' => '0..1');
  721. $reqCred = new EbatNs_RequesterCredentialType();
  722. if ( $this->_session->getTokenMode() == 0 )
  723. {
  724. $cred = new UserIdPasswordType();
  725. $cred->Username = $this->_session->getRequestUser();
  726. $cred->Password = $this->_session->getRequestPassword();
  727. $reqCred->Credentials = $cred;
  728. }
  729. if ( $this->_session->getTokenMode() == 1 )
  730. {
  731. $this->_session->ReadTokenFile();
  732. $reqCred->setEBayAuthToken($this->_session->getRequestToken());
  733. }
  734. $request->RequesterCredentials = $reqCred;
  735. // we support only Sandbox and Production here !
  736. if ($this->_session->getAppMode() == 1)
  737. $ep = "https://api.sandbox.ebay.com/ws/api.dll";
  738. else
  739. $ep = 'https://api.ebay.com/ws/api.dll';
  740. // place all data into theirs header
  741. $reqHeaders[] = 'X-EBAY-API-COMPATIBILITY-LEVEL: ' . $this->getVersion();
  742. $reqHeaders[] = 'X-EBAY-API-DEV-NAME: ' . $this->_session->getDevId();
  743. $reqHeaders[] = 'X-EBAY-API-APP-NAME: ' . $this->_session->getAppId();
  744. $reqHeaders[] = 'X-EBAY-API-CERT-NAME: ' . $this->_session->getCertId();
  745. $reqHeaders[] = 'X-EBAY-API-CALL-NAME: ' . $method;
  746. $reqHeaders[] = 'X-EBAY-API-SITEID: ' . $this->_session->getSiteId();
  747. $multiPartData = null;
  748. if ($method == 'UploadSiteHostedPictures')
  749. {
  750. // assuming to have the picture-binary data
  751. // in $request->PictureData
  752. $multiPartData = $request->getPictureData();
  753. $request->setPictureData(null);
  754. }
  755. $body = $this->encodeMessageXmlStyle( $method, $request );
  756. $message = '<?xml version="1.0" encoding="utf-8"?>' . "\n";
  757. $message .= $body;
  758. $this->_ep = $ep;
  759. $responseMsg = $this->sendMessageXmlStyle( $message, $reqHeaders, $multiPartData );
  760. if ( $responseMsg )
  761. {
  762. $this->_startTp('Decoding SOAP Message');
  763. $ret = & $this->decodeMessage( $method, $responseMsg, $parseMode );
  764. $this->_stopTp('Decoding SOAP Message');
  765. }
  766. else
  767. {
  768. $ret = & $this->_currentResult;
  769. }
  770. return $ret;
  771. }
  772. // sendMessage in XmlStyle,
  773. // the only difference is the extra headers we use here
  774. function sendMessageXmlStyle( $message, $extraXmlHeaders, $multiPartImageData = null )
  775. {
  776. $this->_currentResult = null;
  777. $this->log( $this->_ep, 'RequestUrl' );
  778. $this->logXml( $message, 'Request' );
  779. $timeout = $this->_transportOptions['HTTP_TIMEOUT'];
  780. if (!$timeout || $timeout <= 0)
  781. $timeout = 300;
  782. $ch = curl_init();
  783. if ($multiPartImageData !== null)
  784. {
  785. $boundary = "MIME_boundary";
  786. $CRLF = "\r\n";
  787. $mp_message .= "--" . $boundary . $CRLF;
  788. $mp_message .= 'Content-Disposition: form-data; name="XML Payload"' . $CRLF;
  789. $mp_message .= 'Content-Type: text/xml;charset=utf-8' . $CRLF . $CRLF;
  790. $mp_message .= $message;
  791. $mp_message .= $CRLF;
  792. $mp_message .= "--" . $boundary . $CRLF;
  793. $mp_message .= 'Content-Disposition: form-data; name="dumy"; filename="dummy"' . $CRLF;
  794. $mp_message .= "Content-Transfer-Encoding: binary" . $CRLF;
  795. $mp_message .= "Content-Type: application/octet-stream" . $CRLF . $CRLF;
  796. $mp_message .= $multiPartImageData;
  797. $mp_message .= $CRLF;
  798. $mp_message .= "--" . $boundary . "--" . $CRLF;
  799. $message = $mp_message;
  800. $reqHeaders[] = 'Content-Type: multipart/form-data; boundary=' . $boundary;
  801. $reqHeaders[] = 'Content-Length: ' . strlen($message);
  802. }
  803. else
  804. {
  805. $reqHeaders[] = 'Content-Type: text/xml;charset=utf-8';
  806. }
  807. if ($this->_transportOptions['HTTP_COMPRESS'])
  808. {
  809. $reqHeaders[] = 'Accept-Encoding: gzip, deflate';
  810. curl_setopt( $ch, CURLOPT_ENCODING, "gzip");
  811. curl_setopt( $ch, CURLOPT_ENCODING, "deflate");
  812. }
  813. if (is_array($extraXmlHeaders))
  814. $reqHeaders = array_merge((array)$reqHeaders, $extraXmlHeaders);
  815. curl_setopt( $ch, CURLOPT_URL, $this->_ep );
  816. curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0);
  817. curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 0);
  818. curl_setopt( $ch, CURLOPT_HTTPHEADER, $reqHeaders );
  819. curl_setopt( $ch, CURLOPT_USERAGENT, 'ebatns;xmlstyle;1.0' );
  820. curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
  821. curl_setopt( $ch, CURLOPT_POST, 1 );
  822. curl_setopt( $ch, CURLOPT_POSTFIELDS, $message );
  823. curl_setopt( $ch, CURLOPT_FAILONERROR, 0 );
  824. curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 );
  825. curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
  826. curl_setopt( $ch, CURLOPT_HEADER, 1 );
  827. curl_setopt( $ch, CURLOPT_HTTP_VERSION, 1 );
  828. // added support for multi-threaded clients
  829. if (isset($this->_transportOptions['HTTP_CURL_MULTITHREADED']))
  830. {
  831. curl_setopt( $ch, CURLOPT_DNS_USE_GLOBAL_CACHE, 0 );
  832. }
  833. $responseRaw = curl_exec( $ch );
  834. if ( !$responseRaw )
  835. {
  836. $this->_currentResult = new EbatNs_ResponseError();
  837. $this->_currentResult->raise( 'curl_error ' . curl_errno( $ch ) . ' ' . curl_error( $ch ), 80000 + 1, EBAT_SEVERITY_ERROR );
  838. curl_close( $ch );
  839. return null;
  840. }
  841. else
  842. {
  843. curl_close( $ch );
  844. $responseRaw = str_replace
  845. (
  846. array
  847. (
  848. "HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK\r\n",
  849. "HTTP/1.1 100 Continue\n\nHTTP/1.1 200 OK\n"
  850. ),
  851. array
  852. (
  853. "HTTP/1.1 200 OK\r\n",
  854. "HTTP/1.1 200 OK\n"
  855. ),
  856. $responseRaw
  857. );
  858. $responseBody = null;
  859. if ( preg_match( "/^(.*?)\r?\n\r?\n(.*)/s", $responseRaw, $match ) )
  860. {
  861. $responseBody = $match[2];
  862. $headerLines = split( "\r?\n", $match[1] );
  863. foreach ( $headerLines as $line )
  864. {
  865. if ( strpos( $line, ':' ) === false )
  866. {
  867. $responseHeaders[0] = $line;
  868. continue;
  869. }
  870. list( $key, $value ) = split( ':', $line );
  871. $responseHeaders[strtolower( $key )] = trim( $value );
  872. }
  873. }
  874. if ($responseBody)
  875. $this->logXml( $responseBody, 'Response' );
  876. else
  877. $this->logXml( $responseRaw, 'ResponseRaw' );
  878. }
  879. return $responseBody;
  880. }
  881. function encodeMessageXmlStyle( $method, $request )
  882. {
  883. return $request->serialize( $method . 'Request', $request, array('xmlns' => 'urn:ebay:apis:eBLBaseComponents'), true, null, $this->_dataConverter );
  884. }
  885. public function hasDataConverter()
  886. {
  887. return ($this->_dataConverter !== null);
  888. }
  889. public function getDataConverter()
  890. {
  891. return $this->_dataConverter;
  892. }
  893. public function hasCallbacks()
  894. {
  895. return $this->_hasCallbacks;
  896. }
  897. /**
  898. * Reformats the error data in the response to a printable text or html output
  899. *
  900. * @param AbstractResponseType $response A response returned by any of the eBay API calls
  901. * @param Boolean $asHtml Flag to pass the error in htmlentities for better formating
  902. * @param Boolean $addSlashes Uses addslashes to make the error-string directly insertable to a DB
  903. * @return string
  904. */
  905. public function getErrorsToString($response, $asHtml = false, $addSlashes = true)
  906. {
  907. $errmsg = '';
  908. if (count($response->getErrors()))
  909. foreach ($response->getErrors() as $errorEle)
  910. $errmsg .= '#' . $errorEle->getErrorCode() . ' : ' . ($asHtml ? htmlentities($errorEle->getLongMessage()) : $errorEle->getLongMessage()) . ($asHtml ? "<br>" : "\r\n");
  911. if ($addSlashes)
  912. return addslashes($errmsg);
  913. else
  914. return $errmsg;
  915. }
  916. public function addSelectorModel($callName, $selectorModel, $active)
  917. {
  918. $this->_selectorModels[$selectorModel->getName()][$callName] = $selectorModel;
  919. if ($active)
  920. {
  921. $this->setActiveSelectorModel($selectorModel->getName());
  922. }
  923. }
  924. public function setActiveSelectorModel($selectorName)
  925. {
  926. $this->_activeSelectorModel = $selectorName;
  927. foreach($this->_selectorModels as $selectorModel)
  928. {
  929. foreach($selectorModel as $selectorModelCall)
  930. {
  931. if ($selectorModelCall->getName() == $selectorName)
  932. $selectorModelCall->setActive(true);
  933. else
  934. $selectorModelCall->setActive(false);
  935. }
  936. }
  937. }
  938. public function getSession()
  939. {
  940. return $this->_session;
  941. }
  942. }
  943. ?>