QimenCloudClient::getClusterTag()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
class QimenCloudClient
3
{
4
	public $appkey;
5
6
	public $secretKey;
7
	
8
	public $targetAppkey = "";
9
10
	public $gatewayUrl = null;
11
12
	public $format = "xml";
13
14
	public $connectTimeout;
15
16
	public $readTimeout;
17
18
	/** 是否打开入参check**/
19
	public $checkRequest = true;
20
21
	protected $signMethod = "md5";
22
23
	protected $apiVersion = "2.0";
24
25
	protected $sdkVersion = "top-sdk-php-20151012";
26
27
	public function getAppkey()
28
	{
29
		return $this->appkey;
30
	}
31
32
	public function __construct($appkey = "",$secretKey = ""){
33
		$this->appkey = $appkey;
34
		$this->secretKey = $secretKey ;
35
	}
36
37
	protected function generateSign($params)
38
	{
39
		ksort($params);
40
41
		$stringToBeSigned = $this->secretKey;
42
		foreach ($params as $k => $v)
43
		{
44
			if(!is_array($v) && "@" != substr($v, 0, 1))
45
			{
46
				$stringToBeSigned .= "$k$v";
47
			}
48
		}
49
		unset($k, $v);
50
		$stringToBeSigned .= $this->secretKey;
51
52
		return strtoupper(md5($stringToBeSigned));
53
	}
54
55
	public function curl($url, $postFields = null)
56
	{
57
		$ch = curl_init();
58
		curl_setopt($ch, CURLOPT_URL, $url);
59
		curl_setopt($ch, CURLOPT_FAILONERROR, false);
60
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
61
		if ($this->readTimeout) {
62
			curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
63
		}
64
		if ($this->connectTimeout) {
65
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
66
		}
67
		curl_setopt ( $ch, CURLOPT_USERAGENT, "top-sdk-php" );
68
		//https 请求
69
		if(strlen($url) > 5 && strtolower(substr($url,0,5)) == "https" ) {
70
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
71
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
72
		}
73
74
		if (is_array($postFields) && 0 < count($postFields))
75
		{
76
			$postBodyString = "";
77
			$postMultipart = false;
78
			foreach ($postFields as $k => $v)
79
			{
80
				if("@" != substr($v, 0, 1))//判断是不是文件上传
81
				{
82
					$postBodyString .= "$k=" . urlencode($v) . "&"; 
83
				}
84
				else//文件上传用multipart/form-data,否则用www-form-urlencoded
85
				{
86
					$postMultipart = true;
87
					if(class_exists('\CURLFile')){
88
						$postFields[$k] = new \CURLFile(substr($v, 1));
89
					}
90
				}
91
			}
92
			unset($k, $v);
93
			curl_setopt($ch, CURLOPT_POST, true);
94
			if ($postMultipart)
95
			{
96
				if (class_exists('\CURLFile')) {
97
				    curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
0 ignored issues
show
introduced by
The constant CURLOPT_SAFE_UPLOAD has been deprecated: 7.0 Use <b>CURLFile</b> for uploads instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

97
				    curl_setopt($ch, /** @scrutinizer ignore-deprecated */ CURLOPT_SAFE_UPLOAD, true);
Loading history...
98
				} else {
99
				    if (defined('CURLOPT_SAFE_UPLOAD')) {
100
				        curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
0 ignored issues
show
introduced by
The constant CURLOPT_SAFE_UPLOAD has been deprecated: 7.0 Use <b>CURLFile</b> for uploads instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

100
				        curl_setopt($ch, /** @scrutinizer ignore-deprecated */ CURLOPT_SAFE_UPLOAD, false);
Loading history...
101
				    }
102
				}
103
				curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
104
			}
105
			else
106
			{
107
				$header = array("content-type: application/x-www-form-urlencoded; charset=UTF-8");
108
				curl_setopt($ch,CURLOPT_HTTPHEADER,$header);
109
				curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString,0,-1));
110
			}
111
		}
112
		$reponse = curl_exec($ch);
113
		
114
		if (curl_errno($ch))
115
		{
116
			throw new Exception(curl_error($ch),0);
117
		}
118
		else
119
		{
120
			$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
121
			if (200 !== $httpStatusCode)
122
			{
123
				throw new Exception($reponse,$httpStatusCode);
0 ignored issues
show
Bug introduced by
It seems like $reponse can also be of type true; however, parameter $message of Exception::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

123
				throw new Exception(/** @scrutinizer ignore-type */ $reponse,$httpStatusCode);
Loading history...
124
			}
125
		}
126
		curl_close($ch);
127
		return $reponse;
128
	}
129
	public function curl_with_memory_file($url, $postFields = null, $fileFields = null)
