AliyunClient.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. <?php
  2. class AliyunClient
  3. {
  4. public $accessKeyId;
  5. public $accessKeySecret;
  6. public $serverUrl = "http://ecs.aliyuncs.com/";
  7. public $format = "json";
  8. public $connectTimeout = 3000;//3秒
  9. public $readTimeout = 80000;//80秒
  10. /** 是否打开入参check**/
  11. public $checkRequest = true;
  12. protected $signatureMethod = "HMAC-SHA1";
  13. protected $signatureVersion = "1.0";
  14. protected $dateTimeFormat = 'Y-m-d\TH:i:s\Z'; // ISO8601规范
  15. protected $sdkVersion = "1.0";
  16. public function execute($request)
  17. {
  18. if($this->checkRequest) {
  19. try {
  20. $request->check();
  21. } catch (Exception $e) {
  22. $result->code = $e->getCode();
  23. $result->message = $e->getMessage();
  24. return $result;
  25. }
  26. }
  27. //获取业务参数
  28. $apiParams = $request->getApiParas();
  29. //组装系统参数
  30. $apiParams["AccessKeyId"] = $this->accessKeyId;
  31. $apiParams["Format"] = $this->format;//
  32. $apiParams["SignatureMethod"] = $this->signatureMethod;
  33. $apiParams["SignatureVersion"] = $this->signatureVersion;
  34. $apiParams["SignatureNonce"] = uniqid();
  35. date_default_timezone_set("GMT");
  36. $apiParams["TimeStamp"] = date($this->dateTimeFormat);
  37. $apiParams["partner_id"] = $this->sdkVersion;
  38. $apiNameArray = split("\.", $request->getApiMethodName());
  39. $apiParams["Action"] = $apiNameArray[3];
  40. $apiParams["Version"] = $apiNameArray[4];
  41. //签名
  42. $apiParams["Signature"] = $this->computeSignature($apiParams, $this->accessKeySecret);
  43. //系统参数放入GET请求串
  44. $requestUrl = rtrim($this->serverUrl,"/") . "/?";
  45. foreach ($apiParams as $apiParamKey => $apiParamValue)
  46. {
  47. $requestUrl .= "$apiParamKey=" . urlencode($apiParamValue) . "&";
  48. }
  49. $requestUrl = substr($requestUrl, 0, -1);
  50. //发起HTTP请求
  51. try
  52. {
  53. $resp = $this->curl($requestUrl, null);
  54. }
  55. catch (Exception $e)
  56. {
  57. $this->logCommunicationError($apiParams["Action"],$requestUrl,"HTTP_ERROR_" . $e->getCode(),$e->getMessage());
  58. if ("json" == $this->format)
  59. {
  60. return json_decode($e->getMessage());
  61. }
  62. else if("xml" == $this->format)
  63. {
  64. return @simplexml_load_string($e->getMessage());
  65. }
  66. }
  67. //解析API返回结果
  68. $respWellFormed = false;
  69. if ("json" == $this->format)
  70. {
  71. $respObject = json_decode($resp);
  72. if (null !== $respObject)
  73. {
  74. $respWellFormed = true;
  75. }
  76. }
  77. else if("xml" == $this->format)
  78. {
  79. $respObject = @simplexml_load_string($resp);
  80. if (false !== $respObject)
  81. {
  82. $respWellFormed = true;
  83. }
  84. }
  85. //返回的HTTP文本不是标准JSON或者XML,记下错误日志
  86. if (false === $respWellFormed)
  87. {
  88. $this->logCommunicationError($apiParams["Action"],$requestUrl,"HTTP_RESPONSE_NOT_WELL_FORMED",$resp);
  89. $result->code = 0;
  90. $result->message = "HTTP_RESPONSE_NOT_WELL_FORMED";
  91. return $result;
  92. }
  93. //如果TOP返回了错误码,记录到业务错误日志中
  94. if (isset($respObject->code))
  95. {
  96. $logger = new LtLogger;
  97. $logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/') . '/' . "logs/top_biz_err_" . $this->appkey . "_" . date("Y-m-d") . ".log";
  98. $logger->log(array(
  99. date("Y-m-d H:i:s"),
  100. $resp
  101. ));
  102. }
  103. return $respObject;
  104. }
  105. public function exec($paramsArray)
  106. {
  107. if (!isset($paramsArray["Action"]))
  108. {
  109. trigger_error("No api name passed");
  110. }
  111. $inflector = new LtInflector;
  112. $inflector->conf["separator"] = ".";
  113. $requestClassName = ucfirst($inflector->camelize(substr($paramsArray["Action"], 7))) . "Request";
  114. if (!class_exists($requestClassName))
  115. {
  116. trigger_error("No such api: " . $paramsArray["Action"]);
  117. }
  118. $req = new $requestClassName;
  119. foreach($paramsArray as $paraKey => $paraValue)
  120. {
  121. $inflector->conf["separator"] = "_";
  122. $setterMethodName = $inflector->camelize($paraKey);
  123. $inflector->conf["separator"] = ".";
  124. $setterMethodName = "set" . $inflector->camelize($setterMethodName);
  125. if (method_exists($req, $setterMethodName))
  126. {
  127. $req->$setterMethodName($paraValue);
  128. }
  129. }
  130. return $this->execute($req, $session);
  131. }
  132. protected function percentEncode($str)
  133. {
  134. // 使用urlencode编码后,将"+","*","%7E"做替换即满足 API规定的编码规范
  135. $res = urlencode($str);
  136. $res = preg_replace('/\+/', '%20', $res);
  137. $res = preg_replace('/\*/', '%2A', $res);
  138. $res = preg_replace('/%7E/', '~', $res);
  139. return $res;
  140. }
  141. protected function computeSignature($parameters, $accessKeySecret)
  142. {
  143. // 将参数Key按字典顺序排序
  144. ksort($parameters);
  145. // 生成规范化请求字符串
  146. $canonicalizedQueryString = '';
  147. foreach($parameters as $key => $value)
  148. {
  149. $canonicalizedQueryString .= '&' . $this->percentEncode($key)
  150. . '=' . $this->percentEncode($value);
  151. }
  152. // 生成用于计算签名的字符串 stringToSign
  153. $stringToSign = 'GET&%2F&' . $this->percentencode(substr($canonicalizedQueryString, 1));
  154. // 计算签名,注意accessKeySecret后面要加上字符'&'
  155. $signature = base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret . '&', true));
  156. return $signature;
  157. }
  158. public function curl($url, $postFields = null)
  159. {
  160. $ch = curl_init();
  161. curl_setopt($ch, CURLOPT_URL, $url);
  162. curl_setopt($ch, CURLOPT_FAILONERROR, false);
  163. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  164. if ($this->readTimeout) {
  165. curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
  166. }
  167. if ($this->connectTimeout) {
  168. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
  169. }
  170. //https 请求
  171. if(strlen($url) > 5 && strtolower(substr($url,0,5)) == "https" ) {
  172. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  173. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  174. }
  175. if (is_array($postFields) && 0 < count($postFields))
  176. {
  177. $postBodyString = "";
  178. $postMultipart = false;
  179. foreach ($postFields as $k => $v)
  180. {
  181. if("@" != substr($v, 0, 1))//判断是不是文件上传
  182. {
  183. $postBodyString .= "$k=" . urlencode($v) . "&";
  184. }
  185. else//文件上传用multipart/form-data,否则用www-form-urlencoded
  186. {
  187. $postMultipart = true;
  188. }
  189. }
  190. unset($k, $v);
  191. curl_setopt($ch, CURLOPT_POST, true);
  192. if ($postMultipart)
  193. {
  194. curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
  195. }
  196. else
  197. {
  198. curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString,0,-1));
  199. }
  200. }
  201. $reponse = curl_exec($ch);
  202. if (curl_errno($ch))
  203. {
  204. throw new Exception(curl_error($ch),0);
  205. }
  206. curl_close($ch);
  207. return $reponse;
  208. }
  209. protected function logCommunicationError($apiName, $requestUrl, $errorCode, $responseTxt)
  210. {
  211. $localIp = isset($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : "CLI";
  212. $logger = new LtLogger;
  213. $logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/') . '/' . "logs/top_comm_err_" . $this->accessKeyId . "_" . date("Y-m-d") . ".log";
  214. $logger->conf["separator"] = "^_^";
  215. $logData = array(
  216. date("Y-m-d H:i:s"),
  217. $apiName,
  218. $this->accessKeyId,
  219. $localIp,
  220. PHP_OS,
  221. $this->sdkVersion,
  222. $requestUrl,
  223. $errorCode,
  224. str_replace("\n","",$responseTxt)
  225. );
  226. $logger->log($logData);
  227. }
  228. }