HEX
Server: nginx/1.22.1
System: Linux VM-16-9-centos 3.10.0-1160.99.1.el7.x86_64 #1 SMP Wed Sep 13 14:19:20 UTC 2023 x86_64
User: www (1001)
PHP: 7.3.31
Disabled: passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv
Upload Files
File: /www/wwwroot/softfox.com.cn/wp-content/plugins/wpjam-basic/includes/class-wpjam-api.php
<?php
class WPJAM_Route extends WPJAM_Register{
	public function callback($wp){
		remove_action('template_redirect',	'redirect_canonical');

		$this->action	= $wp->query_vars['action'] ?? '';
		$callback		= $this->callback;

		if(!$callback && $this->model && method_exists($this->model, 'redirect')){
			$callback	= [$this->model, 'redirect'];
		}

		if($callback && is_callable($callback)){
			return call_user_func($callback, $this->action, $this->name);
		}
	}

	public function filter_template($template){
		$file	= $this->action ? $this->action.'.php' : 'index.php';
		$file	= STYLESHEETPATH.'/template/'.$this->name.'/'.$file;
		$file	= apply_filters('wpjam_template', $file, $this->name, $this->action);

		return is_file($file) ? $file : $template;
	}

	public static function filter_determine_current_user($user_id){
		if(empty($user_id)){
			$wpjam_user	= wpjam_get_current_user();

			if($wpjam_user && !empty($wpjam_user['user_id'])){
				return $wpjam_user['user_id'];
			}
		}

		return $user_id;
	}

	public static function filter_current_commenter($commenter){
		if(empty($commenter['comment_author_email'])){
			$wpjam_user	= wpjam_get_current_user();

			if($wpjam_user && !empty($wpjam_user['user_email'])){
				$commenter['comment_author_email']	= $wpjam_user['user_email'];
				$commenter['comment_author']		= $wpjam_user['nickname'];
			}
		}

		return $commenter;
	}

	public static function filter_pre_avatar_data($args, $id_or_email){
		$user_id 	= 0;
		$avatarurl	= '';
		$email		= '';

		if(is_object($id_or_email) && isset($id_or_email->comment_ID)){
			$id_or_email	= get_comment($id_or_email);
		}

		if(is_numeric($id_or_email)){
			$user_id	= $id_or_email;
		}elseif(is_string($id_or_email)){
			$email		= $id_or_email;
		}elseif($id_or_email instanceof WP_User){
			$user_id	= $id_or_email->ID;
		}elseif($id_or_email instanceof WP_Post){
			$user_id	= $id_or_email->post_author;
		}elseif($id_or_email instanceof WP_Comment){
			$user_id	= $id_or_email->user_id;
			$email		= $id_or_email->comment_author_email;
			$avatarurl	= get_comment_meta($id_or_email->comment_ID, 'avatarurl', true);
		}

		if(!$avatarurl && $user_id){
			$avatarurl	= get_user_meta($user_id, 'avatarurl', true);
		}

		if($avatarurl){
			$url	= wpjam_get_thumbnail($avatarurl, [$args['width'], $args['height']]);

			return array_merge($args, ['found_avatar'=>true,	'url'=>$url,]);
		}

		if($user_id){
			$args['user_id']	= $user_id;
		}

		if($email){
			$args['email']		= $email;
		}

		return $args;
	}

	public static function filter_query_vars($query_vars){
		return array_merge($query_vars, ['module', 'action', 'term_id']);
	}

	public static function on_parse_request($wp){
		$module	= $wp->query_vars['module'] ?? null;

		if($module){
			$object	= self::get($module) ?: new self($module);

			$object->callback($wp);

			add_filter('template_include',	[$object, 'filter_template']);
		}
	}

	public static function on_loaded(){
		foreach(self::get_active('rewrite_rule') as $rule){
			$rules	= is_array(current($rule)) ? $rule : [$rule];

			array_walk($rules, function($rule){
				if(is_array($rule)){
					$rule[0]	= $GLOBALS['wp_rewrite']->root.$rule[0];

					add_rewrite_rule(...$rule);
				}
			});
		}
	}
}

class WPJAM_JSON extends WPJAM_Register{
	private $response;

