xiaowei 3 years ago
commit
76a59fd05e
  1. 1
      README.md
  2. 30
      accesstoken/index.php
  3. 53
      idapi.php
  4. 7
      idapi_Extension_points.php
  5. 36
      idapi_class_getuser.php
  6. 47
      idapi_com.php
  7. 18
      idapi_config.php
  8. 208
      idapi_function.php
  9. 29
      idapi_logout.php
  10. 52
      refreshtoken/index.php
  11. 30
      sid/index.php
  12. 69
      token/index.php
  13. 77
      userinfo/index.php

1
README.md

@ -0,0 +1 @@
文档:前后分离项目用

30
accesstoken/index.php

@ -0,0 +1,30 @@
<?php
require '../idapi_config.php';
require '../idapi_function.php';
header("Content-Type: application/json; charset=utf-8");
$getDeAuth = id_CKdecrypt($_COOKIE["fr_id_auth"]);
//print_r($getDeAuth);
if($getDeAuth['access_token']){
echo '{
"code": 200,
"message": "success",
"data": [
{
"fr_access_token": "'.$getDeAuth['access_token'].'",
"fr_expires_time": "'.$getDeAuth['expires_time'].'"
}
],
"status": 0
}';
}else{
echo '{
"code": 200,
"message": "-1",
"data": [],
"status": 0
}';
}
?>

53
idapi.php

@ -0,0 +1,53 @@
<?php
/**
* 同步登录应用接口
* 2020.01 by xiaowei
*/
require 'idapi_config.php';
require 'idapi_function.php';
if(time() - $_GET['time'] > 3600) {
exit('Authracation has expiried');
}
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
if($_GET["type"]=='login' && $_GET["code"]){
$id_user = id_CKdecrypt($_GET["code"]);
$id_userinfo = $id_user['client'];
if(!$id_user['expires_time']){
exit('err');
}
set_idcookie('fr_id_auth',$_GET['code'],IDCookieOptions());
set_idcookie('fr_id_appname',$_GET['appname'],IDCookieOptions());
set_idcookie('fr_access_token',$id_user['access_token'],IDCookieOptions());
set_idcookie('fr_uid',$id_userinfo['uid'],IDCookieOptions());
set_idcookie('fr_appid',$id_userinfo['appid'],IDCookieOptions());
set_idcookie('fr_expires_time',$id_user['expires_time'],IDCookieOptions());
// 登录数字平台接口
digitLogin($_GET["code"]);
}
if($_GET["type"]=='logout'){
set_idcookie('fr_access_token','',IDCookieOptions(0));
set_idcookie('fr_id_auth','',IDCookieOptions(0));
set_idcookie('fr_id_appname','',IDCookieOptions(0));
set_idcookie('fr_id_userinfo','',IDCookieOptions(0));
set_idcookie('fr_id_addexist_time','',IDCookieOptions(0));
set_idcookie('fr_expires_time','',IDCookieOptions(0));
}
if($_GET["type"]=='userinfo'){
$id_user = id_CKdecrypt($_COOKIE["fr_id_auth"]);
$id_userinfo = $id_user['client'];
id_user_info($id_userinfo['uid'],$id_userinfo['appid'],$id_user['access_token']);
del_access_token();
}
echo 'idapi 3.1';
?>

7
idapi_Extension_points.php

@ -0,0 +1,7 @@
<?php
/**
* 扩展功能
* by xiaowei
*/

36
idapi_class_getuser.php

