weixin = $this->get_cache('weixin'.(WEIXIN_MORE_ID > 1 ? '_more_'.WEIXIN_MORE_ID : '')); // 配置 // 获取微信表名 function weixin_wxtable($name, $wxid = WEIXIN_MORE_ID) { $prefix = $wxid > 1 ? 'more_'.$wxid.'_' : ''; if ($name != 'weixin') { $name = 'weixin_'.$name; } return $prefix.$name; } // 获取access_token function weixin_get_access_token($data = []) { if (is_array($data) && $data) { $config = $data; } elseif ($data == 'update') { // 重写写入 $config = \Phpcmf\Service::C()->weixin['account']; } else { $cache_data = \Phpcmf\Service::L('cache')->get_auth_data('weixin_access_token_'.WEIXIN_MORE_ID, 1, 2200); if (is_array($cache_data)) { if ($cache_data['endtime'] && $cache_data['endtime'] > SYS_TIME && $cache_data['access_token']) { return dr_return_data(1, $cache_data['access_token']); } elseif (!\Phpcmf\Service::C()->weixin['account']) { return dr_return_data(0, '未配置微信接入参数'); } } $config = \Phpcmf\Service::C()->weixin['account']; } if (!$config['appid'] || !$config['appsecret']) { return dr_return_data(0, 'appid或者appsecret没填写'); } $result = wx_get_https_json_data('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$config['appid'].'&secret='.$config['appsecret']); if (!$result['code']) { return dr_return_data(0, 'AccessToken:'.$result['msg']); } elseif (!$result['data']['access_token']) { return dr_return_data(0, 'AccessToken为空,请重试'); } $result['data']['endtime'] = SYS_TIME + 2360; $rt = \Phpcmf\Service::L('cache')->set_auth_data('weixin_access_token_'.WEIXIN_MORE_ID, $result['data'], 1); if (!$rt) { return dr_return_data(0, 'AccessToken:/cache/authcode/目录不可写,文件写入失败'); } return dr_return_data(1, $result['data']['access_token']); } // 小程序获取access_token function xcx_get_access_token($data = []) { if (is_array($data) && $data) { $config = $data; } elseif ($data == 'update') { // 重写写入 $config = \Phpcmf\Service::C()->weixin['xcx']; } else { $cache_data = \Phpcmf\Service::L('cache')->get_auth_data('xcx_access_token_'.WEIXIN_MORE_ID, 1, 2200); if (is_array($cache_data)) { if ($cache_data['endtime'] && $cache_data['endtime'] > SYS_TIME && $cache_data['access_token']) { return dr_return_data(1, $cache_data['access_token']); } elseif (!\Phpcmf\Service::C()->weixin['xcx']) { return dr_return_data(0, '未配置小程序接入参数'); } } $config = \Phpcmf\Service::C()->weixin['xcx']; } if (!$config['appid'] || !$config['appsecret']) { return dr_return_data(0, 'appid或者appsecret没填写'); } $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $config['appid'] . '&secret=' . $config['appsecret'] . ''; $result = wx_get_https_json_data($url); if (!$result['code']) { return dr_return_data(0, 'AccessToken:'.$result['msg']); } elseif (!$result['data']['access_token']) { return dr_return_data(0, 'AccessToken为空,请重试'); } $result['data']['endtime'] = SYS_TIME + 2360; $rt = \Phpcmf\Service::L('cache')->set_auth_data('xcx_access_token_'.WEIXIN_MORE_ID, $result['data'], 1); if (!$rt) { return dr_return_data(0, 'AccessToken:/cache/authcode/目录不可写,文件写入失败'); } return dr_return_data(1, $result['data']['access_token']); } function ihttp_request($url, $post = '', $extra = array(), $timeout = 60) { $urlset = parse_url($url); if (empty($urlset['path'])) { $urlset['path'] = '/'; } if (!empty($urlset['query'])) { $urlset['query'] = "?{$urlset['query']}"; } if (empty($urlset['port'])) { $urlset['port'] = $urlset['scheme'] == 'https' ? '443' : '80'; } if (strexists($url, 'https://') && !extension_loaded('openssl')) { if (!extension_loaded("openssl")) { return dr_return_data(0, ' 请开启您PHP环境的openssl'); } } if (function_exists('curl_init') && function_exists('curl_exec')) { $ch = curl_init(); if (!empty($extra['ip'])) { $extra['Host'] = $urlset['host']; $urlset['host'] = $extra['ip']; unset($extra['ip']); } curl_setopt($ch, CURLOPT_URL, $urlset['scheme'] . '://' . $urlset['host'] . ($urlset['port'] == '80' ? '' : ':' . $urlset['port']) . $urlset['path'] . $urlset['query']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_HEADER, 1); //@curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); if ($post) { if (is_array($post)) { $filepost = false; foreach ($post as $name => &$value) { if (version_compare(phpversion(), '5.6') >= 0 && substr($value, 0, 1) == '@') { $value = new CURLFile(ltrim($value, '@')); if (version_compare(phpversion(), '7.4.3') == 0) { return dr_return_data(0, ' 本功能无法在php7.4.3中运行,请升级到php7.4.3以后的版本'); } } if ((is_string($value) && substr($value, 0, 1) == '@') || (class_exists('CURLFile') && $value instanceof CURLFile)) { $filepost = true; } } if (!$filepost) { $post = http_build_query($post); } } curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); } if (!empty($GLOBALS['_W']['config']['setting']['proxy'])) { $urls = parse_url($GLOBALS['_W']['config']['setting']['proxy']['host']); if (!empty($urls['host'])) { curl_setopt($ch, CURLOPT_PROXY, "{$urls['host']}:{$urls['port']}"); $proxytype = 'CURLPROXY_' . strtoupper($urls['scheme']); if (!empty($urls['scheme']) && defined($proxytype)) { curl_setopt($ch, CURLOPT_PROXYTYPE, constant($proxytype)); } else { curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); } if (!empty($GLOBALS['_W']['config']['setting']['proxy']['auth'])) { curl_setopt($ch, CURLOPT_PROXYUSERPWD, $GLOBALS['_W']['config']['setting']['proxy']['auth']); } } } curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSLVERSION, 1); if (defined('CURL_SSLVERSION_TLSv1')) { curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); } curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1'); if (!empty($extra) && is_array($extra)) { $headers = array(); foreach ($extra as $opt => $value) { if (strexists($opt, 'CURLOPT_')) { curl_setopt($ch, constant($opt), $value); } elseif (is_numeric($opt)) { curl_setopt($ch, $opt, $value); } else { $headers[] = "{$opt}: {$value}"; } } if (!empty($headers)) { curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); } } $data = curl_exec($ch); $status = curl_getinfo($ch); $errno = curl_errno($ch); $error = curl_error($ch); curl_close($ch); if ($errno || empty($data)) { return dr_return_data(0, '同步出错:'.$error); } else { return ihttp_response_parse($data); } } $method = empty($post) ? 'GET' : 'POST'; $fdata = "{$method} {$urlset['path']}{$urlset['query']} HTTP/1.1\r\n"; $fdata .= "Host: {$urlset['host']}\r\n"; if (function_exists('gzdecode')) { $fdata .= "Accept-Encoding: gzip, deflate\r\n"; } $fdata .= "Connection: close\r\n"; if (!empty($extra) && is_array($extra)) { foreach ($extra as $opt => $value) { if (!strexists($opt, 'CURLOPT_')) { $fdata .= "{$opt}: {$value}\r\n"; } } } $body = ''; if ($post) { if (is_array($post)) { $body = http_build_query($post); } else { $body = urlencode($post); } $fdata .= 'Content-Length: ' . strlen($body) . "\r\n\r\n{$body}"; } else { $fdata .= "\r\n"; } if ($urlset['scheme'] == 'https') { $fp = fsockopen('ssl://' . $urlset['host'], $urlset['port'], $errno, $error); } else { $fp = fsockopen($urlset['host'], $urlset['port'], $errno, $error); } stream_set_blocking($fp, true); stream_set_timeout($fp, $timeout); if (!$fp) { return dr_return_data(0, '同步出错:'.$error); } else { fwrite($fp, $fdata); $content = ''; while (!feof($fp)) $content .= fgets($fp, 512); fclose($fp); return ihttp_response_parse($content, true); } } function ihttp_response_parse($data, $chunked = false) { $rlt = array(); $headermeta = explode('HTTP/', $data); if (count($headermeta) > 2) { $data = 'HTTP/' . array_pop($headermeta); } $pos = strpos($data, "\r\n\r\n"); $split1[0] = substr($data, 0, $pos); $split1[1] = substr($data, $pos + 4, strlen($data)); $split2 = explode("\r\n", $split1[0], 2); preg_match('/^(\S+) (\S+) (.*)$/', $split2[0], $matches); $rlt['code'] = $matches[2]; $rlt['status'] = $matches[3]; $rlt['responseline'] = $split2[0]; $header = explode("\r\n", $split2[1]); $isgzip = false; $ischunk = false; foreach ($header as $v) { $pos = strpos($v, ':'); $key = substr($v, 0, $pos); $value = trim(substr($v, $pos + 1)); if (is_array($rlt['headers'][$key])) { $rlt['headers'][$key][] = $value; } elseif (!empty($rlt['headers'][$key])) { $temp = $rlt['headers'][$key]; unset($rlt['headers'][$key]); $rlt['headers'][$key][] = $temp; $rlt['headers'][$key][] = $value; } else { $rlt['headers'][$key] = $value; } if(!$isgzip && strtolower($key) == 'content-encoding' && strtolower($value) == 'gzip') { $isgzip = true; } if(!$ischunk && strtolower($key) == 'transfer-encoding' && strtolower($value) == 'chunked') { $ischunk = true; } } if($chunked && $ischunk) { $rlt['content'] = ihttp_response_parse_unchunk($split1[1]); } else { $rlt['content'] = $split1[1]; } if($isgzip && function_exists('gzdecode')) { $rlt['content'] = gzdecode($rlt['content']); } $rlt['meta'] = $data; if($rlt['code'] == '100') { return ihttp_response_parse($rlt['content']); } $data = json_decode($rlt['content'], true); if (!$data) { if($rlt['code'] != '200' && $rlt['status']) { return dr_return_data(0, $rlt['status']); } return dr_return_data(0, $rlt['content'].'不是一个有效的json数据'); } elseif (isset($data['errcode']) && $data['errcode']) { return dr_return_data(0, '错误代码('.dr_weixin_error_msg($data['errcode']).'):'.$data['errmsg']); } return dr_return_data(1, 'ok', $data); } function strexists($string, $find) { return !(strpos($string, $find) === FALSE); } /** * * 通过code从工作平台获取openid机器access_token * @param string $code 微信跳转回来带上的code * * @return openid */ function weixin_GetOpenidFromMp($code) { $url = weixin_CreateOauthUrlForOpenid($code); //初始化curl $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, 60); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE); curl_setopt($ch, CURLOPT_HEADER, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); //运行curl,结果以jason形式返回 $res = curl_exec($ch); curl_close($ch); //取出openid $data = json_decode($res,true); $openid = $data['openid']; return $openid; } /** * * 构造获取code的url连接 * @param string $redirectUrl 微信服务器回跳的url,需要url编码 * * @return 返回构造好的url */ function weixin_CreateOauthUrlForCode($redirectUrl) { $wx = \Phpcmf\Service::C()->get_cache('weixin'.(WEIXIN_MORE_ID > 1 ? '_more_'.WEIXIN_MORE_ID : '')); // 配置 $urlObj["appid"] = $wx['account']['appid']; $urlObj["redirect_uri"] = "$redirectUrl"; $urlObj["response_type"] = "code"; $urlObj["scope"] = "snsapi_base"; $urlObj["state"] = "STATE"."#wechat_redirect"; $bizString = weixin_ToUrlParams($urlObj); return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString; } /** * * 构造获取open和access_toke的url地址 * @param string $code,微信跳转带回的code * * @return 请求的url */ function weixin_CreateOauthUrlForOpenid($code) { $wx = \Phpcmf\Service::C()->get_cache('weixin'.(WEIXIN_MORE_ID > 1 ? '_more_'.WEIXIN_MORE_ID : '')); // 配置 $urlObj["appid"] = $wx['account']['appid']; $urlObj["secret"] = $wx['account']['appsecret']; $urlObj["code"] = $code; $urlObj["grant_type"] = "authorization_code"; $bizString = weixin_ToUrlParams($urlObj); return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString; } /** * * 拼接签名字符串 * @param array $urlObj * * @return 返回已经拼接好的字符串 */ function weixin_ToUrlParams($urlObj) { $buff = ""; foreach ($urlObj as $k => $v) { if($k != "sign"){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } // 从url获取json数据 function wx_get_https_json_data($url, $ct = 0) { if (!$url) { return dr_return_data(0, 'url为空'); } $response = dr_catcher_data($url); $data = json_decode($response, true); if (!$data) { return dr_return_data(0, var_export($response, true).' 不是一个有效的json数据'); } elseif (isset($data['errcode']) && $data['errcode']) { if ($data['errcode'] == '40001' && $ct == 0 && strpos($url, 'access_token=')) { // 重新获取token list($a, $b) = explode('access_token=', $url); if (strpos($b, '&') !== false) { list($b) = explode('&', $b); } $rt = weixin_get_access_token('update'); if ($rt['code']) { return wx_get_https_json_data(str_replace($b, $rt['msg'], $url), 1); } } return dr_return_data(0, '错误代码('.$data['errcode'].'):'.$data['errmsg']); } return dr_return_data(1, 'ok', $data); } // 从url获取json数据 function wx_post_https_json_data($url, $param = [], $ct = 0) { $rt = dr_post_json_data($url, json_encode($param, JSON_UNESCAPED_UNICODE)); if ($rt['code']) { if (isset($rt['data']['errcode']) && $rt['data']['errcode']) { if ($rt['data']['errcode'] == '40001' && $ct == 0 && strpos($url, 'access_token=')) { // 重新获取token list($a, $b) = explode('access_token=', $url); if (strpos($b, '&') !== false) { list($b) = explode('&', $b); } $rt = weixin_get_access_token('update'); if ($rt['code']) { return wx_post_https_json_data(str_replace($b, $rt['msg'], $url), $param, 1); } } return dr_return_data(0, '错误代码('.dr_weixin_error_msg($rt['data']['errcode']).'):'.$rt['data']['errmsg']); } } return $rt; } // 微信端的错误码转 function dr_weixin_error_msg($code) { if ($code == '40001') { // 清除掉token \Phpcmf\Service::L('cache')->del_auth_data('weixin_access_token_'.(WEIXIN_MORE_ID > 1 ? '_more_'.WEIXIN_MORE_ID : ''), 1); } return $code; }