	public function response(){
		$this->response	= apply_filters('wpjam_pre_json', [], $this->args, $this->name);
		$this->response	= wpjam_throw_if_error($this->response);
		$this->response	= array_merge($this->response, [
			'errcode'		=> 0,
			'current_user'	=> wpjam_try('wpjam_get_current_user', $this->pull('auth'))
		]);

		if($_SERVER['REQUEST_METHOD'] != 'POST' && !str_ends_with($this->name, '.config')){
			$this->response	+= wp_array_slice_assoc($this, ['page_title', 'share_title', 'share_image']);
		}

		if($this->modules){
			$modules	= $this->modules;
			$modules	= is_callable($modules) ? call_user_func($modules, $this->name) : $modules;
			$modules	= wp_is_numeric_array($modules) ? $modules : [$modules];

			$this->walk($modules, 'merge');
		}else{
			$result		= null;
			$callback	= $this->pull('callback');

			if($callback){
				if(is_callable($callback)){
					$result	= wpjam_try($callback, $this->args, $this->name);
				}
			}elseif($this->template){
				if(is_file($this->template)){
					$result	= include $this->template;
				}
			}else{
				$result	= $this->args;
			}

			$this->merge($result, 'result');
		}

		$response	= apply_filters('wpjam_json', $this->response, $this->args, $this->name);

		if($_SERVER['REQUEST_METHOD'] != 'POST' && !str_ends_with($this->name, '.config')){
			foreach(['page_title', 'share_title']  as $title_key){
				if(empty($response[$title_key])){
					$response[$title_key]	= html_entity_decode(wp_get_document_title());
				}
			}

			if(!empty($response['share_image'])){
				$response['share_image']	= wpjam_get_thumbnail($response['share_image'], '500x400');
			}
		}

		return $response;
	}

	protected function merge($result, $type='module'){
		if($type !== 'result'){
			$result	= $this->parse_module($result);
		}

		wpjam_throw_if_error($result);

		if(is_array($result)){
			$attr	= array_filter(wp_array_slice_assoc($this->response, ['page_title', 'share_title', 'share_image']));

			$this->response	= array_merge($this->response, array_except($result, array_keys($attr)));
		}
	}

	public static function parse_module($module){
		$args	= array_get($module, 'args', []);
		$args	= is_array($args) ? $args : wpjam_parse_shortcode_attr(stripslashes_deep($args), 'module');
		$parser	= array_get($module, 'parser');

		if(!$parser){
			$type	= array_get($module, 'type');
			$parser	= wpjam_get_json_module_parser($type);
		}

		return $parser ? wpjam_call($parser, $args) : $args;
	}

	public static function redirect($action){
		if(!wpjam_doing_debug()){
			header('X-Content-Type-Options: nosniff');

			rest_send_cors_headers(false); 

			if('OPTIONS' === $_SERVER['REQUEST_METHOD']){
				status_header(403);
				exit;
			}

			$type	= wp_is_jsonp_request() ? 'javascript' : 'json';

			@header('Content-Type: application/'.$type.'; charset='.get_option('blog_charset'));
		}

		if(!str_starts_with($action, 'mag.')){
			return;
		}

		$name	= wpjam_remove_prefix($action, 'mag.');
		$name	= wpjam_remove_prefix($name, 'mag.');	// 兼容
		$name	= str_replace('/', '.', $name);
		$name	= apply_filters('wpjam_json_name', $name);

		wpjam_set_current_var('json', $name);

		$current_user	= wpjam_get_current_user();

		if($current_user && !empty($current_user['user_id'])){
			wp_set_current_user($current_user['user_id']);
		}

		do_action('wpjam_api', $name);

		$object	= self::get($name);

		if($object){
			if(is_wp_error($object)){
				self::send($object);
			}

			if($object->defaults){
				add_filter('wpjam_parameter_default', [$object, 'filter_parameter_default'], 10, 2);
			}

			self::send(wpjam_call([$object, 'response']));
		}else{
			wp_die('接口未定义!', 'invalid_api');
		}
	}

	public static function send($data=[], $status_code=null){
		$data	= wpjam_parse_error($data);
		$result	= self::encode($data);

		if(!headers_sent() && !wpjam_doing_debug()){
			if(!is_null($status_code)){
				status_header($status_code);
			}

			if(wp_is_jsonp_request()){
				$result	= '/**/' . $_GET['_jsonp'] . '(' . $result . ')';

				$type	= 'javascript';
			}else{
				$type	= 'json';
			}

			@header('Content-Type: application/'.$type.'; charset='.get_option('blog_charset'));
		}

		echo $result;

		exit;
	}

