TopClient.php 7.2 KB

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