Tools.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | wechat-php-sdk
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2014~2017 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
  6. // +----------------------------------------------------------------------
  7. // | 官方文档: https://www.kancloud.cn/zoujingli/wechat-php-sdk
  8. // +----------------------------------------------------------------------
  9. // | 开源协议 ( https://mit-license.org )
  10. // +----------------------------------------------------------------------
  11. // | github开源项目:https://github.com/zoujingli/wechat-php-sdk
  12. // +----------------------------------------------------------------------
  13. namespace Wechat\Lib;
  14. use CURLFile;
  15. /**
  16. * 微信接口通用类
  17. *
  18. * @category WechatSDK
  19. * @subpackage library
  20. * @author Anyon <zoujingli@qq.com>
  21. * @date 2016/05/28 11:55
  22. */
  23. class Tools
  24. {
  25. /**
  26. * 产生随机字符串
  27. * @param int $length 指定字符长度
  28. * @param string $str 字符串前缀
  29. * @return string
  30. */
  31. static public function createNoncestr($length = 32, $str = "")
  32. {
  33. $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
  34. for ($i = 0; $i < $length; $i++) {
  35. $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  36. }
  37. return $str;
  38. }
  39. /**
  40. * 数据生成签名
  41. * @param array $data 签名数组
  42. * @param string $method 签名方法
  43. * @return bool|string 签名值
  44. */
  45. static public function getSignature($data, $method = "sha1")
  46. {
  47. if (!function_exists($method)) {
  48. return false;
  49. }
  50. ksort($data);
  51. $params = array();
  52. foreach ($data as $key => $value) {
  53. $params[] = "{$key}={$value}";
  54. }
  55. return $method(join('&', $params));
  56. }
  57. /**
  58. * 生成支付签名
  59. * @param array $option
  60. * @param string $partnerKey
  61. * @return string
  62. */
  63. static public function getPaySign($option, $partnerKey)
  64. {
  65. ksort($option);
  66. $buff = '';
  67. foreach ($option as $k => $v) {
  68. $buff .= "{$k}={$v}&";
  69. }
  70. return strtoupper(md5("{$buff}key={$partnerKey}"));
  71. }
  72. /**
  73. * XML编码
  74. * @param mixed $data 数据
  75. * @param string $root 根节点名
  76. * @param string $item 数字索引的子节点名
  77. * @param string $id 数字索引子节点key转换的属性名
  78. * @return string
  79. */
  80. static public function arr2xml($data, $root = 'xml', $item = 'item', $id = 'id')
  81. {
  82. return "<{$root}>" . self::_data_to_xml($data, $item, $id) . "</{$root}>";
  83. }
  84. /**
  85. * XML内容生成
  86. * @param array $data 数据
  87. * @param string $item 子节点
  88. * @param string $id 节点ID
  89. * @param string $content 节点内容
  90. * @return string
  91. */
  92. static private function _data_to_xml($data, $item = 'item', $id = 'id', $content = '')
  93. {
  94. foreach ($data as $key => $val) {
  95. is_numeric($key) && $key = "{$item} {$id}=\"{$key}\"";
  96. $content .= "<{$key}>";
  97. if (is_array($val) || is_object($val)) {
  98. $content .= self::_data_to_xml($val);
  99. } elseif (is_numeric($val)) {
  100. $content .= $val;
  101. } else {
  102. $content .= '<![CDATA[' . preg_replace("/[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]/", '', $val) . ']]>';
  103. }
  104. list($_key,) = explode(' ', $key . ' ');
  105. $content .= "</$_key>";
  106. }
  107. return $content;
  108. }
  109. /**
  110. * 将xml转为array
  111. * @param string $xml
  112. * @return array
  113. */
  114. static public function xml2arr($xml)
  115. {
  116. return json_decode(Tools::json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
  117. }
  118. /**
  119. * 生成安全JSON数据
  120. * @param array $array
  121. * @return string
  122. */
  123. static public function json_encode($array)
  124. {
  125. return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', function ($matches) {
  126. return mb_convert_encoding(pack("H*", $matches[1]), "UTF-8", "UCS-2BE");
  127. }, json_encode($array));
  128. }
  129. /**
  130. * 以get方式提交请求
  131. * @param $url
  132. * @return bool|mixed
  133. */
  134. static public function httpGet($url)
  135. {
  136. $curl = curl_init();
  137. if (stripos($url, "https") === 0) {
  138. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  139. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  140. curl_setopt($curl, CURLOPT_SSLVERSION, 1);
  141. }
  142. curl_setopt($curl, CURLOPT_URL, $url);
  143. curl_setopt($curl, CURLOPT_TIMEOUT, 30);
  144. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  145. list($content, $status) = array(curl_exec($curl), curl_getinfo($curl), curl_close($curl));
  146. return (intval($status["http_code"]) === 200) ? $content : false;
  147. }
  148. /**
  149. * 以post方式提交请求
  150. * @param string $url
  151. * @param array|string $data
  152. * @return bool|mixed
  153. */
  154. static public function httpPost($url, $data)
  155. {
  156. $curl = curl_init();
  157. curl_setopt($curl, CURLOPT_URL, $url);
  158. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  159. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  160. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  161. curl_setopt($curl, CURLOPT_HEADER, false);
  162. curl_setopt($curl, CURLOPT_POST, true);
  163. curl_setopt($curl, CURLOPT_POSTFIELDS, self::_buildPost($data));
  164. list($content, $status) = array(curl_exec($curl), curl_getinfo($curl), curl_close($curl));
  165. return (intval($status["http_code"]) === 200) ? $content : false;
  166. }
  167. /**
  168. * 使用证书,以post方式提交xml到对应的接口url
  169. * @param string $url POST提交的内容
  170. * @param array $data 请求的地址
  171. * @param string $ssl_cer 证书Cer路径 | 证书内容
  172. * @param string $ssl_key 证书Key路径 | 证书内容
  173. * @param int $second 设置请求超时时间
  174. * @return bool|mixed
  175. */
  176. static public function httpsPost($url, $data, $ssl_cer = null, $ssl_key = null, $second = 30)
  177. {
  178. $curl = curl_init();
  179. curl_setopt($curl, CURLOPT_URL, $url);
  180. curl_setopt($curl, CURLOPT_TIMEOUT, $second);
  181. curl_setopt($curl, CURLOPT_HEADER, false);
  182. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  183. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  184. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  185. if (!is_null($ssl_cer) && file_exists($ssl_cer) && is_file($ssl_cer)) {
  186. curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
  187. curl_setopt($curl, CURLOPT_SSLCERT, $ssl_cer);
  188. }
  189. if (!is_null($ssl_key) && file_exists($ssl_key) && is_file($ssl_key)) {
  190. curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
  191. curl_setopt($curl, CURLOPT_SSLKEY, $ssl_key);
  192. }
  193. curl_setopt($curl, CURLOPT_POST, true);
  194. curl_setopt($curl, CURLOPT_POSTFIELDS, self::_buildPost($data));
  195. list($content, $status) = array(curl_exec($curl), curl_getinfo($curl), curl_close($curl));
  196. return (intval($status["http_code"]) === 200) ? $content : false;
  197. }
  198. /**
  199. * POST数据过滤处理
  200. * @param array $data
  201. * @return array
  202. */
  203. static private function _buildPost(&$data)
  204. {
  205. if (is_array($data)) {
  206. foreach ($data as &$value) {
  207. if (is_string($value) && $value[0] === '@' && class_exists('CURLFile', false)) {
  208. $filename = realpath(trim($value, '@'));
  209. file_exists($filename) && $value = new CURLFile($filename);
  210. }
  211. }
  212. }
  213. return $data;
  214. }
  215. /**
  216. * 读取微信客户端IP
  217. * @return null|string
  218. */
  219. static public function getAddress()
  220. {
  221. foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP', 'REMOTE_ADDR') as $header) {
  222. if (!isset($_SERVER[$header]) || ($spoof = $_SERVER[$header]) === null) {
  223. continue;
  224. }
  225. sscanf($spoof, '%[^,]', $spoof);
  226. if (!filter_var($spoof, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
  227. $spoof = null;
  228. } else {
  229. return $spoof;
  230. }
  231. }
  232. return '0.0.0.0';
  233. }
  234. /**
  235. * 设置缓存,按需重载
  236. * @param string $cachename
  237. * @param mixed $value
  238. * @param int $expired
  239. * @return bool
  240. */
  241. static public function setCache($cachename, $value, $expired = 0)
  242. {
  243. return Cache::set($cachename, $value, $expired);
  244. }
  245. /**
  246. * 获取缓存,按需重载
  247. * @param string $cachename
  248. * @return mixed
  249. */
  250. static public function getCache($cachename)
  251. {
  252. return Cache::get($cachename);
  253. }
  254. /**
  255. * 清除缓存,按需重载
  256. * @param string $cachename
  257. * @return bool
  258. */
  259. static public function removeCache($cachename)
  260. {
  261. return Cache::del($cachename);
  262. }
  263. /**
  264. * SDK日志处理方法
  265. * @param string $msg 日志行内容
  266. * @param string $type 日志级别
  267. */
  268. static public function log($msg, $type = 'MSG')
  269. {
  270. Cache::put($type . ' - ' . $msg);
  271. }
  272. }