init($config); } /** * @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; } /** * 生成二维码 * @param $filename (文件名称) * @param $scene (最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) * @param $page (必须是已经发布的小程序存在的页面(否则报错),例如 pages/index/index, 根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面) * @param $width (二维码的宽度,单位 px,最小 280px,最大 1280px,默认430px) * @return array {'file':'文件路径', 'url':'访问相对路径'} */ function wxacode($filename, $scene, $page, $width){ $file = APPPATH . '../www/home/wx/wxacode/' . $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/wxacode/' . $filename . '.png'); } $pre_url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='; $url = $pre_url . $this->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'); } function qrcode($filename, $scene, $type = 0, $expire = 0){ $file = APPPATH . '../www/home/wx/qrcode/' . $filename . '.png'; $file_url = 'wx/qrcode/' . $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}", $this->log_file); return array(); } } if(file_exists($file)){ return array('file' => $file, 'url' => $file_url); } if(is_numeric($scene)){ $action_info = array( 'scene' => array('scene_id' => $scene) ); $action_name = $type ? 'QR_LIMIT_SCENE' : 'QR_SCENE'; } else { $action_info = array( 'scene' => array('scene_str' => $scene) ); $action_name = $type ? 'QR_LIMIT_STR_SCENE' : 'QR_STR_SCENE'; } $data = array( 'action_name' => $action_name, 'action_info' => $action_info ); $expire && $data['expire_seconds'] = $expire; $qr_url = 'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token='; $url = $qr_url . $this->access_token(); //请求获取二维码的ticket list($code, $res) = $this->curl_post($url, $data); $ret = json_decode($res, true); if(isset($ret['errcode']) && 40001 == $ret['errcode']){//token过期,重置后请求 $url = $qr_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}", $this->log_file); return array(); } if(!$ret['ticket']){ debug_log("[error] ". __FUNCTION__ . ": not ticket, filename:{$filename}, scene:{$scene}", $this->log_file); return array(); } //根据ticket获取 $ticket_url='https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket='.$ret['ticket']; debug_log("[info] ". __FUNCTION__ . ": ticket_url=$ticket_url", $this->log_file); $ret = file_put_contents($file, $this->url_get($ticket_url)); if(false === $ret){ debug_log("[error] ". __FUNCTION__ . ": file_put_contents {$ret}, filename:{$filename}, scene:{$scene}", $this->log_file); return array(); } return array('file' => $file, 'url' => $file_url); } /** * @param $url * @param $data * @return array */ private function curl_post($url, $data){ debug_log("[info] ". __FUNCTION__ . ":url={$url}, data=".json_encode($data), $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)); $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; } }