130
	{
131
		$ch = curl_init();
132
		curl_setopt($ch, CURLOPT_URL, $url);
133
		curl_setopt($ch, CURLOPT_FAILONERROR, false);
134
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
135
		if ($this->readTimeout) {
136
			curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
137
		}
138
		if ($this->connectTimeout) {
139
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
140
		}
141
		curl_setopt ( $ch, CURLOPT_USERAGENT, "top-sdk-php" );
142
		//https 请求
143
		if(strlen($url) > 5 && strtolower(substr($url,0,5)) == "https" ) {
144
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
145
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
146
		}
147
		//生成分隔符
148
		$delimiter = '-------------' . uniqid();
149
		//先将post的普通数据生成主体字符串
150
		$data = '';
151
		if($postFields != null){
152
			foreach ($postFields as $name => $content) {
153
			    $data .= "--" . $delimiter . "\r\n";
154
			    $data .= 'Content-Disposition: form-data; name="' . $name . '"';
155
			    //multipart/form-data 不需要urlencode,参见 http:stackoverflow.com/questions/6603928/should-i-url-encode-post-data
156
			    $data .= "\r\n\r\n" . $content . "\r\n";
157
			}
158
			unset($name,$content);
159
		}
160
161
		//将上传的文件生成主体字符串
162
		if($fileFields != null){
163
			foreach ($fileFields as $name => $file) {
164
			    $data .= "--" . $delimiter . "\r\n";
165
			    $data .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $file['name'] . "\" \r\n";
166
			    $data .= 'Content-Type: ' . $file['type'] . "\r\n\r\n";//多了个文档类型
167
168
			    $data .= $file['content'] . "\r\n";
169
			}
170
			unset($name,$file);
171
		}
172
		//主体结束的分隔符
173
		$data .= "--" . $delimiter . "--";
174
175
		curl_setopt($ch, CURLOPT_POST, true);
176
		curl_setopt($ch, CURLOPT_HTTPHEADER , array(
177
		    'Content-Type: multipart/form-data; boundary=' . $delimiter,
178
		    'Content-Length: ' . strlen($data))
179
		); 
180
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
181
		curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
182
183
		$reponse = curl_exec($ch);
184
		unset($data);
185
186
		if (curl_errno($ch))
187
		{
188
			throw new Exception(curl_error($ch),0);
189
		}
190
		else
191
		{
192
			$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
193
			if (200 !== $httpStatusCode)
194
			{
195
				throw new Exception($reponse,$httpStatusCode);
0 ignored issues
show
Bug introduced by
It seems like $reponse can also be of type true; however, parameter $message of Exception::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

195
				throw new Exception(/** @scrutinizer ignore-type */ $reponse,$httpStatusCode);
Loading history...
196
			}
197
		}
198
		curl_close($ch);
199
		return $reponse;
200
	}
201
202
	protected function logCommunicationError($apiName, $requestUrl, $errorCode, $responseTxt)