	public static function encode($data){
		return wp_json_encode($data, JSON_UNESCAPED_UNICODE);
	}

	public static function decode($json, $assoc=true){
		$json	= wpjam_strip_control_characters($json);

		if(!$json){
			return new WP_Error('json_decode_error', 'JSON 内容不能为空!');
		}

		$result	= json_decode($json, $assoc);

		if(is_null($result)){
			$result	= json_decode(stripslashes($json), $assoc);

			if(is_null($result)){
				if(wpjam_doing_debug()){
					print_r(json_last_error());
					print_r(json_last_error_msg());
				}
				trigger_error('json_decode_error '. json_last_error_msg()."\n".var_export($json,true));
				return new WP_Error('json_decode_error', json_last_error_msg());
			}
		}

		return $result;
	}

	public static function get_current($output='name'){
		$name	= wpjam_get_current_var('json');

		return $output == 'object' ? self::get($json) : $name;
	}

	public static function get_rewrite_rule(){
		return [
			['api/([^/]+)/(.*?)\.json?$',	['module'=>'json', 'action'=>'mag.$matches[1].$matches[2]'], 'top'],
			['api/([^/]+)\.json?$', 		'index.php?module=json&action=$matches[1]', 'top'],
		];
	}

	public static function get_config($key){
		if($key == 'defaults'){
			return [
				'post.list'		=> ['modules'=>['WPJAM_Posts', 'json_modules_callback']],
				'post.calendar'	=> ['modules'=>['WPJAM_Posts', 'json_modules_callback']],
				'post.get'		=> ['modules'=>['WPJAM_Posts', 'json_modules_callback']],
				'media.upload'	=> ['modules'=>['type'=>'media', 'args'=>['media'=>'media']]],
				'site.config'	=> ['modules'=>['type'=>'config']],
			];
		}
	}

	public static function __callStatic($method, $args){
		if(in_array($method, ['parse_post_list_module', 'parse_post_get_module'])){
			$args	= $args[0] ?? [];
			$action	= str_replace(['parse_post_', '_module'], '', $method);

			return self::parse_module(['type'=>'post_type', 'args'=>array_merge($args, ['action'=>$action])]);
		}
	}
}

class WPJAM_Error extends WPJAM_Model{
	public static function get_handler(){
		$option		= 'wpjam_errors';
		$handler	= wpjam_get_handler($option);

		return $handler ?: wpjam_register_handler([
			'option_name'	=> $option,
			'primary_key'	=> 'errcode',
			'primary_title'	=> '代码',
		]);
	}

	public static function filter($data){
		$error	= self::get($data['errcode']);

		if($error){
			$data['errmsg']	= $error['errmsg'];

			if(!empty($error['show_modal'])){
				if(!empty($error['modal']['title']) && !empty($error['modal']['content'])){
					$data['modal']	= $error['modal'];
				}
			}
		}else{
			if(empty($data['errmsg'])){
				$item	= self::get_setting($data['errcode']);

				if($item){
					$data['errmsg']	= $item['message'];

					if($item['modal']){
						$data['modal']	= $item['modal'];
					}
				}
			}
		}

		return $data;
	}

	public static function parse($data){
		if(is_wp_error($data)){
			$errdata	= $data->get_error_data();
			$data		= [
				'errcode'	=> $data->get_error_code(),
				'errmsg'	=> $data->get_error_message(),
			];

			if($errdata){
				$errdata	= is_array($errdata) ? $errdata : ['errdata'=>$errdata];
				$data 		= $data + $errdata;
			}
		}else{
			if($data === true){
				return ['errcode'=>0];
			}elseif($data === false || is_null($data)){
				return ['errcode'=>'-1', 'errmsg'=>'系统数据错误或者回调函数返回错误'];
			}elseif(is_array($data)){
				if(!$data || !wp_is_numeric_array($data)){
					$data	= wp_parse_args($data, ['errcode'=>0]);
				}
			}
		}

		if(!empty($data['errcode'])){
			$data	= self::filter($data);
		}

		return $data;
	}

	public static function add_setting($code, $message, $modal=[]){
		$object = wpjam_get_items_object('error');

		if(!$object->get_items()){
			add_action('wp_error_added', [self::class, 'on_wp_error_added'], 10, 4);
		}

		$object->add_item($code, ['message'=>$message, 'modal'=>$modal]);
	}

