TopClient.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. class TopClient {
  3. public $appkey;
  4. public $secretKey;
  5. public $gatewayUrl = "http://gw.api.taobao.com/router/rest";
  6. public $format = "xml";
  7. public $connectTimeout;
  8. public $readTimeout;
  9. /** 是否打开入参check**/
  10. public $checkRequest = true;
  11. protected $signMethod = "md5";
  12. protected $apiVersion = "2.0";
  13. protected $sdkVersion = "top-sdk-php-20151012";
  14. public function __construct($appkey = "", $secretKey = "") {
  15. $this->appkey = $appkey;
  16. $this->secretKey = $secretKey;
  17. }
  18. protected function generateSign($params) {
  19. ksort($params);
  20. $stringToBeSigned = $this->secretKey;
  21. foreach ($params as $k => $v) {
  22. if ("@" != substr($v, 0, 1)) {
  23. $stringToBeSigned .= "$k$v";
  24. }
  25. }
  26. unset($k, $v);
  27. $stringToBeSigned .= $this->secretKey;
  28. return strtoupper(md5($stringToBeSigned));
  29. }
  30. public function curl($url, $postFields = null) {
  31. $ch = curl_init();
  32. curl_setopt($ch, CURLOPT_URL, $url);
  33. curl_setopt($ch, CURLOPT_FAILONERROR, false);
  34. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  35. if ($this->readTimeout) {
  36. curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
  37. }
  38. if ($this->connectTimeout) {
  39. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
  40. }
  41. curl_setopt($ch, CURLOPT_USERAGENT, "top-sdk-php");
  42. //https 请求
  43. if (strlen($url) > 5 && strtolower(substr($url, 0, 5)) == "https") {
  44. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  45. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  46. }
  47. if (is_array($postFields) && 0 < count($postFields)) {
  48. $postBodyString = "";
  49. $postMultipart = false;
  50. foreach ($postFields as $k => $v) {
  51. if ("@" != substr($v, 0, 1))//判断是不是文件上传
  52. {
  53. $postBodyString .= "$k=".urlencode($v)."&";
  54. } else//文件上传用multipart/form-data,否则用www-form-urlencoded
  55. {
  56. $postMultipart = true;
  57. if (class_exists('\CURLFile')) {
  58. $postFields[$k] = new \CURLFile(substr($v, 1));
  59. }
  60. }
  61. }
  62. unset($k, $v);
  63. curl_setopt($ch, CURLOPT_POST, true);
  64. if ($postMultipart) {
  65. if (class_exists('\CURLFile')) {
  66. curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
  67. } else {
  68. if (defined('CURLOPT_SAFE_UPLOAD')) {
  69. curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
  70. }
  71. }
  72. curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
  73. } else {
  74. $header = array("content-type: application/x-www-form-urlencoded; charset=UTF-8");
  75. curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  76. curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString, 0, -1));
  77. }
  78. }
  79. $reponse = curl_exec($ch);
  80. if (curl_errno($ch)) {
  81. throw new Exception(curl_error($ch), 0);
  82. } else {
  83. $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  84. if (200 !== $httpStatusCode) {
  85. throw new Exception($reponse, $httpStatusCode);
  86. }
  87. }
  88. curl_close($ch);
  89. return $reponse;
  90. }
  91. protected function logCommunicationError($apiName, $requestUrl, $errorCode, $responseTxt) {
  92. $localIp = isset($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : "CLI";
  93. $logger = new TopLogger;
  94. $logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/').'/'."logs/top_comm_err_".$this->appkey."_".date(
  95. "Y-m-d"
  96. ).".log";
  97. $logger->conf["separator"] = "^_^";
  98. $logData = array(
  99. date("Y-m-d H:i:s"),
  100. $apiName,
  101. $this->appkey,
  102. $localIp,
  103. PHP_OS,
  104. $this->sdkVersion,
  105. $requestUrl,
  106. $errorCode,
  107. str_replace("\n", "", $responseTxt)
  108. );
  109. $logger->log($logData);
  110. }
  111. public function execute($request, $session = null, $bestUrl = null) {
  112. $result = new ResultSet();
  113. if ($this->checkRequest) {
  114. try {
  115. $request->check();
  116. } catch (Exception $e) {
  117. $result->code = $e->getCode();
  118. $result->msg = $e->getMessage();
  119. return $result;
  120. }
  121. }
  122. //组装系统参数
  123. $sysParams["app_key"] = $this->appkey;
  124. $sysParams["v"] = $this->apiVersion;
  125. $sysParams["format"] = $this->format;
  126. $sysParams["sign_method"] = $this->signMethod;
  127. $sysParams["method"] = $request->getApiMethodName();
  128. $sysParams["timestamp"] = date("Y-m-d H:i:s");
  129. if (null != $session) {
  130. $sysParams["session"] = $session;
  131. }
  132. //获取业务参数
  133. $apiParams = $request->getApiParas();
  134. //系统参数放入GET请求串
  135. if ($bestUrl) {
  136. $requestUrl = $bestUrl."?";
  137. $sysParams["partner_id"] = $this->getClusterTag();
  138. } else {
  139. $requestUrl = $this->gatewayUrl."?";
  140. $sysParams["partner_id"] = $this->sdkVersion;
  141. }
  142. //签名
  143. $sysParams["sign"] = $this->generateSign(array_merge($apiParams, $sysParams));
  144. foreach ($sysParams as $sysParamKey => $sysParamValue) {
  145. // if(strcmp($sysParamKey,"timestamp") != 0)
  146. $requestUrl .= "$sysParamKey=".urlencode($sysParamValue)."&";
  147. }
  148. // $requestUrl .= "timestamp=" . urlencode($sysParams["timestamp"]) . "&";
  149. $requestUrl = substr($requestUrl, 0, -1);
  150. //发起HTTP请求
  151. try {
  152. $resp = $this->curl($requestUrl, $apiParams);
  153. } catch (Exception $e) {
  154. $this->logCommunicationError(
  155. $sysParams["method"], $requestUrl, "HTTP_ERROR_".$e->getCode(), $e->getMessage()
  156. );
  157. $result->code = $e->getCode();
  158. $result->msg = $e->getMessage();
  159. return $result;
  160. }
  161. //解析TOP返回结果
  162. $respWellFormed = false;
  163. if ("json" == $this->format) {
  164. $respObject = json_decode($resp);
  165. if (null !== $respObject) {
  166. $respWellFormed = true;
  167. foreach ($respObject as $propKey => $propValue) {
  168. $respObject = $propValue;
  169. }
  170. }
  171. } else if ("xml" == $this->format) {
  172. $respObject = @simplexml_load_string($resp);
  173. if (false !== $respObject) {
  174. $respWellFormed = true;
  175. }
  176. }
  177. //返回的HTTP文本不是标准JSON或者XML,记下错误日志
  178. if (false === $respWellFormed) {
  179. $this->logCommunicationError($sysParams["method"], $requestUrl, "HTTP_RESPONSE_NOT_WELL_FORMED", $resp);
  180. $result->code = 0;
  181. $result->msg = "HTTP_RESPONSE_NOT_WELL_FORMED";
  182. return $result;
  183. }
  184. //如果TOP返回了错误码,记录到业务错误日志中
  185. if (isset($respObject->code)) {
  186. $logger = new TopLogger;
  187. $logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/').'/'."logs/top_biz_err_".$this->appkey."_".date(
  188. "Y-m-d"
  189. ).".log";
  190. $logger->log(
  191. array(
  192. date("Y-m-d H:i:s"),
  193. $resp
  194. )
  195. );
  196. }
  197. return $respObject;
  198. }
  199. public function exec($paramsArray) {
  200. if (!isset($paramsArray["method"])) {
  201. trigger_error("No api name passed");
  202. }
  203. $inflector = new LtInflector;
  204. $inflector->conf["separator"] = ".";
  205. $requestClassName = ucfirst($inflector->camelize(substr($paramsArray["method"], 7)))."Request";
  206. if (!class_exists($requestClassName)) {
  207. trigger_error("No such api: ".$paramsArray["method"]);
  208. }
  209. $session = isset($paramsArray["session"]) ? $paramsArray["session"] : null;
  210. $req = new $requestClassName;
  211. foreach ($paramsArray as $paraKey => $paraValue) {
  212. $inflector->conf["separator"] = "_";
  213. $setterMethodName = $inflector->camelize($paraKey);
  214. $inflector->conf["separator"] = ".";
  215. $setterMethodName = "set".$inflector->camelize($setterMethodName);
  216. if (method_exists($req, $setterMethodName)) {
  217. $req->$setterMethodName($paraValue);
  218. }
  219. }
  220. return $this->execute($req, $session);
  221. }
  222. private function getClusterTag() {
  223. return substr($this->sdkVersion, 0, 11)."-cluster".substr($this->sdkVersion, 11);
  224. }
  225. }