203
	{
204
		$localIp = isset($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : "CLI";
205
		$logger = new TopLogger;
206
		$logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/') . '/' . "logs/top_comm_err_" . $this->appkey . "_" . date("Y-m-d") . ".log";
207
		$logger->conf["separator"] = "^_^";
208
		$logData = array(
209
		date("Y-m-d H:i:s"),
210
		$apiName,
211
		$this->appkey,
212
		$localIp,
213
		PHP_OS,
214
		$this->sdkVersion,
215
		$requestUrl,
216
		$errorCode,
217
		str_replace("\n","",$responseTxt)
218
		);
219
		$logger->log($logData);
220
	}
221
222
	public function execute($request, $session = null,$bestUrl = null)
223
	{
224
		if($this->gatewayUrl == null) {
225
			throw new Exception("client-check-error:Need Set gatewayUrl.", 40);
226
		}
227
228
		$result =  new ResultSet(); 
229
		if($this->checkRequest) {
230
			try {
231
				$request->check();
232
			} catch (Exception $e) {
233
234
				$result->code = $e->getCode();
235
				$result->msg = $e->getMessage();
236
				return $result;
237
			}
238
		}
239
		//组装系统参数
240
		$sysParams["app_key"] = $this->appkey;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$sysParams was never initialized. Although not strictly required by PHP, it is generally a good practice to add $sysParams = array(); before regardless.
Loading history...
241
		$sysParams["v"] = $this->apiVersion;
242
		$sysParams["format"] = $this->format;
243
		$sysParams["sign_method"] = $this->signMethod;
244
		$sysParams["method"] = $request->getApiMethodName();
245
		$sysParams["timestamp"] = date("Y-m-d H:i:s");
246
		$sysParams["target_app_key"] = $this->targetAppkey;
247
		if (null != $session)
248
		{
249
			$sysParams["session"] = $session;
250
		}
251
		$apiParams = array();
0 ignored issues
show
Unused Code introduced by
The assignment to $apiParams is dead and can be removed.
Loading history...
252
		//获取业务参数
253
		$apiParams = $request->getApiParas();
254
255
256
		//系统参数放入GET请求串
257
		if($bestUrl){
258
			$requestUrl = $bestUrl."?";
259
			$sysParams["partner_id"] = $this->getClusterTag();
260
		}else{
261
			$requestUrl = $this->gatewayUrl."?";
262
			$sysParams["partner_id"] = $this->sdkVersion;
263
		}
264
		//签名
265
		$sysParams["sign"] = $this->generateSign(array_merge($apiParams, $sysParams));
266
267
		foreach ($sysParams as $sysParamKey => $sysParamValue)
268
		{
269
			// if(strcmp($sysParamKey,"timestamp") != 0)
270
			$requestUrl .= "$sysParamKey=" . urlencode($sysParamValue) . "&";
271
		}
272
273
		$fileFields = array();
274
		foreach ($apiParams as $key => $value) {
275
			if(is_array($value) && array_key_exists('type',$value) && array_key_exists('content',$value) ){
276
				$value['name'] = $key;
277
				$fileFields[$key] = $value;
278
				unset($apiParams[$key]);
279
			}
280
		}
281
282
		// $requestUrl .= "timestamp=" . urlencode($sysParams["timestamp"]) . "&";
283
		$requestUrl = substr($requestUrl, 0, -1);
284
285
		//发起HTTP请求
286
		try
287
		{
288
			if(count($fileFields) > 0){
289
				$resp = $this->curl_with_memory_file($requestUrl, $apiParams, $fileFields);
290
			}else{
291
				$resp = $this->curl($requestUrl, $apiParams);
292
			}
293
		}
294
		catch (Exception $e)
295
		{
296
			$this->logCommunicationError($sysParams["method"],$requestUrl,"HTTP_ERROR_" . $e->getCode(),$e->getMessage());
297
			$result->code = $e->getCode();
298
			$result->msg = $e->getMessage();
299
			return $result;
300
		}
301
302
		unset($apiParams);
303
		unset($fileFields);
304
		//解析TOP返回结果
305
		$respWellFormed = false;
306
		if ("json" == $this->format)
307
		{
308
			$respObject = json_decode($resp);
0 ignored issues
show
Bug introduced by
It seems like $resp can also be of type true; however, parameter $json of json_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

308
			$respObject = json_decode(/** @scrutinizer ignore-type */ $resp);
Loading history...
309
			if (null !== $respObject)
310
			{
311
				$respWellFormed = true;
312
				foreach ($respObject as $propKey => $propValue)
313
				{
314
					$respObject = $propValue;
315
				}
316
			}
317
		}
318
		else if("xml" == $this->format)
319
		{
320
			$respObject = @simplexml_load_string($resp);
0 ignored issues
show
Bug introduced by
It seems like $resp can also be of type true; however, parameter $data of simplexml_load_string() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

320
			$respObject = @simplexml_load_string(/** @scrutinizer ignore-type */ $resp);
Loading history...
321
			if (false !== $respObject)
322
			{
323
				$respWellFormed = true;
324
			}
325
		}
326
327
		//返回的HTTP文本不是标准JSON或者XML,记下错误日志
328
		if (false === $respWellFormed)
329
		{
330
			$this->logCommunicationError($sysParams["method"],$requestUrl,"HTTP_RESPONSE_NOT_WELL_FORMED",$resp);
331
			$result->code = 0;
332
			$result->msg = "HTTP_RESPONSE_NOT_WELL_FORMED";
333
			return $result;
334
		}
335
336
		//如果TOP返回了错误码,记录到业务错误日志中
337
		if (isset($respObject->code))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $respObject does not seem to be defined for all execution paths leading up to this point.
Loading history...
338
		{
339
			$logger = new TopLogger;
340
			$logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/') . '/' . "logs/top_biz_err_" . $this->appkey . "_" . date("Y-m-d") . ".log";
341
			$logger->log(array(
342
				date("Y-m-d H:i:s"),
343
				$resp
344
			));
345
		}
346
		return $respObject;
347
	}
348
349
	public function exec($paramsArray)
350
	{
351
		if (!isset($paramsArray["method"]))
352
		{
353
			trigger_error("No api name passed");
354
		}
355
		$inflector = new LtInflector;
0 ignored issues
show
Bug introduced by
The type LtInflector was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
356
		$inflector->conf["separator"] = ".";
357
		$requestClassName = ucfirst($inflector->camelize(substr($paramsArray["method"], 7))) . "Request";
358
		if (!class_exists($requestClassName))
359
		{
360
			trigger_error("No such api: " . $paramsArray["method"]);
361
		}
362
363
		$session = isset($paramsArray["session"]) ? $paramsArray["session"] : null;
364
365
		$req = new $requestClassName;
366
		foreach($paramsArray as $paraKey => $paraValue)
367
		{
368
			$inflector->conf["separator"] = "_";
369
			$setterMethodName = $inflector->camelize($paraKey);
370
			$inflector->conf["separator"] = ".";
371
			$setterMethodName = "set" . $inflector->camelize($setterMethodName);
372
			if (method_exists($req, $setterMethodName))
373
			{
374
				$req->$setterMethodName($paraValue);
375
			}
376
		}
377
		return $this->execute($req, $session);
378
	}
379
380
	private function getClusterTag()
381
    {
382
	    return substr($this->sdkVersion,0,11)."-cluster".substr($this->sdkVersion,11);
383
    }
384
}
385