Files
liche/api/controllers/Hd.php
T
2021-10-14 15:54:40 +08:00

730 lines
24 KiB
PHP
Executable File

<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Hd extends CI_Controller {
/**
* 版本控制
* 高版本写在前面
* 长的key写前面
* @var array
*/
private static $verison = array(
);
/**
* 应用ID
* @var array
*/
private static $apps = array(
'e49d182c6e6dab64' => 'liche',
'1c156bb57cd6984a' => 'licheb',
);
/**
* 错误信息映射到lang,数字不能使用
*/
private static $err_lang = array(
API_CODE_SUCCESS => 'api_code_success',
API_CODE_FAIL => 'api_code_fail',
API_CODE_NONE => 'api_code_none',
API_CODE_LOGOUT => 'api_code_logout',
);
private $request;
private $inputs;
private $log_file = 'hd.log';
public function wxapp(){
$callback = $_GET['callback'];
!$callback && $callback = $_POST['callback'];
trim($callback);//去掉首尾空白符
$callback = $this->match_version($callback);
$callback = explode('.', $callback);
if(count($callback) > 2) {
$method_name = array_pop($callback);
$class_name = ucfirst(array_pop($callback));
$dir = implode('/', $callback);
} else {
echo 'inval request';
exit;
}
define('WECHATAPP', 1);
$file_name = APPPATH."controllers/wxapp/{$dir}/{$class_name}.php";
if(file_exists($file_name)) {
require_once $file_name;
} else {
echo "class {$class_name} not exist";exit;
}
if($class_name == 'Welcome') {
$class = $this;
} else {
$class = new $class_name();
};
if(!$method_name || !method_exists($class, $method_name)) {
echo "method {$method_name} not exist";
exit;
};
try{
if(method_exists($class, 'check_login')){//校验登录
$class->check_login($method_name);
}
$result = $class->$method_name();
if(!$result) {
throw new Exception('', ERR_SYS_FAIL);
}
$this->print_return($result);
} catch (Exception $e) {
$this->print_return($this->return_error($e->getCode(), $e->getMessage()));
}
}
/**
* 内容入口
*/
function content(){
define('WXAPP_CONTENT', 1);
//加载输入参数
$this->input_param();
$version = $this->input_param('version');
$sversion = $this->input_param('sversion');
$app_id = $this->input_param('app_id');
$this->log_file = get_class($this) . "_{$app_id}.log";
//卡ID为空
$app = self::$apps[$app_id];
if(!$app_id){
debug_log("[fail]". __FUNCTION__ . ":app_id is null; uri_string:" . $this->uri->uri_string(), $this->log_file);
return $this->print_return($this->return_error(API_CODE_INVILD_PARAM, '应用不存在'));
}
//签名不正确
if(!$this->vaild_sign()){
debug_log("[fail]". __FUNCTION__ . ":sign check fail; uri_string:" . $this->uri->uri_string() . "; param:".json_encode($this->inputs), $this->log_file);
return $this->print_return($this->return_error(API_CODE_INVILD_PARAM, '验签失败'));
}
$app = self::$apps[$app_id];
$class_name = ucfirst($this->uri->segment(3));//:hd/content/subject/tag
if($this->uri->segment(4)){
$method = $this->request . "_" . $this->uri->segment(4);
} else {
$method = $this->request;
}
//app定制ct
$file_name = APPPATH."controllers/wxapp/content/{$app}/{$class_name}.php";
//ct不存在
if(file_exists($file_name)) {
require_once $file_name;
} else {
//app定制ct不存在,使用公共ct
$file_name = APPPATH."controllers/wxapp/content/{$class_name}.php";
if(file_exists($file_name)) {
require_once $file_name;
} else{
debug_log("[fail]". __FUNCTION__ . ": file '{$file_name}' not exist; method:{$method}, app_id:".$app_id, $this->log_file);
return $this->print_return($this->return_error(API_CODE_NONE, '内部错误'));
}
}
try{
$class = new $class_name($this->inputs, $app);
$result = $class->$method($version, $sversion);
if(!$result) {
throw new Exception('', ERR_SYS_FAIL);
}
return $this->print_return($result);
} catch (Exception $e){
return $this->print_return($this->return_error($e->getCode(), $e->getMessage()));
}
}
/**
* app其他入口
*/
function app(){
define('WXAPP_APP', 1);
//加载输入参数
$this->input_param();
$app_id = $this->input_param('app_id');
$version = $this->input_param('version');
$sversion = $this->input_param('sversion');
$this->log_file = get_class($this) . "_{$app_id}.log";
$app = self::$apps[$app_id];
$dir = $app;
//卡ID为空
if(!$app_id){
debug_log("[fail]". __FUNCTION__ . ": app_id is null; uri_string:" . $this->uri->uri_string(), $this->log_file);
return $this->print_return($this->return_error(API_CODE_INVILD_PARAM, '应用不存在'.$app_id));
}
//签名不正确
if(!$this->vaild_sign()){
debug_log("[fail]". __FUNCTION__ . ": sign check fail; uri_string:" . $this->uri->uri_string() . "; param:".json_encode($this->inputs), $this->log_file);
return $this->print_return($this->return_error(API_CODE_INVILD_PARAM, '验签失败'));
}
$class_name = ucfirst($this->uri->segment(3));//:hd/app/user/ukey
if($this->uri->segment(4)){
$method = $this->request . "_" . $this->uri->segment(4);
} else {
$method = $this->request;
}
//app定制ct
$file_name = APPPATH."controllers/wxapp/{$app}/{$class_name}.php";
//ct不存在
if(file_exists($file_name)) {
require_once $file_name;
} else {
$file_name = APPPATH."controllers/wxapp/app/{$dir}/Self_{$class_name}.php";
if(file_exists($file_name)){
require_once $file_name;
$class_name = "Self_{$class_name}";
} else {
//app定制ct不存在,使用公共ct
$file_name = APPPATH."controllers/wxapp/app/{$class_name}.php";
if(file_exists($file_name)) {
require_once $file_name;
} else{
debug_log("[fail]". __FUNCTION__ . ": file '{$file_name}' not exist; method:{$method}, app_id:".$app_id, $this->log_file);
return $this->print_return($this->return_error(API_CODE_NONE, '内部错误'));
}
}
}
try{
$class = new $class_name($this->inputs, $app);
$result = $class->$method($version, $sversion);
if(!$result) {
throw new Exception('', ERR_SYS_FAIL);
}
return $this->print_return($result);
} catch (Exception $e){
return $this->print_return($this->return_error($e->getCode(), $e->getMessage()));
}
}
/**
* 分销入口
*/
public function distribution(){
define('WXAPP_ITEMS', 1);
//加载输入参数
$this->input_param();
$app_id = $this->input_param('app_id');
!$app_id && $app_id = $this->input_param('vipcard_id');
$version = $this->input_param('version');
$sversion = $this->input_param('sversion');
$this->log_file = get_class($this) . "_{$app_id}.log";
//应用ID为空
if(!$app_id){
debug_log("[fail]". __FUNCTION__ . ":app_id is null; uri_string:" . $this->uri->uri_string(), $this->log_file);
return $this->print_return($this->return_error(API_CODE_INVILD_PARAM, '请求丢失'));
}
//签名不正确
if(!$this->vaild_sign()){
debug_log("[fail]". __FUNCTION__ . ":sign check fail; uri_string:" . $this->uri->uri_string() . "; param:".json_encode($this->inputs), $this->log_file);
return $this->print_return($this->return_error(API_CODE_INVILD_PARAM, '非法请求'));
}
$app = self::$apps[$app_id];
$class_name = ucfirst($this->uri->segment(3));
if($this->uri->segment(4)){
$method = $this->request . "_" . $this->uri->segment(4);
} else {
$method = $this->request;
}
//app定制ct
$file_name = APPPATH."controllers/wxapp/distribution/{$app}/{$class_name}.php";
//ct不存在
if(file_exists($file_name)) {
require_once $file_name;
} else {
//app定制ct不存在,使用公共ct
$file_name = APPPATH."controllers/wxapp/distribution/{$class_name}.php";
if(file_exists($file_name)) {
require_once $file_name;
} else{
debug_log("[fail]". __FUNCTION__ . ": file '{$file_name}' not exist; method:{$method}, app_id:".$app_id, $this->log_file);
return $this->print_return($this->return_error(API_CODE_NONE, '非法请求'));
}
}
try{
$class = new $class_name($this->inputs, $app);
$result = $class->$method($version, $sversion);
if(!$result) {
throw new Exception('', ERR_SYS_FAIL);
}
return $this->print_return($result);
} catch (Exception $e){
return $this->print_return($this->return_error($e->getCode(), $e->getMessage()));
}
}
/**
* 博饼入口
*/
public function bobing()
{
define('WXAPP_ITEMS', 1);
//加载输入参数
$this->input_param();
$app_id = $this->input_param('app_id');
!$app_id && $app_id = $this->input_param('vipcard_id');
$version = $this->input_param('version');
$sversion = $this->input_param('sversion');
$this->log_file = get_class($this) . "_{$app_id}.log";
//应用ID为空
if (!$app_id) {
debug_log("[fail]" . __FUNCTION__ . ":app_id is null; uri_string:" . $this->uri->uri_string(), $this->log_file);
return $this->print_return($this->return_error(API_CODE_INVILD_PARAM, '请求丢失'));
}
//签名不正确
if (!$this->vaild_sign()) {
debug_log("[fail]" . __FUNCTION__ . ":sign check fail; uri_string:" . $this->uri->uri_string() . "; param:" . json_encode($this->inputs), $this->log_file);
return $this->print_return($this->return_error(API_CODE_INVILD_PARAM, '非法请求'));
}
$app = self::$apps[$app_id];
$class_name = ucfirst($this->uri->segment(3));
if ($this->uri->segment(4)) {
$method = $this->request . "_" . $this->uri->segment(4);
} else {
$method = $this->request;
}
//app定制ct
$file_name = APPPATH . "controllers/wxapp/bobing/{$app}/{$class_name}.php";
//ct不存在
if (file_exists($file_name)) {
require_once $file_name;
} else {
//app定制ct不存在,使用公共ct
$file_name = APPPATH . "controllers/wxapp/bobing/{$class_name}.php";
if (file_exists($file_name)) {
require_once $file_name;
} else {
debug_log("[fail]" . __FUNCTION__ . ": file '{$file_name}' not exist; method:{$method}, app_id:" . $app_id, $this->log_file);
return $this->print_return($this->return_error(API_CODE_NONE, '非法请求'));
}
}
try {
$class = new $class_name($this->inputs, $app);
$result = $class->$method($version, $sversion);
if (!$result) {
throw new Exception('', ERR_SYS_FAIL);
}
return $this->print_return($result);
} catch (Exception $e) {
return $this->print_return($this->return_error($e->getCode(), $e->getMessage()));
}
}
/**
* 推广素材入口
*/
public function material()
{
define('WXAPP_ITEMS', 1);
//加载输入参数
$this->input_param();
$app_id = $this->input_param('app_id');
!$app_id && $app_id = $this->input_param('vipcard_id');
$version = $this->input_param('version');
$sversion = $this->input_param('sversion');
$this->log_file = get_class($this) . "_{$app_id}.log";
//应用ID为空
if (!$app_id) {
debug_log("[fail]" . __FUNCTION__ . ":app_id is null; uri_string:" . $this->uri->uri_string(), $this->log_file);
return $this->print_return($this->return_error(API_CODE_INVILD_PARAM, '请求丢失'));
}
//签名不正确
if (!$this->vaild_sign()) {
debug_log("[fail]" . __FUNCTION__ . ":sign check fail; uri_string:" . $this->uri->uri_string() . "; param:" . json_encode($this->inputs), $this->log_file);
return $this->print_return($this->return_error(API_CODE_INVILD_PARAM, '非法请求'));
}
$app = self::$apps[$app_id];
$class_name = ucfirst($this->uri->segment(3));
if ($this->uri->segment(4)) {
$method = $this->request . "_" . $this->uri->segment(4);
} else {
$method = $this->request;
}
//app定制ct
$file_name = APPPATH . "controllers/wxapp/material/{$app}/{$class_name}.php";
//ct不存在
if (file_exists($file_name)) {
require_once $file_name;
} else {
//app定制ct不存在,使用公共ct
$file_name = APPPATH . "controllers/wxapp/material/{$class_name}.php";
if (file_exists($file_name)) {
require_once $file_name;
} else {
debug_log("[fail]" . __FUNCTION__ . ": file '{$file_name}' not exist; method:{$method}, app_id:" . $app_id, $this->log_file);
return $this->print_return($this->return_error(API_CODE_NONE, '非法请求'));
}
}
try {
$class = new $class_name($this->inputs, $app);
$result = $class->$method($version, $sversion);
if (!$result) {
throw new Exception('', ERR_SYS_FAIL);
}
return $this->print_return($result);
} catch (Exception $e) {
return $this->print_return($this->return_error($e->getCode(), $e->getMessage()));
}
}
/**
* 测试签名(开发环境)
*/
public function test_sign(){
if(false === strpos($_SERVER['SERVER_NAME'], 'dev')){
exit('forbidden');
}
//加载输入参数
$this->input_param();
$param = $this->inputs;
$app_id = $param['app_id'];
!$app_id && $app_id = $param['vipcard_id'];
$sign = strtoupper($param['sign']);
$nonce_str = $param['nonce_str'];
unset($param['sign']);
if(!$app_id || !$sign || !$nonce_str){
exit(json_encode($param));
}
//根据biz_id 获取key
$app = self::$apps[$app_id];
$this->config->load('app', true, true);
$configs = $this->config->item('app');
$config = $configs[$app];
$key = $config['sign_key'];
//按字典序排序参数
ksort($param);
$buff = "";
foreach($param as $k => $v){
if(!is_array($v) && strlen($v) > 0){
// $buff .= $k . "=" . $v . "&";
$buff .= $k . "=" . ($v) . "&";
}
}
$buff = trim($buff, "&");
//在string后加入KEY
$buff = $buff . "&key=" . $key;
//MD5加密并转大写
$string = strtoupper(md5($buff));
// if($sign == $string){
// return true;
// }
$res = array('sign_input' => $sign, 'sign_output' => $string, 'buff' => $buff);
exit(json_encode($res));
}
/**
* 可能要被废弃
* @param $err_code
* @param string $err_info
* @return array
*/
function error_msg($err_code, $err_info = "")
{
if(!$err_info) {
$this->lang->load('error_lang','zh');
$err_info = $this->lang->line(self::$err_lang[$err_code], false);
}
return array('errCode' => $err_code, 'errMessage' => $err_info);
}
/**
* 打印返回值
* @param array $data
* @param bool $ifgzip
*/
private function print_return($data = array(), $ifgzip = false){
if(!isset($data['code'])){
$msg = $data['msg'] ? $data['msg'] : '';
$data = array('code' => 200, 'data' => $data, 'msg' => $msg);
}
if($ifgzip)
{
header('Content-Type: application/json');
header('Content-Encoding: gzip');
echo gzencode(json_encode($data, JSON_UNESCAPED_UNICODE), 6);
exit;
}
else
{
$result = json_encode($data, JSON_UNESCAPED_UNICODE);
echo $result;
exit;
}
}
/**
* 根据错误码输出
* @param $code
* @param string $msg
* @return array
*/
private function return_error($code, $msg = ''){
if(!$msg) {
$this->lang->load('error_lang','zh');
$msg = $this->lang->line(self::$err_lang[$code], false);
}
return array('code' => $code, 'msg' => $msg);
}
/**
* 匹配版本url
* @param $callback
* @param string $version
* @return mixed
*/
private function match_version($callback, $version = ''){
$version_group = self::$verison;
$ver_arr = $version_group[$callback];
$ck = $callback;
if(!$ver_arr){
foreach($version_group as $k => $arr){
if(0 === strpos($callback, $k)){
$ver_arr = $arr;
$ck = $k;
break;
}
}
}
if($ver_arr){
if(!$version){
$cv = reset($ver_arr);
} else {
foreach($ver_arr as $k => $v){
$cmp = $this->vercmp($version, $k);
if($cmp >= 0){
$cv = $v;
break;
}
}
}
}
if(isset($cv)){
$callback = str_replace($ck, $cv, $callback);
}
return $callback;
}
/**
* 比较版本号
* @param $ver1
* @param $ver2
* @return int 1:$ver1 > $ver2; -1:$ver1 < $ver2; 0:$ver1 == $ver2;
*/
private function vercmp($ver1, $ver2){
$v1_arr = explode('.', $ver1);
$v2_arr = explode('.', $ver2);
foreach($v1_arr as $k => $v){
$sub = $v - $v2_arr[$k];
if(0 != $sub){
return $sub > 0 ? 1 : -1;
}
}
return 0;
}
/**
* 获取参数
* @param string $key
* @return array|mixed
*/
private function input_param($key = ''){
if($key){
return $this->inputs[$key];
}
$request = $this->input->method();
switch($request){
case 'post':
case 'put':
case 'delete':
$input = json_decode(file_get_contents('php://input'), true);
break;
default:
$input = $this->input->get();
}
$this->request = $request;
$this->inputs = $input;
return $this->inputs;
}
/**
* 校验签名
* @return bool
*/
private function vaild_sign(){
$param = $this->inputs;
$app_id = $param['app_id'];
!$app_id && $app_id = $param['vipcard_id'];
$sign = strtoupper($param['sign']);
$nonce_str = $param['nonce_str'];
unset($param['sign']);
if(!$app_id || !$sign || !$nonce_str){
debug_log("[fail]". __FUNCTION__ . ": not app_id, sign, nonce_str", $this->log_file);
return false;
}
//根据biz_id 获取key
$app = self::$apps[$app_id];
$this->config->load('app', true, true);
$configs = $this->config->item('app');
$config = $configs[$app];
$key = $config['sign_key'];
//按字典序排序参数
ksort($param);
$buff = "";
foreach($param as $k => $v){
if(!is_array($v) && strlen($v) > 0){
// $buff .= $k . "=" . $v . "&";
$buff .= $k . "=" . ($v) . "&";
}
}
$buff = trim($buff, "&");
//在string后加入KEY
$buff = $buff . "&key=" . $key;
//MD5加密并转大写
$string = strtoupper(md5($buff));
// var_dump($string);
// var_dump($buff);
if($sign == $string){
return true;
}
// return true;
debug_log("[fail]". __FUNCTION__ . ": sign:{$sign}, check:{$string}, buff:{$buff}", $this->log_file);
return false;
}
/**
* 上传图片
* @throws Exception
*/
public function upimg(){
$app = $this->input->post('app');
$log_name = "{$app}_upimg.log";
try {
if(!$app){
throw new Exception('参数错误', API_CODE_INVILD_PARAM);
}
//接收图片
if (!$file = $_FILES['img']) {
throw new Exception('请选择图片', API_CODE_INVILD_PARAM);
}
if (!$file['tmp_name']) {//太大的图片上传,这个参数会变成空的
debug_log(json_encode($file), $log_name);
throw new Exception('参数错误', API_CODE_INVILD_PARAM);
}
debug_log("[info]". __FUNCTION__ . ": tmp_name:" . $file['tmp_name'] . ";size:" . filesize($file['tmp_name']), $log_name);
if (!file_exists(TEMP_PATH)){
$oldumask = umask(0);
mkdir(TEMP_PATH, 0777, true);
umask($oldumask);
}
$tmp = TEMP_PATH . md5($file['name'] . uniqid()) . substr($file['name'], strpos($file['name'], '.', strlen($file['name']) - 1));
move_uploaded_file($file['tmp_name'], $tmp);
debug_log("[info]". __FUNCTION__ . "tmp:$tmp;size:" . filesize($tmp), $log_name);
if (!filesize($tmp)) {
throw new Exception('图片有点问题,换个小的试试', API_CODE_INVILD_PARAM);
}
//上传图片到FTP
$res = $this->upload_img_qiniu($tmp,"{$app}/");
if (!$res) {
throw new Exception('上传失败', API_CODE_FAIL);
}
$data['full_url'] = build_qiniu_image_url($res['photo']);
$data['url'] = $res['photo'];
debug_log("[info]". __FUNCTION__ . "full_url:" . $data['full_url'], $log_name);
$this->print_return($data);
} catch (Exception $e) {
$message = $e->getMessage();
$this->print_return($this->return_error($e->getCode(), $message));
}
}
/**
* @param string $file 上传的文件
* @param string $path 要保存的目录
* @param string $filename 原始文件名称
* @throws Exception
* @return array
*/
private function upload_img_qiniu($file, $path = '',$filename = ''){
$phoId = md5(uniqid().mt_rand(0,10000).time());
$filename = $filename ? $filename : $file;
$ext_arr = explode(".", $filename);
$ext = count($ext_arr)>1?$ext_arr[count($ext_arr)-1]:'jpg';
if (is_uploaded_file($file)) {
//上传图片
$oriPath = TEMP_PATH . '/p_' . $phoId . '_ori.' . $ext;
move_uploaded_file($file, $oriPath);
} else {
$oriPath = $file;
}
$oriKey = 'p_' . $phoId . '.' . $ext;
// 上传到七牛后保存的文件名
$photo = $path .date('Ym') . "/" . $oriKey;
//上传图片到FTP
$this->load->library('qiniu');
$res= $this->qiniu->save($photo, file_get_contents($oriPath));
$img_size = getimagesize($oriPath);
$file_size = filesize($oriPath);
$size = "{$img_size[0]},{$img_size[1]},{$file_size}";
unlink($oriPath);
if ($res) {
$size = getimagesize($res['url']);
return array('photo' => $res['file'], 'size' => $size);
} else {
return array();
}
}
}