CURL.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: tandunzhao
  5. * Date: 2017/12/13
  6. * Time: 下午2:56
  7. */
  8. namespace App\Libs\allinpay;
  9. define('IS_DEBUG_CURL', FALSE);
  10. class CURL
  11. {
  12. public static $instance = NULL;
  13. public static function factory($config = NULL)
  14. {
  15. if (! isset(self::$instance))
  16. {
  17. self::$instance = new CURL($config);
  18. }
  19. return self::$instance;
  20. }
  21. private $ch = NULL;
  22. private $timeout = 5;
  23. public $target_ip = NULL;
  24. public $response = '';
  25. public $response_header = '';
  26. public $response_body = '';
  27. public $response_http_code = 100;
  28. public $cookie_file = './curl_cookie.txt';
  29. private $use_cookie = FALSE;
  30. private $referer = NULL;
  31. private $options = array(
  32. CURLOPT_HEADER => TRUE,
  33. CURLOPT_VERBOSE => 0,
  34. CURLOPT_RETURNTRANSFER => TRUE,
  35. CURLOPT_MAXREDIRS => 5,
  36. CURLOPT_FOLLOWLOCATION => TRUE,
  37. CURLOPT_ENCODING => '',
  38. CURLOPT_USERAGENT => 'cURL API Utility/1.0 (compatible;)',
  39. CURLOPT_DNS_CACHE_TIMEOUT => 1800
  40. );
  41. private $reqest_headers = array('Expect:');
  42. private $domain = NULL;
  43. private $append_cookie_data = array();
  44. public function __construct($config = NULL)
  45. {
  46. }
  47. /**
  48. * 强制把域名指向到该IP地址,忽略Host、DNS服务器等域名设置
  49. * 但是注意:
  50. * 本处做法只能访问那些直接能访问的服务器,
  51. * 不能经过中间层(F5、Nginx等)负载均衡过去。
  52. * @param string $target_ip
  53. * @return $this
  54. */
  55. public function force_ip($target_ip)
  56. {
  57. $this->target_ip = $target_ip;
  58. return $this;
  59. }
  60. public function fake_ip($client_ip)
  61. {
  62. $this->reqest_headers[] = 'X-FORWARDED-FOR:'.$client_ip;
  63. $this->reqest_headers[] = 'X-REAL-IP:'.$client_ip;
  64. $this->reqest_headers[] = 'CLIENT-IP:'.$client_ip;
  65. $this->reqest_headers[] = 'REMOTE-ADDR:'.$client_ip;
  66. return $this;
  67. }
  68. private function prepare($url, $data = array(), $referrer = NULL, $timeout = 5, $headers = array())
  69. {
  70. $this->headers($headers);
  71. $this->referrer($referrer);
  72. $this->set_timeout($timeout);
  73. $this->options[CURLOPT_REFERER] = $this->referer;
  74. $this->options[CURLOPT_HTTPHEADER] = $this->reqest_headers;
  75. $this->options[CURLOPT_CONNECTTIMEOUT] = $this->timeout;
  76. return $this;
  77. }
  78. public function get($url, $params = array(), $referrer = NULL, $timeout = 5, $headers = array())
  79. {
  80. $this->prepare($url, $params, $referrer, $timeout, $headers);
  81. $this->options[CURLOPT_URL] = $this->get_url($url, $params);
  82. echo $this->get_url($url, $params).'<br>';
  83. $this->options[CURLOPT_CONNECTTIMEOUT] = $this->timeout;
  84. $this->options[CURLOPT_HTTPGET] = TRUE;
  85. $ret = $this->execute(FALSE);
  86. return $ret === FALSE ? FALSE : $this->response();
  87. }
  88. public function post($url, $data = array(), $referrer = NULL, $timeout = 5, $headers = array())
  89. {
  90. $this->prepare($url, $data, $referrer, $timeout, $headers);
  91. $this->options[CURLOPT_URL] = $this->get_url($url);
  92. $this->options[CURLOPT_POST] = TRUE;
  93. $this->options[CURLOPT_POSTFIELDS] = $data;
  94. $ret = $this->execute(FALSE);
  95. return $ret === FALSE ? FALSE : $this->response();
  96. }
  97. public function response()
  98. {
  99. $response_info = curl_getinfo($this->handle());
  100. $this->destroy_curl();
  101. list ($this->response_header, $this->response_body) = explode("\r\n\r\n", $this->response, 2);
  102. if ($response_info['http_code'] != 200)
  103. {
  104. $msg = IS_DEBUG_CURL ? $response_info['http_code'].':'.$this->response_body : '';
  105. return $this->halt($msg, FALSE);
  106. }
  107. return array('header' => $this->response_header, 'body' => $this->response_body);
  108. }
  109. public function headers($headers = array())
  110. {
  111. if (empty($headers))
  112. {
  113. return $this->response_header;
  114. }
  115. else
  116. {
  117. $this->reqest_headers = array_merge($headers, $this->reqest_headers);
  118. return $this;
  119. }
  120. }
  121. public function cookie($name, $value, $expire = 0, $path = '/', $domain = '', $secure = FALSE, $httponly = FALSE)
  122. {
  123. $this->append_cookie_data[] = array(
  124. 'name' => $name,
  125. 'value' => $value,
  126. 'expire' => $expire,
  127. 'path' => $path,
  128. 'domain' => $domain,
  129. 'secure' => $secure,
  130. 'httponly' => $httponly
  131. );
  132. $this->use_cookie = TRUE;
  133. return $this;
  134. }
  135. public function set_cookie_file($cookie_file = NULL)
  136. {
  137. if (! is_null($cookie_file))
  138. {
  139. $this->cookie_file = $cookie_file;
  140. }
  141. $this->use_cookie = TRUE;
  142. return $this;
  143. }
  144. public function cookies($data = array())
  145. {
  146. foreach ($data as $d)
  147. {
  148. $this->append_cookie_data[] = array(
  149. 'name' => $d['name'],
  150. 'value' => $d['value'],
  151. 'expire' => isset($d['expire']) ? $d['expire'] : 0,
  152. 'path' => isset($d['path']) ? $d['path'] : '/',
  153. 'domain' => isset($d['domain']) ? $d['domain'] : '',
  154. 'secure' => (isset($d['secure']) and $d['secure']) ? 'TRUE' : 'FALSE',
  155. 'httponly' => (isset($d['httponly']) and $d['httponly']) ? 'TRUE' : 'FALSE'
  156. );
  157. }
  158. $this->use_cookie = TRUE;
  159. return $this;
  160. }
  161. public function append_cookie($data = array())
  162. {
  163. }
  164. public function referrer($referrer = '')
  165. {
  166. $this->referer = $referrer;
  167. return $this;
  168. }
  169. public function set_timeout($timeout = 5)
  170. {
  171. $this->timeout = $timeout;
  172. return $this;
  173. }
  174. public function set_useragent($useragent = '')
  175. {
  176. if (! empty($useragent))
  177. {
  178. $this->options[CURLOPT_USERAGENT] = $useragent;
  179. }
  180. return $this;
  181. }
  182. private function handle()
  183. {
  184. if (! is_resource($this->ch))
  185. {
  186. $this->ch = curl_init();
  187. }
  188. return $this->ch;
  189. }
  190. private function encoder($data = array())
  191. {
  192. return empty($data) ? '' : http_build_query($data);
  193. }
  194. public function use_ssl()
  195. {
  196. $this->options[CURLOPT_SSL_VERIFYHOST] = 2;
  197. $this->options[CURLOPT_SSL_VERIFYPEER] = FALSE;
  198. }
  199. /**
  200. * 设置代理
  201. *
  202. * @param $proxy_ip
  203. * @param $proxy_port
  204. * @param $type 代理类型,仅仅支持 http和socks5
  205. * @param $user
  206. * @param $password
  207. */
  208. public function proxy($proxy_ip, $proxy_port, $type = 'http', $user = '', $password = '')
  209. {
  210. $this->options[CURLOPT_HTTPPROXYTUNNEL] = TRUE;
  211. $this->options[CURLOPT_PROXY] = $proxy_ip . ':' . $proxy_port;
  212. $this->options[CURLOPT_PROXYTYPE] = $type == 'http' ? CURLPROXY_HTTP : CURLPROXY_SOCKS5;
  213. if (! empty($user))
  214. {
  215. $this->options[CURLOPT_PROXYUSERPWD] = $user . ':' . $password;
  216. }
  217. return $this;
  218. }
  219. private function get_url($url, $params = array())
  220. {
  221. $urldata = parse_url($url);
  222. if (strtolower($urldata['scheme']) == 'https')
  223. {
  224. $this->use_ssl();
  225. }
  226. $flag_contact = $query_string = '';
  227. if (! empty($this->target_ip))
  228. {
  229. $urldata['port'] = isset($urldata['port']) ? $urldata['port'] : '80';
  230. // $this->options[CURLOPT_PROXY] = $this->target_ip.':'.$urldata['port'];
  231. $this->proxy($this->target_ip, $urldata['port']);
  232. if (IS_DEBUG_CURL)
  233. {
  234. echo $this->target_ip . ':' . $urldata['port'] . "\r\n";
  235. }
  236. }
  237. if (! empty($params))
  238. {
  239. $query_string = $this->encoder($params);
  240. $flag_contact = strpos($url, '?') === FALSE ? '?' : '&';
  241. }
  242. if (IS_DEBUG_CURL)
  243. {
  244. echo $url . $flag_contact . $query_string . "\r\n";
  245. }
  246. $this->domain = $urldata['host'];
  247. return $url . $flag_contact . $query_string;
  248. }
  249. public function get_exist_cookies()
  250. {
  251. $exist_cookie_data = array();
  252. if (! empty($this->append_cookie_data) and is_file($this->cookie_file))
  253. {
  254. $content = file_get_contents($this->cookie_file);
  255. if (! empty($content))
  256. {
  257. $cookie_lines = explode("\n", str_replace("\r\n", "\n", $content));
  258. foreach ($cookie_lines as $cookie_line)
  259. {
  260. if (empty($cookie_line) or preg_match('/^#/', $cookie_line))
  261. continue;
  262. $cookie_fields = explode("\t", $cookie_line);
  263. $exist_cookie_data[$cookie_fields[0] . '_' . $cookie_fields[5]] = array(
  264. 'name' => urldecode($cookie_fields[5]),
  265. 'value' => urldecode($cookie_fields[6]),
  266. 'expire' => $cookie_fields[4],
  267. 'path' => urldecode($cookie_fields[2]),
  268. 'domain' => $cookie_fields[0],
  269. 'secure' => $cookie_fields[3],
  270. 'httponly' => $cookie_fields[1]
  271. );
  272. }
  273. }
  274. }
  275. return $exist_cookie_data;
  276. }
  277. private function execute($halt = FALSE)
  278. {
  279. $this->curl_cookie();
  280. curl_setopt_array($this->handle(), $this->options);
  281. $this->response = curl_exec($this->handle());
  282. $error_no = curl_errno($this->handle());
  283. if ($error_no)
  284. {
  285. $msg = curl_error($this->handle());
  286. $this->destroy_curl();
  287. $this->halt('Error occured: NO.' . $error_no . ', ' . $msg, $halt);
  288. return FALSE;
  289. }
  290. }
  291. private function curl_cookie()
  292. {
  293. // echo "HostName: ".$this->domain."\n";
  294. if (! $this->use_cookie)
  295. return FALSE;
  296. if (! is_file($this->cookie_file))
  297. {
  298. file_put_contents($this->cookie_file, '');
  299. }
  300. $data_cookies = array();
  301. foreach ($this->append_cookie_data as $append_cookie)
  302. {
  303. $domain = $this->get_domain($append_cookie['domain']);
  304. $data_cookies[$domain . '_' . $append_cookie['name']] = $append_cookie;
  305. }
  306. $data_cookies += $this->get_exist_cookies();
  307. $output_cookie = array();
  308. foreach ($data_cookies as $data_cookie)
  309. {
  310. $domain = $this->get_domain($data_cookie['domain']);
  311. $output_cookie[] = $domain . "\t" . $data_cookie['httponly'] . "\t" . $data_cookie['path'] . "\t" . $data_cookie['secure'] . "\t" . $data_cookie['expire'] . "\t" . urlencode($data_cookie['name']) . "\t" .
  312. urlencode($data_cookie['value']);
  313. }
  314. if (! empty($output_cookie))
  315. {
  316. $content_pre = "# Netscape HTTP Cookie File\n" . "# http://curl.haxx.se/rfc/cookie_spec.html\n" . "# This file was generated by libcurl! Edit at your own risk.\n" . "\n";
  317. file_put_contents($this->cookie_file, $content_pre . implode("\n", $output_cookie) . "\n");
  318. }
  319. $this->options[CURLOPT_COOKIEJAR] = $this->cookie_file;
  320. $this->options[CURLOPT_COOKIEFILE] = $this->cookie_file;
  321. }
  322. private function get_domain($domain)
  323. {
  324. if (is_null($domain))
  325. {
  326. $domain = 'localhost';
  327. }
  328. elseif ($domain == '')
  329. {
  330. $domain = $this->domain;
  331. }
  332. return $domain;
  333. }
  334. private function destroy_curl()
  335. {
  336. if (is_resource($this->handle()))
  337. {
  338. curl_close($this->handle());
  339. $this->ch = NULL;
  340. }
  341. }
  342. private function get_httpcode()
  343. {
  344. }
  345. public function close()
  346. {
  347. $this->destroy_curl();
  348. if (is_file($this->cookie_file))
  349. {
  350. unlink($this->cookie_file);
  351. }
  352. }
  353. private function halt($msg = '', $is_exit = TRUE, $title = '') {
  354. if (! empty($title) AND IS_DEBUG_CURL) {
  355. echo "Title: $msg;;;;\r\n";
  356. }
  357. if (! empty($msg) AND IS_DEBUG_CURL) {
  358. echo "Message: $msg;;;;\r\n";
  359. }
  360. if ($is_exit) {
  361. exit();
  362. } else {
  363. return FALSE;
  364. }
  365. }
  366. }