You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AliExecute.php 14 KiB

3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. <?php
  2. namespace backend\modules\hotel\models\Ali;
  3. /**
  4. * Created by PhpStorm.
  5. * User: Steven
  6. * Date: 2017/10/12
  7. * Time: 14:28
  8. */
  9. use common\models\commonModel;
  10. class AliExecute extends commonModel
  11. {
  12. //TOP分配给应用的AppKey
  13. public $appkey = '23769843'; // 正式环境
  14. // public $appkey = '1023769843'; // 沙箱环境
  15. //TOP分配给应用的AppKey
  16. public $secretKey = '94327ea2d0e45d084b8b7f1a6eba590e';
  17. //响应格式。默认为xml格式,可选值:xml,json。
  18. public $format = "json";
  19. //HTTP请求地址
  20. public $gatewayUrl = "http://gw.api.taobao.com/router/rest"; //正式环境23769843
  21. // public $gatewayUrl = "http://gw.api.tbsandbox.com/router/rest"; //沙箱环境
  22. //签名的摘要算法,可选值为:hmac,md5
  23. protected $signMethod = "md5";
  24. //API协议版本,可选值:2.0。
  25. protected $apiVersion = "2.0";
  26. protected $sdkVersion = "top-sdk-php-20151012";
  27. public $connectTimeout;
  28. public $readTimeout;
  29. public $session = '6101915c7f2e081083b6971187bfa138e2805a913f2c8a42850504041';
  30. public $sessionUpdateTime = '2020-03-18 10:26:28';
  31. private $Username = 'taobao_zz'; //阿里用于请求下单等操作的用户名
  32. private $Password = "zzcx1q2w3e4r"; //密码
  33. private $CreateToken = '22251178182015010620150107497867981843210904377';
  34. public $action_id = '';
  35. public $action_param = '';
  36. /**
  37. * Author:Steven
  38. * Desc:
  39. * @param $request
  40. */
  41. public function validAuth($request)
  42. {
  43. if ($request == '') {
  44. return false;
  45. }
  46. $request = simplexml_load_string($request, 'SimpleXMLElement', LIBXML_NOCDATA);
  47. $this->action_id = $request->getName();
  48. $logger = new TopLogger;
  49. $user_ip=\Yii::$app->request->userIP;
  50. $logger->log([date("Y-m-d H:i:s"), "【{$this->action_id}】【{$user_ip}】" . $request->asXML()], 'ali/order');
  51. if (isset($request->AuthenticationToken)) {
  52. $AuthenticationToken = $request->AuthenticationToken;
  53. if ($AuthenticationToken->Username != $this->Username || $AuthenticationToken->Password != $this->Password) {
  54. //权限验证失败
  55. return false;
  56. }
  57. unset($request->AuthenticationToken);
  58. $this->action_param = $request;
  59. } else {
  60. return false;
  61. }
  62. return true;
  63. }
  64. /**
  65. * Author:Steven
  66. * Desc:生成合作伙伴身份标识
  67. * @return string
  68. */
  69. private function getClusterTag()
  70. {
  71. return substr($this->sdkVersion, 0, 11) . "-cluster" . substr($this->sdkVersion, 11);
  72. }
  73. /**
  74. * Author:Steven
  75. * Desc:组装需要的参数发送请求
  76. * @param $request
  77. * @param bool $session_flag
  78. * @param null $bestUrl
  79. * @return mixed|\SimpleXMLElement
  80. */
  81. public function execute($request, $session_flag = false, $bestUrl = null)
  82. {
  83. //组装系统参数(公共参数)
  84. $sysParams["app_key"] = $this->appkey;
  85. $sysParams["v"] = $this->apiVersion;
  86. $sysParams["format"] = $this->format;
  87. $sysParams["sign_method"] = $this->signMethod;
  88. //用户登录授权成功后,TOP颁发给应用的授权信息。当此API的标签上注明:“需要授权”,则此参数必传;“不需要授权”,则此参数不需要传;“可选授权”,则此参数为可选
  89. $sysParams["method"] = $request->getApiMethodName();
  90. $sysParams["timestamp"] = date("Y-m-d H:i:s");
  91. if ($session_flag) {
  92. $sysParams["session"] = $this->session;
  93. }
  94. //系统参数放入GET请求串
  95. if ($bestUrl) {
  96. $requestUrl = $bestUrl . "?";
  97. $sysParams["partner_id"] = $this->getClusterTag();
  98. } else {
  99. $requestUrl = $this->gatewayUrl . "?";
  100. $sysParams["partner_id"] = $this->sdkVersion;
  101. }
  102. //获取业务参数
  103. $apiParams = $request->getApiParas();
  104. //签名串
  105. $sysParams["sign"] = $this->generateSign(array_merge($apiParams, $sysParams));
  106. foreach ($sysParams as $sysParamKey => $sysParamValue) {
  107. // if(strcmp($sysParamKey,"timestamp") != 0)
  108. $requestUrl .= "$sysParamKey=" . urlencode($sysParamValue) . "&";
  109. }
  110. $fileFields = array();
  111. foreach ($apiParams as $key => $value) {
  112. if (is_array($value) && array_key_exists('type', $value) && array_key_exists('content', $value)) {
  113. $value['name'] = $key;
  114. $fileFields[$key] = $value;
  115. unset($apiParams[$key]);
  116. }
  117. }
  118. // $requestUrl .= "timestamp=" . urlencode($sysParams["timestamp"]) . "&";
  119. $requestUrl = substr($requestUrl, 0, -1);
  120. //发起HTTP请求
  121. try {
  122. $startTime = microtime(TRUE);
  123. $logger = new TopLogger;
  124. $logger->log(array(date("Y-m-d H:i:s"), $requestUrl . "\n" . json_encode($apiParams, true)), 'ali/room_status');
  125. if (count($fileFields) > 0) {
  126. $resp = $this->curl_with_memory_file($requestUrl, $apiParams, $fileFields);
  127. } else {
  128. $resp = $this->curl($requestUrl, $apiParams);
  129. }
  130. $endTime = microtime(TRUE);
  131. $scTime = round(floatval($endTime - $startTime), 3);//时间差
  132. $user_id = \Yii::$app -> user -> id;
  133. $logger->log(array($user_id. "\n". date("Y-m-d H:i:s"), $resp . "\n" . 'time:' . $scTime . 's' . PHP_EOL), 'ali/room_status');
  134. } catch (\Exception $e) {
  135. $this->logCommunicationError($sysParams["method"], $requestUrl, "HTTP_ERROR_" . $e->getCode(), $e->getMessage());
  136. $result['code'] = $e->getCode();
  137. $result['msg'] = $e->getMessage();
  138. return $result;
  139. }
  140. unset($apiParams);
  141. unset($fileFields);
  142. //解析返回结果
  143. $respWellFormed = false;
  144. if ("json" == $this->format) {
  145. $respObject = json_decode($resp);
  146. if (null !== $respObject) {
  147. $respWellFormed = true;
  148. foreach ($respObject as $propKey => $propValue) {
  149. $respObject = $propValue;
  150. }
  151. }
  152. } else if ("xml" == $this->format) {
  153. $respObject = @simplexml_load_string($resp);
  154. if (false !== $respObject) {
  155. $respWellFormed = true;
  156. }
  157. }
  158. //返回的HTTP文本不是标准JSON或者XML,记下错误日志
  159. if (false === $respWellFormed) {
  160. $this->logCommunicationError($sysParams["method"], $requestUrl, "HTTP_RESPONSE_NOT_WELL_FORMED", $resp);
  161. $result['code'] = 0;
  162. $result['msg'] = "HTTP_RESPONSE_NOT_WELL_FORMED";
  163. return $result;
  164. }
  165. //如果TOP返回了错误码,记录到业务错误日志中
  166. if (isset($respObject->code)) {
  167. $logger = new TopLogger;
  168. $logger->log(array(
  169. date("Y-m-d H:i:s"),
  170. $resp
  171. ));
  172. }
  173. return $respObject;
  174. }
  175. /**
  176. * Author:Steven
  177. * Desc:生成签名串
  178. * @param $params
  179. * @return string
  180. */
  181. protected function generateSign($params)
  182. {
  183. ksort($params);
  184. $stringToBeSigned = $this->secretKey;
  185. foreach ($params as $k => $v) {
  186. if (is_string($v) && "@" != substr($v, 0, 1)) {
  187. $stringToBeSigned .= "$k$v";
  188. }
  189. }
  190. unset($k, $v);
  191. $stringToBeSigned .= $this->secretKey;
  192. return strtoupper(md5($stringToBeSigned));
  193. }
  194. /**
  195. * Author:Steven
  196. * Desc:
  197. * @param $url
  198. * @param null $postFields
  199. * @return mixed
  200. * @throws Exception
  201. */
  202. public function curl($url, $postFields = null)
  203. {
  204. $ch = curl_init();
  205. curl_setopt($ch, CURLOPT_URL, $url);
  206. curl_setopt($ch, CURLOPT_FAILONERROR, false);
  207. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  208. if ($this->readTimeout) {
  209. curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
  210. }
  211. if ($this->connectTimeout) {
  212. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
  213. }
  214. curl_setopt($ch, CURLOPT_USERAGENT, "top-sdk-php");
  215. //https 请求
  216. if (strlen($url) > 5 && strtolower(substr($url, 0, 5)) == "https") {
  217. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  218. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  219. }
  220. if (is_array($postFields) && 0 < count($postFields)) {
  221. $postBodyString = "";
  222. $postMultipart = false;
  223. foreach ($postFields as $k => $v) {
  224. if (!is_string($v))
  225. continue;
  226. if ("@" != substr($v, 0, 1))//判断是不是文件上传
  227. {
  228. $postBodyString .= "$k=" . urlencode($v) . "&";
  229. } else//文件上传用multipart/form-data,否则用www-form-urlencoded
  230. {
  231. $postMultipart = true;
  232. if (class_exists('\CURLFile')) {
  233. $postFields[$k] = new \CURLFile(substr($v, 1));
  234. }
  235. }
  236. }
  237. unset($k, $v);
  238. curl_setopt($ch, CURLOPT_POST, true);
  239. if ($postMultipart) {
  240. if (class_exists('\CURLFile')) {
  241. curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
  242. } else {
  243. if (defined('CURLOPT_SAFE_UPLOAD')) {
  244. curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
  245. }
  246. }
  247. curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
  248. } else {
  249. $header = array("content-type: application/x-www-form-urlencoded; charset=UTF-8");
  250. curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  251. curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString, 0, -1));
  252. }
  253. }
  254. $reponse = curl_exec($ch);
  255. if (curl_errno($ch)) {
  256. throw new \Exception(curl_error($ch), 0);
  257. } else {
  258. $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  259. if (200 !== $httpStatusCode) {
  260. throw new \Exception($reponse, $httpStatusCode);
  261. }
  262. }
  263. curl_close($ch);
  264. return $reponse;
  265. }
  266. /**
  267. * Author:Steven
  268. * Desc:
  269. * @param $url
  270. * @param null $postFields
  271. * @param null $fileFields
  272. * @return mixed
  273. * @throws Exception
  274. */
  275. public function curl_with_memory_file($url, $postFields = null, $fileFields = null)
  276. {
  277. $ch = curl_init();
  278. curl_setopt($ch, CURLOPT_URL, $url);
  279. curl_setopt($ch, CURLOPT_FAILONERROR, false);
  280. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  281. if ($this->readTimeout) {
  282. curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
  283. }
  284. if ($this->connectTimeout) {
  285. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
  286. }
  287. curl_setopt($ch, CURLOPT_USERAGENT, "top-sdk-php");
  288. //https 请求
  289. if (strlen($url) > 5 && strtolower(substr($url, 0, 5)) == "https") {
  290. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  291. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  292. }
  293. //生成分隔符
  294. $delimiter = '-------------' . uniqid();
  295. //先将post的普通数据生成主体字符串
  296. $data = '';
  297. if ($postFields != null) {
  298. foreach ($postFields as $name => $content) {
  299. $data .= "--" . $delimiter . "\r\n";
  300. $data .= 'Content-Disposition: form-data; name="' . $name . '"';
  301. //multipart/form-data 不需要urlencode,参见 http:stackoverflow.com/questions/6603928/should-i-url-encode-post-data
  302. $data .= "\r\n\r\n" . $content . "\r\n";
  303. }
  304. unset($name, $content);
  305. }
  306. //将上传的文件生成主体字符串
  307. if ($fileFields != null) {
  308. foreach ($fileFields as $name => $file) {
  309. $data .= "--" . $delimiter . "\r\n";
  310. $data .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $file['name'] . "\" \r\n";
  311. $data .= 'Content-Type: ' . $file['type'] . "\r\n\r\n";//多了个文档类型
  312. $data .= $file['content'] . "\r\n";
  313. }
  314. unset($name, $file);
  315. }
  316. //主体结束的分隔符
  317. $data .= "--" . $delimiter . "--";
  318. curl_setopt($ch, CURLOPT_POST, true);
  319. curl_setopt($ch, CURLOPT_HTTPHEADER, array(
  320. 'Content-Type: multipart/form-data; boundary=' . $delimiter,
  321. 'Content-Length: ' . strlen($data))
  322. );
  323. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  324. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  325. $reponse = curl_exec($ch);
  326. unset($data);
  327. if (curl_errno($ch)) {
  328. throw new \Exception(curl_error($ch), 0);
  329. } else {
  330. $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  331. if (200 !== $httpStatusCode) {
  332. throw new \Exception($reponse, $httpStatusCode);
  333. }
  334. }
  335. curl_close($ch);
  336. return $reponse;
  337. }
  338. /**
  339. * Author:Steven
  340. * Desc:通讯错误日志
  341. * @param $apiName
  342. * @param $requestUrl
  343. * @param $errorCode
  344. * @param $responseTxt
  345. */
  346. protected function logCommunicationError($apiName, $requestUrl, $errorCode, $responseTxt)
  347. {
  348. $localIp = isset($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : "CLI";
  349. $logger = new TopLogger;
  350. $logger->conf["separator"] = "^_^";
  351. $logData = array(
  352. date("Y-m-d H:i:s"),
  353. $apiName,
  354. $this->appkey,
  355. $localIp,
  356. PHP_OS,
  357. $this->sdkVersion,
  358. $requestUrl,
  359. $errorCode,
  360. str_replace("\n", "", $responseTxt)
  361. );
  362. $logger->log($logData);
  363. }
  364. public function checkExpireTime()
  365. {
  366. $second1 = strtotime($this->sessionUpdateTime);
  367. $second2 = time();
  368. if ($second1 < $second2) {
  369. $tmp = $second2;
  370. $second2 = $second1;
  371. $second1 = $tmp;
  372. }
  373. return ($second1 - $second2) / 86400;
  374. }
  375. }