@ -0,0 +1,36 @@
<?php
/**
* 解密并返回同步的用户信息
* 2020.02 by xiaowei
*/
class idapi_getuser{
public function aes_decrypt($enc){
$raw = hex2bin($enc);
$cipherMethod = 'aes-128-ctr';
$ivlen = openssl_cipher_iv_length($cipherMethod);
$iv = substr($raw, 0, $ivlen);
$raw = substr($raw, $ivlen);
$res = openssl_decrypt($raw, $cipherMethod, API_KEY, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
return $res;
}
public function getAuth(){
if(!$_COOKIE["fr_id_auth"]){return false;}
$ck_auth = $this->aes_decrypt($_COOKIE["fr_id_auth"]);
$jsonarr = json_decode($ck_auth,true);
return $jsonarr;
}
public function getUserinfo(){
if($_COOKIE['fr_id_auth']){
if(!$_COOKIE["fr_id_userinfo"]){return false;}
$ck_auth = $this->aes_decrypt($_COOKIE["fr_id_userinfo"]);
$jsonarr = json_decode($ck_auth,true);
return $jsonarr;
}else{
return false;
}
}
}

47
idapi_com.php

@ -0,0 +1,47 @@
<?php
/**
* 同步登录应用接口
* 2020.01.31 by xiaowei
*/
if(!defined('IDAPI')) {
exit('Access Denied');
}
require 'idapi_config.php';
require 'idapi_function.php';
require 'idapi_class_getuser.php';
//实例化授权用户
$idNewGetuser = new idapi_getuser();
$id_ckauth = $idNewGetuser->getAuth();
$id_ckauthinfo = $id_ckauth['client'];
$id_getUserinfo = $idNewGetuser->getUserinfo();
//获取资料
if($_COOKIE['fr_id_auth'] && !$_COOKIE['fr_id_userinfo']){
id_user_info($id_ckauthinfo['uid'],$id_ckauthinfo['appid'],$id_ckauth['access_token']);
}elseif($_COOKIE['fr_id_userinfo'] && !$id_getUserinfo['data']['uid']){
id_refresh_token();
id_user_info($id_ckauthinfo['uid'],$id_ckauthinfo['appid'],$id_ckauth['access_token']);
}
//access_token时效
if($id_ckauthinfo['uid'] && time() > $id_ckauth['expires_time']){
id_refresh_token();
}
//每天第一次访问统计
if($_COOKIE["fr_id_auth"] && $_COOKIE["fr_id_addexist_time"] != date('Ymd')){
$addexist_data = ['uid' => $id_ckauthinfo['uid'],'device' => $_COOKIE["fr_id_appname"]];
$addexist_header = ['authentication:'.base64_encode($id_ckauthinfo['appid'].'.'.$id_ckauth['access_token'].'.'.$id_ckauthinfo['uid'])];
$re_addexist = CallInterface(API_URL.'/v1/user/addexist/','POST',$addexist_data,$addexist_header);
$addexist_jsonarr = json_decode($re_addexist,true);
if($addexist_jsonarr['code']=='201' || $addexist_jsonarr['code']=='200'){
setcookie('fr_id_addexist_time',date('Ymd'),time()+3600*24*365,'/');
}
}
?>

18
idapi_config.php

@ -0,0 +1,18 @@
<?php
/**
* @API_URL 接口
* @API_KEY 密钥
* 2020.01 by xiaowei
*/
//define('API_URL', 'http://testapi.shequ.fanruan.com');
//define('API_URL', 'https://api.shequ.fanruan.com');
//define('ID_URL', 'https://id.fanruan.com');
define('API_KEY', 'i7hP48WAcuTrmxfN');
define('API_URL', 'http://testapi');
define('ID_URL', 'https://id');
define('DIGIT_API_URL', 'https://testdpapi.fanruan.com');
?>

208
idapi_function.php

@ -0,0 +1,208 @@
<?php
/**
* 应用方法
* 2020.02 by xiaowei
*/
function id_aes_encrypt($plaintext, $key){
$cipherMethod = 'aes-128-ctr';
$ivlen = openssl_cipher_iv_length($cipherMethod);
$iv = openssl_random_pseudo_bytes(16);
$ciphertext = openssl_encrypt($plaintext, $cipherMethod, $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
$res = $iv . $ciphertext;
$code = bin2hex($res);
return $code;
}
function id_aes_decrypt($enc, $key){
$raw = hex2bin($enc);
$cipherMethod = 'aes-128-ctr';
$ivlen = openssl_cipher_iv_length($cipherMethod);
$iv = substr($raw, 0, $ivlen);
$raw = substr($raw, $ivlen);
$res = openssl_decrypt($raw, $cipherMethod, $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
return $res;
}
function id_CKdecrypt($enc){
$ck_auth = id_aes_decrypt($enc, API_KEY);
$jsonarr = json_decode($ck_auth,true);
return $jsonarr;
}
//登录数字平台接口
function digitLogin($code='')
{
if($code){
$id_ckuserinfo = $id_ckuser['client'];
$re_login = CallInterface(DIGIT_API_URL.'/v1/user/login?code='.$code,'GET');
//print_r($re_login);
$jsonarr = json_decode($re_login,true);
if($jsonarr['success']===true){
$data = $jsonarr['data'];
$base64_data = base64_encode($data['client']['appid'].'.'.$data['access_token'].'.'.$data['client']['uid']);
//print_r($base64_data);
setcookie('digit_authentication',$base64_data,time()+3600*24*14,'/');
setcookie('digit_accessToken',$data['access_token'],time()+3600*24*3,'/');
setcookie('digit_refreshToken',$data['refresh_token'],time()+3600*24*14,'/');
setcookie('digit_expiresTime',$data['expires_time'],time()+3600*24*3,'/');
}
}
}
function CallInterface($URL,$type,$params='',$arr_header=''){
$ch = curl_init();
if($arr_header){
curl_setopt($ch, CURLOPT_HTTPHEADER, $arr_header);
}
curl_setopt ($ch, CURLOPT_URL, $URL);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
switch ($type){
case "GET" : curl_setopt($ch, CURLOPT_HTTPGET, true);break;
case "POST": curl_setopt($ch, CURLOPT_POST,true);
curl_setopt($ch, CURLOPT_POSTFIELDS,$params);break;
case "PUT" : curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_POSTFIELDS,$params);break;
case "DELETE":curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_POSTFIELDS,$params);break;
}
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$file_contents = curl_exec($ch);
curl_close($ch);
return $file_contents;
}
//刷新token
function id_refresh_token()
{
$id_ckuser = id_CKdecrypt($_COOKIE["fr_id_auth"]);
$id_ckuserinfo = $id_ckuser['client'];
$data = '&appid='.$id_ckuserinfo['appid'].'&uid='.$id_ckuserinfo['uid'].'&refresh_token='.$id_ckuser['refresh_token'];
$re_login = CallInterface(API_URL.'/v1/token/refresh/'.$data,'GET');
//print_r($re_login);
$jsonarr = json_decode($re_login,true);
if($jsonarr['message']=='success'){
$new_json = json_encode($jsonarr['data'],JSON_UNESCAPED_UNICODE);
$u_data = id_aes_encrypt($new_json, API_KEY);
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
setcookie('fr_id_auth',$u_data,time()+3600*24*14,'/');
}else{
setcookie('fr_id_auth','',0,'/');
}
}
//刷新token 前后分离用
function setRefreshToken()
{
$id_ckuser = id_CKdecrypt($_COOKIE["fr_id_auth"]);
$id_ckuserinfo = $id_ckuser['client'];
$data = '&appid='.$id_ckuserinfo['appid'].'&uid='.$id_ckuserinfo['uid'].'&refresh_token='.$id_ckuser['refresh_token'];
$re_login = CallInterface(API_URL.'/v1/token/refresh/'.$data,'GET');
$jsonarr = json_decode($re_login,true);
if($jsonarr['message']=='success'){
$new_json = json_encode($jsonarr['data'],JSON_UNESCAPED_UNICODE);
$u_data = id_aes_encrypt($new_json, API_KEY);
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
setcookie('fr_access_token',$jsonarr['data']['access_token'],time()+3600*24*365,'/');
setcookie('fr_uid',$jsonarr['data']['client']['uid'],time()+3600*24*365,'/');
setcookie('fr_appid',$jsonarr['data']['client']['appid'],time()+3600*24*365,'/');
setcookie('fr_id_auth',$u_data,time()+3600*24*14,'/');
}else{
setcookie('fr_id_auth','',0,'/');
}
}
//生成用户资料
function id_user_info($uid,$appid,$access_token){
$au_header = ['authentication:'.base64_encode($appid.'.'.$access_token.'.'.$uid)];
$re_api = CallInterface(API_URL.'/v1/user/getUserinfo/?uid='.$uid,'GET','',$au_header);
$u_data = id_aes_encrypt($re_api, API_KEY);
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
set_idcookie('fr_id_userinfo',$u_data,IDCookieOptions());
}
//写入access_token
function set_access_token($code){
$id_ckauthinfo = $code['client'];
set_idcookie('fr_access_token',$code['access_token'],IDCookieOptions());
set_idcookie('fr_uid',$id_ckauthinfo['uid'],IDCookieOptions());
set_idcookie('fr_appid',$id_ckauthinfo['appid'],IDCookieOptions());
}
//删除access_token
function del_access_token(){
set_idcookie('access_token','',IDCookieOptions(0));
set_idcookie('uid','',IDCookieOptions(0));
set_idcookie('appid','',IDCookieOptions(0));
}
//属性参数
function IDCookieOptions($exptime=1){
$Options = [
'expires' => $exptime ? time()+3600*24*14:0,
'domain' => '',
'httponly' => false,
'samesite' => 'None',
'secure' => true,
'path' => '/'
];
return $Options;
}
//idapi 写cookie方式
function set_idcookie($name, $value, array $options)
{
setcookie($name,$value,$options['expires'],'/');
/*if(id_ChromeVer()<79){
setcookie($name,$value,$options['expires'],'/');
}else{
$header = 'Set-Cookie:';
$header .= rawurlencode($name) . '=' . rawurlencode($value) . ';';
if (isset($options['expires'])) {
$header .= 'expires=' . \gmdate('D, d-M-Y H:i:s T', $options['expires']) . ';';
}
if (isset($options['expires'])) {
$header .= 'Max-Age=' . max(0, (int) ($options['expires'] - time())) . ';';
}
if (!empty($options['path'])) {
$header .= 'path=' . $options['path']. ';';
}
if (!empty($options['domain'])) {
$header .= 'domain=' . rawurlencode($options['domain']) . ';';
}
if (!empty($options['secure'])) {
$header .= 'Secure;';
}
if (!empty($options['httponly'])) {
$header .= 'HttpOnly;';
}
if (!empty($options['samesite'])) {
$header .= 'SameSite=' . rawurlencode($options['samesite']);
}
header($header, false);
} */
}
//Chrome版本
function id_ChromeVer(){
if (empty($_SERVER['HTTP_USER_AGENT'])){
return 'unknow';
}
$agent= $_SERVER['HTTP_USER_AGENT'];
if (preg_match('/Chrome\/(\d+)\..*/i', $agent, $regs)){
return $regs[1];
}
else{
return 'unknow';
}
}
?>

29
idapi_logout.php

@ -0,0 +1,29 @@
<?php
/**
* 同步登录应用接口
* 2020.01.31 by xiaowei
*/
error_reporting(0);
set_magic_quotes_runtime(0);
echo '<script type="text/javascript" src="https://frhelp/idapi/idapi.php?time='.time().'&type=logout"></script>';
/*require 'idapi_config.php';
require 'idapi_function.php';
//获取应用列表
$idaaps_curl_get = CallInterface(ID_URL.'/idapi/idapps.php','GET');
$apps_jsonarr = json_decode($idaaps_curl_get,true);
//遍历各应用退出
foreach($apps_jsonarr as $appid => $app) {
if($app['isopen']==1){
echo '<script type="text/javascript" src="'.$app['url'].'/idapi/idapi.php?time='.time().'&type=logout"></script>';
}
}
*/
?>

52
refreshtoken/index.php

@ -0,0 +1,52 @@
<?php
require '../idapi_config.php';
require '../idapi_function.php';
header("Content-Type: application/json; charset=utf-8");
$get_cookie = $_COOKIE["fr_id_auth"];
if($get_cookie){
$id_ckuser = id_CKdecrypt($get_cookie);
$id_ckuserinfo = $id_ckuser['client'];
$data = '&appid='.$id_ckuserinfo['appid'].'&uid='.$id_ckuserinfo['uid'].'&refresh_token='.$id_ckuser['refresh_token'];
$re_login = CallInterface(API_URL.'/v1/token/refresh/'.$data,'GET');
$jsonarr = json_decode($re_login,true);
if($jsonarr['code']==200){
$new_json = json_encode($jsonarr['data'],JSON_UNESCAPED_UNICODE);
$u_data = id_aes_encrypt($new_json, API_KEY);
setcookie('fr_id_auth',$u_data,time()+3600*24*14,'/');
$str['code']=200;
$str['message']='success';
$str['data']['fr_access_token'] = $jsonarr['data']['access_token'];
$str['data']['fr_appid'] = $jsonarr['data']['client']['appid'];
$str['data']['fr_uid'] = $jsonarr['data']['client']['uid'];
$str['data']['fr_expires_time'] = $jsonarr['data']['expires_time'];
$return_json = json_encode($str);
echo $return_json;
}else{
$str['code']=401;
$str['message']='-1';
$str['data']=[];
$return_json = json_encode($str);
echo $return_json;
}
}else{
$str['code']=401;
$str['message']='-1';
$str['data']=[];
$return_json = json_encode($str);
echo $return_json;
}
?>

30
sid/index.php

@ -0,0 +1,30 @@
<?php
require '../idapi_config.php';
require '../idapi_function.php';
require '../idapi_class_getuser.php';
header("Content-Type: application/json; charset=utf-8");
// sid
$getSid = htmlspecialchars($_GET['sid']);
if($getSid){
$re_getcode = json_decode(CallInterface(API_URL.'/v1/user/getUserCode?sid='.$getSid,'GET'),true);
if($re_getcode['status']===1){
$fr_id_auth = $re_getcode['data']['code'];
$sid_ckauth = id_CKdecrypt($fr_id_auth);
$sid_ckauthinfo = $sid_ckauth['client'];
setcookie('fr_access_token',$sid_ckauth['access_token'],time()+3600*24*365,'/');
setcookie('fr_uid',$sid_ckauthinfo['uid'],time()+3600*24*365,'/');
setcookie('fr_appid',$sid_ckauthinfo['appid'],time()+3600*24*365,'/');
setcookie('fr_id_auth',$fr_id_auth,time()+3600*24*365,'/');
}
else{
$return_json = json_encode($re_getcode);
echo $return_json;
}
}
?>

69
token/index.php

@ -0,0 +1,69 @@
<?php
/**
* 自动返回有效access_token
**/
require '../idapi_config.php';
require '../idapi_function.php';
require '../idapi_class_getuser.php';
header("Content-Type: application/json; charset=utf-8");
$get_cookie = $_COOKIE["fr_id_auth"];
if(!$get_cookie){
$str['code']=200;
$str['message']='-1';
$str['data']=[];
$return_json = json_encode($str);
echo $return_json;
}
//实例化授权用户
$idNewGetuser = new idapi_getuser();
$id_ckauth = $idNewGetuser->getAuth();
$id_ckauthinfo = $id_ckauth['client'];
//刷新access_token
if($id_ckauthinfo['uid'] && time() > $id_ckauth['expires_time']){
$id_ckuser = id_CKdecrypt($get_cookie);
$id_ckuserinfo = $id_ckuser['client'];
$data = '&appid='.$id_ckuserinfo['appid'].'&uid='.$id_ckuserinfo['uid'].'&refresh_token='.$id_ckuser['refresh_token'];
$re_login = CallInterface(API_URL.'/v1/token/refresh/'.$data,'GET');
$jsonarr = json_decode($re_login,true);
if($jsonarr['message']=='success'){
$new_json = json_encode($jsonarr['data'],JSON_UNESCAPED_UNICODE);
$u_data = id_aes_encrypt($new_json, API_KEY);
header('P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"');
setcookie('fr_id_auth',$u_data,time()+3600*24*14,'/');
}else{
setcookie('fr_id_auth','',0,'/');
}
$str['code']=200;
$str['message']='success';
$str['data']['access_token'] = $jsonarr['data']['access_token'];
$str['data']['appid'] = $jsonarr['data']['client']['appid'];
$str['data']['uid'] = $jsonarr['data']['client']['uid'];
$str['data']['ref'] = 1;
$return_json = json_encode($str);
echo $return_json;
}else{
$run_json = array (
'access_token' => $id_ckauth['access_token'],
'appid' => $id_ckauthinfo['appid'],
'uid' => $id_ckauth['client']['uid'],
);
echo json_encode($run_json);
}
?>

77
userinfo/index.php

@ -0,0 +1,77 @@
<?php
require '../idapi_config.php';
require '../idapi_function.php';
require '../idapi_class_getuser.php';
header("Content-Type: application/json; charset=utf-8");
//实例化授权用户
$idNewGetuser = new idapi_getuser();
$id_ckauth = $idNewGetuser->getAuth();// 读取cookie中的fr_id_auth
$id_ckauthinfo = $id_ckauth['client'];
$id_getUserinfo = $idNewGetuser->getUserinfo();
//刷新access_token
/*if($id_ckauthinfo['uid'] && time() > $id_ckauth['expires_time']){
setRefreshToken();
}*/
//获取资料
if($_COOKIE['fr_id_auth'] && !$_COOKIE['fr_id_userinfo']){
id_user_info($id_ckauthinfo['uid'],$id_ckauthinfo['appid'],$id_ckauth['access_token']);
}elseif($_COOKIE['fr_id_userinfo'] && !$id_getUserinfo['data']['uid']){
//这里的token会导致无法直接写入:fr_id_auth
id_refresh_token();
id_user_info($id_ckauthinfo['uid'],$id_ckauthinfo['appid'],$id_ckauth['access_token']);
}
//每天第一次访问统计
if($_COOKIE["fr_id_auth"] && $_COOKIE["fr_id_addexist_time"] != date('Ymd')){
$addexist_data = ['uid' => $id_ckauthinfo['uid'],'device' => $_COOKIE["fr_id_appname"]];
$addexist_header = ['authentication:'.base64_encode($id_ckauthinfo['appid'].'.'.$id_ckauth['access_token'].'.'.$id_ckauthinfo['uid'])];
$re_addexist = CallInterface(API_URL.'/v1/user/addexist/','POST',$addexist_data,$addexist_header);
$addexist_jsonarr = json_decode($re_addexist,true);
if($addexist_jsonarr['code']=='201' || $addexist_jsonarr['code']=='200'){
setcookie('fr_id_addexist_time',date('Ymd'),time()+3600*24*365,'/');
}
}
// 无token更新
if(!$_COOKIE["fr_access_token"]){
setcookie('fr_access_token',$id_ckauth['access_token'],time()+3600*24*365,'/');
setcookie('fr_uid',$id_ckauthinfo['uid'],time()+3600*24*365,'/');
setcookie('fr_appid',$id_ckauthinfo['appid'],time()+3600*24*365,'/');
}
// 无auth退出
if(!$_COOKIE["fr_id_auth"]){
setcookie('fr_access_token','',0,'/');
setcookie('fr_uid','',0,'/');
setcookie('fr_appid','',0,'/');
}
$userInfo = $id_getUserinfo['data'];
$run_json=array(
'code' => 200,
'message' => 'success',
'data' => array(
'avatar' => 'https://bbs.fanruan.com/uc_server/avatar.php?uid='.$id_ckauthinfo['uid'],
'fr_uid' => $id_ckauthinfo['uid'],
'username' => $userInfo['username'],
'regdate' => $userInfo['regdate'],
'position' => $userInfo['position'],
'location' => '',
'signature' => $userInfo['signature'],
'fr_expires_time'=> $id_ckauth['expires_time'],
)
);
echo json_encode($run_json);
?>
Loading…
Cancel
Save