	public static function get_setting($code){
		$object = wpjam_get_items_object('error');
		$item	= $object->get_item($code);

		if($item && $item['message']){
			return $object->get_item($code);
		}
	}

	public static function convert($message, $title='', $code=0){
		$modal	= [];

		if(is_wp_error($message)){
			$wp_error	= $message;
		}else{
			if($code){
				if($title){
					$modal	= ['title'=>$title, 'message'=>$message];
				}
			}else{
				$code	= $title;

				if(!$code){
					if(is_scalar($message) && self::get_setting($message)){
						$code		= $message;
						$message	= '';
					}else{
						$code		= 'error';
					}
				}
			}
		}

		$wp_error	= new WP_Error($code, $message);

		if($modal){
			$wp_error->add_data(['modal'=>$modal]);
		}

		return $wp_error;
	}

	public static function wp_die_handler($message, $title='', $code=0){
		wpjam_send_json(self::convert($message, $title, $code));
	}

	public static function on_wp_error_added($code, $message, $data, $wp_error){
		if($code && (!$message || is_array($message)) && count($wp_error->get_error_messages($code)) <= 1){
			$item	= self::get_setting($code);

			if(is_array($code)){
				trigger_error(var_export($code, true));
			}

			if($item){
				if($item['modal']){
					$data	= is_array($data) ? $data : [];
					$data	= array_merge($data, ['modal'=>$item['modal']]);
				}

				if(is_callable($item['message'])){
					$message	= call_user_func($item['message'], $message, $code);
				}else{
					$message	= is_array($message) ? sprintf($item['message'], ...$message) : $item['message'];
				}
			}elseif(str_starts_with($code, 'invalid_')){
				$msg	= is_array($message) ? implode($message) : '';
				$name	= wpjam_remove_prefix($code, 'invalid_');

				if($name == 'parameter'){
					$message	= $msg ? '无效的参数:'.$msg.'。' : '参数错误。';
				}elseif($name == 'callback'){
					$message	= '无效的回调函数'.($msg ? ':' : '').$msg.'。';
				}else{
					$map	= [
						'id'			=> ' ID',
						'appsecret'		=> '密钥',
						'post'			=> '文章',
						'term'			=> '分类',
						'user_id'		=> '用户 ID',
						'user'			=> '用户',
						'comment_type'	=> '评论类型',
						'comment_id'	=> '评论 ID',
						'comment'		=> '评论',
						'type'			=> '类型',
						'signup_type'	=> '登录方式',
						'email'			=> '邮箱地址',
						'data_type'		=> '数据类型',
						'submit_button'	=> '提交按钮',
						'qrcode'		=> '二维码',
					];

					$message	= '无效的'.$msg.($map[$name] ?? ' '.ucwords($name));
				}
			}elseif(str_starts_with($code, 'illegal_')){
				$name	= wpjam_remove_prefix($code, 'illegal_');
				$map	= [
					'access_token'	=> 'Access Token ',
					'refresh_token'	=> 'Refresh Token ',
					'verify_code'	=> '验证码',
				];

				$message	= ($map[$name] ?? ucwords($name).' ').'无效或已过期。';
			}elseif(str_ends_with($code, '_occupied')){
				$name	= wpjam_remove_postfix($code, '_occupied');
				$map	= [
					'phone'		=> '手机号码',
					'email'		=> '邮箱地址',
					'nickname'	=> '昵称',
				];

				$message	= ($map[$name] ?? ucwords($name).' ').'已被其他账号使用。';
			}

			if($message){
				$wp_error->remove($code);
				$wp_error->add($code, $message, $data);
			}
		}
	}

	public static function filter_wp_die_handler(){
		return [self::class, 'wp_die_handler'];
	}

	public static function callback($args, $code){
		if($code == 'undefined_method'){
			if(count($args) >= 2){
				return sprintf('「%s」%s未定义', ...$args);
			}elseif(count($args) == 1){
				return sprintf('%s方法未定义', ...$args);
			}
		}elseif($code == 'quota_exceeded'){
			if(count($args) >= 2){
				return sprintf('%s超过上限:%s', ...$args);
			}elseif(count($args) == 1){
				return sprintf('%s超过上限', ...$args);
			}else{
				return '超过上限';
			}
		}
	}
}

class WPJAM_Exception extends Exception{
	private $wp_error	= null;

