init($config); $class_name = get_class($this); $this->log_file = "{$class_name}_{$this->appid}.log"; $this->log_dir = "{$class_name}_{$this->appid}"; } /** * @param $config ('appid', 'secret') */ function init($config) { $this->appid = $config['appid']; $this->secret = $config['secret']; $this->token_url = $config['token_url']; $CI = &get_instance(); $CI->load->library("hd_wechat", $config); /*这里用new的方式,因为load如果对象已经存在,会去取旧的,不会生成新配置的对象*/ $this->hd_wechat = new Hd_wechat($config); } /** * 获取或者重置access_token * @param $reset (是否重置) * @return mixed */ function access_token($reset = false) { $this->access_token = $this->hd_wechat->access_token($reset); return $this->access_token; } function activityid($unionid) { $access_token = $this->access_token(); if (!$access_token) { debug_log("[error] " . __FUNCTION__ . ": not access_token", $this->log_file); return array(); } $pre_url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/activityid/create?unionid={$unionid}&access_token="; $url = $pre_url . $access_token; $res = $this->url_get($url); $ret = json_decode($res, true); return $ret; } /** * 生成二维码 * @param $filename (文件名称) * @param $scene (最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) * @param $page (必须是已经发布的小程序存在的页面(否则报错),例如 pages/index/index, 根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面) * @param $width (二维码的宽度,单位 px,最小 280px,最大 1280px,默认430px) * @return array {'file':'文件路径', 'url':'访问相对路径'} */ function qrcode($filename, $scene, $page, $width) { $file = APPPATH . '../www/api/wx/' . $filename . '.png'; $dir = substr($file, 0, strrpos($file, '/')); if (!is_dir($dir)) { $ret = mkdir($dir, 0777, true);// 如果文件夹不存在,将以递归方式创建该文件夹 if (!$ret) { debug_log("[error] " . __FUNCTION__ . ": mkdir {$ret}, filename:{$filename}, scene:{$scene}, page:{$page}, width:{$width}", $this->log_file); return array(); } } if (file_exists($file)) { return array('file' => $file, 'url' => 'wx/' . $filename . '.png'); } $access_token = $this->access_token(); var_dump($access_token);exit; if (!$access_token) { debug_log("[error] " . __FUNCTION__ . ": not access_token", $this->log_file); return array(); } $pre_url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='; $url = $pre_url . $access_token; $data = array( 'scene' => $scene, 'page' => $page, 'width' => $width ? $width : 430, ); list($code, $res) = $this->curl_post($url, $data); $ret = json_decode($res, true); if (isset($ret['errcode']) && 40001 == $ret['errcode']) {//token过期,重置后请求 $url = $pre_url . $this->access_token(true); list($code, $res) = $this->curl_post($url, $data); $ret = json_decode($res, true); } if (isset($ret['errcode'])) { debug_log("[error] " . __FUNCTION__ . ": httpcode:{$code}, response:{$res}, filename:{$filename}, scene:{$scene}, page:{$page}, width:{$width}", $this->log_file); return array(); } $ret = file_put_contents($file, $res); if (false === $ret) { debug_log("[error] " . __FUNCTION__ . ": file_put_contents {$ret}, filename:{$filename}, scene:{$scene}, page:{$page}, width:{$width}", $this->log_file); return array(); } return array('file' => $file, 'url' => 'wx/' . $filename . '.png'); } /** * 获取微信用户信息 * @param $openid * @return array|mixed */ function user($openid) { $access_token = $this->access_token(); if (!$access_token) { debug_log("[error] " . __FUNCTION__ . ": not access_token", $this->log_file); return array(); } $pre_url = "https://api.weixin.qq.com/cgi-bin/user/info?openid={$openid}&lang=zh_CN&access_token="; $url = $pre_url . $access_token; $res = $this->url_get($url); $ret = json_decode($res, true); if (isset($ret['errcode']) && 40001 == $ret['errcode']) {//token过期,重置后请求 $url = $pre_url . $this->access_token(true); $res = $this->url_get($url); $ret = json_decode($res, true); } if (isset($ret['errcode'])) { debug_log("[error] " . __FUNCTION__ . ":url=$url, res={$res}", $this->log_file); return array(); } /* { "subscribe": 1,//是否关注 "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", "nickname": "Band", "sex": 1, "language": "zh_CN", "city": "广州", "province": "广东", "country": "中国", "headimgurl":"http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0", "subscribe_time": 1382694957, "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL" "remark": "", "groupid": 0, "tagid_list":[128,2], "subscribe_scene": "ADD_SCENE_QR_CODE", "qr_scene": 98765, "qr_scene_str": "" } */ return $ret; } /** * 批获取用户信息 * @param $openids * @return array|mixed */ function users($openids) { $lists = array(); foreach ($openids as $openid) { $lists[] = array( "openid" => $openid, 'lang' => "zh_CN", ); } $access_token = $this->access_token(); if (!$access_token) { debug_log("[error] " . __FUNCTION__ . ": not access_token", $this->log_file); return array(); } $pre_url = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token="; $url = $pre_url . $access_token; $data = array('user_list' => $lists); list($code, $res) = $this->curl_post($url, $data); $ret = json_decode($res, true); if (isset($ret['errcode']) && 40001 == $ret['errcode']) {//token过期,重置后请求 $url = $pre_url . $this->access_token(true); list($code, $res) = $this->curl_post($url, $data); $ret = json_decode($res, true); } if (isset($ret['errcode'])) { debug_log("[error] " . __FUNCTION__ . ":url=$url, res={$res}", $this->log_file); return array(); } /* { "user_info_list": [ { "subscribe": 1, "openid": "otvxTs4dckWG7imySrJd6jSi0CWE", "nickname": "iWithery", "sex": 1, "language": "zh_CN", "city": "揭阳", "province": "广东", "country": "中国", "headimgurl": "http://thirdwx.qlogo.cn/mmopen/xbIQx1GRqdvyqkMMhEaGOX802l1CyqMJNgUzKP8MeAeHFicRDSnZH7FY4XB7p8XHXIf6uJA2SCunTPicGKezDC4saKISzRj3nz/0", "subscribe_time": 1434093047, "unionid": "oR5GjjgEhCMJFyzaVZdrxZ2zRRF4", "remark": "", "groupid": 0, "tagid_list":[128,2], "subscribe_scene": "ADD_SCENE_QR_CODE", "qr_scene": 98765, "qr_scene_str": "" }, { "subscribe": 0, "openid": "otvxTs_JZ6SEiP0imdhpi50fuSZg" } ] } * */ return $ret; } /** * 获取用户列表 * @param $next_openid (起始openid,默认从头开始) * @return array {'total':'总数', 'count':'这次获取数', 'data':{'openid'['openid'],'next_openid':'下一页起始openid'}} */ function openids($next_openid = '') { $access_token = $this->access_token(); if (!$access_token) { debug_log("[error] " . __FUNCTION__ . ": not access_token", $this->log_file); return array(); } $pre_url = "https://api.weixin.qq.com/cgi-bin/user/get?next_openid={$next_openid}&access_token="; $url = $pre_url . $access_token; $res = $this->url_get($url); $ret = json_decode($res, true); if (isset($ret['errcode']) && 40001 == $ret['errcode']) {//token过期,重置后请求 $url = $pre_url . $this->access_token(true); $res = $this->url_get($url); $ret = json_decode($res, true); } if (isset($ret['errcode'])) { debug_log("[error] " . __FUNCTION__ . ":url=$url, res={$res}", $this->log_file); return array(); } /* { "total":2, "count":2, "data":{ "openid":["OPENID1","OPENID2"]}, "next_openid":"NEXT_OPENID" } */ return $ret; } /** * 获取回放源视频和获取直播房间列表 共用(调用限额 10 万次/天,200 次/分钟) * @param $start 起始拉取房间,start = 0 表示从第 1 个房间开始拉取 * @param $limit 每次拉取的个数上限,不要设置过大,建议 100 以内 * @param $room_id 直播间id,当传直播间id获取视频 */ function getliveinfo($start = 0, $limit = 20, $room_id = '') { $access_token = $this->access_token(); if (!$access_token) { debug_log("[error] " . __FUNCTION__ . ": not access_token", $this->log_file); return array(); } $data = array( 'start' => $start, 'limit' => $limit ); if ($room_id) {//直播间id $data['room_id'] = $room_id; $data['action'] = 'get_replay'; } $pre_url = "https://api.weixin.qq.com/wxa/business/getliveinfo?access_token="; $url = $pre_url . $access_token; list($code, $res) = $this->curl_post($url, $data); $ret = json_decode($res, true); if (isset($ret['errcode']) && $ret['errcode'] != 'ok') { debug_log("[error] " . __FUNCTION__ . ":url=$url, res={$res}", $this->log_file); return array(); } return $ret; } /** * @return array|mixed */ function tag_get() { $access_token = $this->access_token(); if (!$access_token) { debug_log("[error] " . __FUNCTION__ . ": not access_token", $this->log_file); return array(); } $pre_url = "https://api.weixin.qq.com/cgi-bin/tags/get?access_token="; $url = $pre_url . $access_token; $res = $this->url_get($url); $ret = json_decode($res, true); if (isset($ret['errcode']) && (40001 == $ret['errcode'] || -1 == $ret['errcode'])) {//token过期,重置后请求 $url = $pre_url . $this->access_token(true); $res = $this->url_get($url); $ret = json_decode($res, true); } if (isset($ret['errcode'])) { debug_log("[error] " . __FUNCTION__ . ":url=$url, res={$res}", $this->log_file); return array(); } /* { "tags":[{ "id":1, "name":"每天一罐可乐星人", "count":0 //此标签下粉丝数 }] } */ return $ret; } /** * @param $tagid * @param string $next_openid * @return array|mixed */ function tag_user($tagid, $next_openid = '') { $access_token = $this->access_token(); if (!$access_token) { debug_log("[error] " . __FUNCTION__ . ": not access_token", $this->log_file); return array(); } $pre_url = "https://api.weixin.qq.com/cgi-bin/user/tag/get?access_token="; $url = $pre_url . $access_token; $data = array( 'tagid' => $tagid, 'next_openid' => $next_openid, ); list($code, $res) = $this->curl_post($url, $data); $ret = json_decode($res, true); if (isset($ret['errcode']) && (40001 == $ret['errcode'] || -1 == $ret['errcode'])) {//token过期,重置后请求 $url = $pre_url . $this->access_token(true); list($code, $res) = $this->curl_post($url, $data); $ret = json_decode($res, true); } if (isset($ret['errcode'])) { debug_log("[error] " . __FUNCTION__ . ":url=$url, res={$res}", $this->log_file); return array(); } /* { "count":2,//这次获取的粉丝数量 "data":{//粉丝列表 "openid":[ "ocYxcuAEy30bX0NXmGn4ypqx3tI0", "ocYxcuBt0mRugKZ7tGAHPnUaOW7Y" ] }, "next_openid":"ocYxcuBt0mRugKZ7tGAHPnUaOW7Y"//拉取列表最后一个用户的openid } */ return $ret; } /** * 内容安全校验 * @param $type "msg内容, img图片" * @param $data * @return array|mixed */ function sec_check($type, $data) { $pre_url = "https://api.weixin.qq.com/wxa/servicemarket?access_token="; $post_data = array(); switch ($type) { case 'msg': $post_data = array( "service" => "wxee446d7507c68b11", 'api' => "msgSecCheck", "client_msg_id" => "client_msg_id_1", "data" => array( "Action" => "TextApproval", "Text" => $data, ) ); break; case 'img': $post_data = array( "service" => "wxee446d7507c68b11", 'api' => "msgSecCheck", "client_msg_id" => "client_msg_id_1", "data" => array( "Action" => "ImageModeration", "Scenes" => ["PORN", "POLITICS", "TERRORISM"], "ImageUrl" => $data, "ImageBase64" => "", "Config" => "", "Extra" => "" ) ); break; } if (!$post_data) { debug_log("[error]# " . __FUNCTION__ . ": unknow type:{$type}", $this->log_file); return array(); } $access_token = $this->access_token(); if (!$access_token) { debug_log("[error] " . __FUNCTION__ . ": not access_token", $this->log_file); return array(); } $url = $pre_url . $access_token; list($code, $res) = $this->curl_post($url, $post_data); $ret = json_decode($res, true); if (isset($ret['errcode']) && 40001 == $ret['errcode']) {//token过期,重置后请求 $url = $pre_url . $this->access_token(true); list($code, $res) = $this->curl_post($url, $post_data); $ret = json_decode($res, true); } if (0 != $ret['errcode'] && 80714) { debug_log("[error] " . __FUNCTION__ . ":url=$url, res={$res}", $this->log_file); return array(); } switch ($type) { case "msg": /* { "errcode": 0, "errmsg": "ok", "data": "{$data}", "request_id": "MLw1pg8TN_O8SFol2BwbHNsKJtGl_Vf7WEaBObyDjYifxq9hx8v-TpQne9X_1jilYwA", "provider_errmsg": "", } $data={ "Response": { "EvilTokens": [ { "EvilFlag": 1, "EvilType": 2, "EvilKeywords": [ "骚逼" ] }, { "EvilFlag": 1, "EvilType": 3, "EvilKeywords": [ "你妈逼", "我草", "王八蛋", "你他妈的" ] }, { "EvilFlag": 2, "EvilType": 3, "EvilKeywords": [ "他妈的", "你他妈", "骚逼", "我草你妈", "王八" ] } ], "RequestId": "2cb93e69-8f5a-47a3-8dc3-93f177f2912b" } } */ $EvilFlags = array("正常", "恶意", "可疑送审"); $EvilTypes = array( 0 => '正常', 1 => '政治', 2 => '色情', 3 => '辱骂/低俗', 4 => '暴恐/毒品', 5 => '广告/灌水', 6 => '迷信/邪教', 7 => '其他违法(如跨站追杀/恶意竞争等)', 8 => '综合', 9 => '联系方式/链接', ); $msg = ""; if (0 == $ret['errcode'] && $ret['data']) { $response = json_decode($ret['data'], true); if ($response['Response'] && $response['Response']['EvilTokens']) { $rows = $response['Response']['EvilTokens']; foreach ($rows as $v) { $msg .= "{$EvilFlags[$v['EvilFlag']]}-{$EvilTypes[$v['EvilType']]}:" . implode(',', $v['EvilKeywords']) . ";"; } } $ret['msg'] = $msg; } break; case "img": /* 图片审核返回值 { "errcode": 0, "errmsg": "ok", "data": "{$data}", "request_id": "MLxQcr8W8oGH0nrM7d0FNjYtWap5v-FIjCVDH0zVV9oprnDyD2sKCiBPl7iT8zWEWPw", "provider_errmsg": "", } $data={ "Response": { "PornResult": { "Suggestion": "BLOCK", "Confidence": 99, "AdvancedInfo": "", "Type": "PORN", "Code": 0, "Msg": "OK" }, "PoliticsResult": { "Suggestion": "PASS", "Confidence": 37, "AdvancedInfo": "", "Type": "DNA", "Code": 0, "Msg": "OK", "FaceResults": [] }, "TerrorismResult": { "Suggestion": "PASS", "Confidence": 0, "AdvancedInfo": "", "Type": "LABEL", "Code": 0, "Msg": "OK", "FaceResults": [] }, "DisgustResult": null, "TextResult": null, "Suggestion": "BLOCK", "Extra": "", "RequestId": "33b73a27-8bb6-48d6-855e-cb6bab2faf20" } } */ $sugs = array("pass" => "正常", 'review' => "疑似", "block" => "违规"); $types = array( "PornResult" => "色情", "TerrorismResult" => "暴恐", "PoliticsResult" => "政治敏感", "DisgustResult" => "恶心内容", "TextResult" => "文字", ); $msg = ""; if (0 == $ret['errcode'] && $ret['data']) { $response = json_decode($ret['data'], true); if ($response['Response']) { foreach ($response['Response'] as $k => $type) { if (!$types[$k] || !$type) { continue; } $sug = strtolower($type['Suggestion']); if ('pass' == $sug) { continue; } $msg .= "{$types[$k]}:{$sugs[$sug]};"; } } $ret['msg'] = $msg; } break; } return $ret; } /** * 从其他接口获取token,保证获取token不影响其他平台 * @param $url * @return string */ private function get_self_token($url) { $res = trim(file_get_contents($url)); debug_log("[info] " . __FUNCTION__ . ":url={$url}, res={$res}", $this->log_file); return $res; } /** * @param $url * @param $data * @return array */ private function curl_post($url, $data) { debug_log("[info] " . __FUNCTION__ . ":url={$url}, data=" . json_encode($data, JSON_UNESCAPED_UNICODE), $this->log_file); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_UNICODE)); $res = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $size = strlen($res); if ($size > 5000) { debug_log("[info] " . __FUNCTION__ . ":httpcode={$code}, response is big only show size={$size}", $this->log_file); } else { debug_log("[info] " . __FUNCTION__ . ":httpcode={$code}, response={$res}", $this->log_file); } return array($code, $res); } /** * @param $url * @return string */ private function url_get($url) { $res = file_get_contents($url); debug_log("[info] " . __FUNCTION__ . ":url={$url}, res={$res}", $this->log_file); return $res; } }