	public function __construct($errmsg, $errcode=null, Throwable $previous=null){
		if(is_wp_error($errmsg)){
			$wp_error	= $errmsg;
			$errcode	= $wp_error->get_error_code();
		}else{
			$errcode	= $errcode ?: 'error';
			$wp_error	= new WP_Error($errcode, $errmsg);
		}

		$this->wp_error	= $wp_error;

		$errmsg		= $wp_error->get_error_message();
		$errcode	= is_numeric($errcode) ? (int)$errcode : 1;

		parent::__construct($errmsg, $errcode, $previous);
	}

	public function get_wp_error(){
		return $this->wp_error;
	}

	public function get_error_code(){
		return $this->wp_error->get_error_code();
	}

	public function get_error_message(){
		return $this->wp_error->get_error_message();
	}
}

class WPJAM_Parameter extends WPJAM_Singleton{
	protected $_input;

	public function get_value($name, $args=null){
		if(!is_null($args)){
			$this->set_args($args);
		}

		$value	= $this->get_by_name($name);
		$value	= $value ?? $this->get_fallback($name);
		$result	= $this->validate_value($value, $name);

		if(is_wp_error($result)){
			return $this->send === false ? $result : wpjam_send_json($result);
		}

		return $this->sanitize_value($value);
	}

	protected function get_by_name($name){
		$method	= strtoupper($this->method) ?: 'GET';

		if($method == 'POST'){
			$data	= $_POST;
		}elseif($method == 'REQUEST'){
			$data	= $_REQUEST;
		}else{
			$data	= $_GET;
		}

		if($name){
			if(isset($data[$name])){
				return wp_unslash($data[$name]);
			}else{
				if($_POST || $method == 'GET'){
					return null;
				}
			}
		}else{
			if($data || in_array($method, ['GET', 'REQUEST'])){
				return wp_unslash($data);
			}
		}

		if(is_null($this->_input)){
			$input	= file_get_contents('php://input');
			$input	= is_string($input) ? @wpjam_json_decode($input) : $input;

			$this->_input	= is_array($input) ? $input : [];
		}

		$data	= $this->_input;

		return $name ? ($data[$name] ?? null) : $data;
	}

	protected function get_fallback($name){
		if($this->fallback){
			foreach(array_filter((array)$this->fallback) as $fallback){
				$value	= $this->get_by_name($fallback);

				if(!is_null($value)){
					return $value;
				}
			}
		}

		return $this->default ?? apply_filters('wpjam_parameter_default', null, $name);	// 内部底层接口,不建议直接使用
	}

	protected function validate_value($value, $name=''){
		if($this->required){
			if(is_null($value)){
				return new WP_Error('missing_parameter', '缺少参数:'.$name);
			}
		}

		if($this->length){
			if(is_numeric($this->length) && mb_strlen($value) < $this->length){
				return new WP_Error('invalid_parameter', [$name]);
			}
		}

		$result	= parent::validate_value($value);

		if($result === false){
			return new WP_Error('invalid_parameter', [$name]);
		}elseif(is_wp_error($result)){
			return $result;
		}

		return true;
	}

	protected function sanitize_value($value){
		if($this->type == 'int' && !is_null($value)){
			return (int)$value;
		}

		return parent::sanitize_value($value);
	}
}

class WPJAM_Data_Parameter extends WPJAM_Parameter{
	protected $_data;

	protected function get_by_name($name){
		if($name && isset($_GET[$name])){
			return wp_unslash($_GET[$name]);
		}

		if(is_null($this->_data)){
			$this->_data	= $this->sandbox(function(){
				$args		= ['sanitize_callback'=>'wp_parse_args', 'default'=>[]];
				$data		= wpjam_get_post_parameter('data', $args);
				$defaults	= wpjam_get_post_parameter('defaults', $args);

				return merge_deep($defaults, $data);
			});
		}

		if($name){
			return $this->_data[$name] ?? null;
		}

		return $this->_data;
	}
}

class WPJAM_Request extends WPJAM_Singleton{
	public function request($url, $args=null, $err_args=[], &$headers=null){
		if(!is_null($args)){
			$this->args	= $args;
		}

		$this->args	= wp_parse_args($this->args, [
			'body'			=> [],
			'headers'		=> [],
			'sslverify'		=> false,
			'blocking'		=> true,	// 如果不需要立刻知道结果,可以设置为 false
			'stream'		=> false,	// 如果是保存远程的文件,这里需要设置为 true
			'filename'		=> null,	// 设置保存下来文件的路径和名字
			// 'headers'	=> ['Accept-Encoding'=>'gzip;'],	//使用压缩传输数据
			// 'compress'	=> false,
		]);

		if($this->method){
			$this->method	= strtoupper($this->method);
		}else{
			$this->method	= $this->body ? 'POST' : 'GET';
		}

		if($this->method == 'GET'){
			$response	= wp_remote_get($url, $this->args);
		}elseif($this->method == 'FILE'){
			$response	= (new WP_Http_Curl())->request($url, wp_parse_args($this->args, [
				'method'			=> $this->body ? 'POST' : 'GET',
				'sslcertificates'	=> ABSPATH.WPINC.'/certificates/ca-bundle.crt',
				'user-agent'		=> 'WordPress',
				'decompress'		=> true,
			]));
		}else{
			$encode_required	= $this->pull('json_encode_required', $this->pull('need_json_encode'));

			if($encode_required){
				if(is_array($this->body)){
					$this->body	= $this->body ?: new stdClass;
					$this->body	= wpjam_json_encode($this->body);
				}

				if($this->method == 'POST' && empty($this->headers['Content-Type'])){
					$this->headers	+= ['Content-Type'=>'application/json'];
				}
			}

			$response	= wp_remote_request($url, $this->args);
		}

		if(wpjam_doing_debug()){
			print_r($response);
		}

		if(is_wp_error($response)){
			trigger_error($url."\n".$response->get_error_code().' : '.$response->get_error_message()."\n".var_export($this->body,true));
			return $response;
		}

		$errcode	= $response['response']['code'] ?? 0;

		if($errcode && $errcode != 200){
			return new WP_Error($errcode, '远程服务器错误:'.$errcode.' - '.$response['response']['message']);
		}

		if(!$this->blocking){
			return true;
		}

		$this->url	= $url;
		$body		= $response['body'];
		$headers	= $response['headers'];

		return $this->decode($body, $headers, $err_args);
	}

	public function decode($body, $headers, $err_args=[]){
		$disposition	= $headers['content-disposition'] ?? '';
		$content_type	= $headers['content-type'] ?? '';
		$content_type	= is_array($content_type) ? implode(' ', $content_type) : $content_type;

		if($disposition && strpos($disposition, 'attachment;') !== false){
			if(!$this->stream){
				if(!$content_type){
					$content_type	= finfo_buffer(finfo_open(), $body, FILEINFO_MIME_TYPE);
				}

				return 'data:'.$content_type.';base64, '.base64_encode($body);
			}

			return $body;
		}else{
			if($content_type && strpos($content_type, '/json')){
				$decode_required	= true;
			}else{
				$decode_required	= $this->pull('json_decode_required', $this->pull('need_json_decode', ($this->stream ? false : true)));
			}

			if($decode_required){
				if($this->stream){
					$body	= file_get_contents($this->filename);
				}

				if(empty($body)){
					trigger_error(var_export($body, true).var_export($headers, true));
				}else{
					$body	= wpjam_json_decode($body);

					if(is_wp_error($body)){
						return $body;
					}
				}
			}
		}

		$err_args	= wp_parse_args($err_args,  [
			'errcode'	=>'errcode',
			'errmsg'	=>'errmsg',
			'detail'	=>'detail',
			'success'	=>'0',
		]);

		if(isset($body[$err_args['errcode']]) && $body[$err_args['errcode']] != $err_args['success']){
			$errcode	= array_pull($body, $err_args['errcode']);
			$errmsg		= array_pull($body, $err_args['errmsg']);
			$detail		= array_pull($body, $err_args['detail']);
			$detail		= is_null($detail) ? array_filter($body) : $detail;

			if(apply_filters('wpjam_http_response_error_debug', true, $errcode, $errmsg, $detail)){
				trigger_error($this->url."\n".$errcode.' : '.$errmsg."\n".($detail ? var_export($detail,true)."\n" : '').var_export($this->body,true));
			}

			return new WP_Error($errcode, $errmsg, $detail);
		}

		return $body;
	}
}

class WPJAM_API{
	public static function __callStatic($method, $args){
		$function	= 'wpjam_'.$method;

		if(function_exists($function)){
			return call_user_func($function, ...$args);
		}
	}

	public static function get_apis(){	// 兼容
		return WPJAM_JSON::get_registereds();
	}
}