国际版测试代码

This commit is contained in:
tiansf 2025-04-19 17:24:07 +08:00
parent c9296ecb2a
commit 075de75020
1040 changed files with 113294 additions and 315 deletions

View File

@ -141,17 +141,17 @@ class Base extends Controller{
$length = strlen($token); $length = strlen($token);
if ($length < 10 ) { if ($length < 10 ) {
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败字符串长度小于10', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败字符串长度小于10', 'token_log');
return false; return ['state'=>false,'language'=>null];
} }
}else{ }else{
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败不是字符串', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败不是字符串', 'token_log');
return false; return ['state'=>false,'language'=>null];
} }
$user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->field('id,login_time')->find(); $user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->field('id,login_time,language')->find();
if(!$user_login){ if(!$user_login){
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败未找到用户token', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败未找到用户token', 'token_log');
return false; return ['state'=>false,'language'=>null];
} }
// 创建 DateTime 对象来表示指定的日期和时间 // 创建 DateTime 对象来表示指定的日期和时间
@ -174,16 +174,16 @@ class Base extends Controller{
if ($daysDifference > $this->token_time) { if ($daysDifference > $this->token_time) {
// echo "超过 {$specifiedDays} 天"; // echo "超过 {$specifiedDays} 天";
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败原因没有找到该token,或该token已经超过30天', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败原因没有找到该token,或该token已经超过30天', 'token_log');
return false; return ['state'=>false,'language'=>$user_login['language']];
} else { } else {
// echo "未超过 {$specifiedDays} 天"; // echo "未超过 {$specifiedDays} 天";
$user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->update(['login_time'=>date('Y-m-d H:i:s')]); $user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->update(['login_time'=>date('Y-m-d H:i:s')]);
if($user_login){ if($user_login){
Log::record('用户尝试更新token时间token' . $token.',记录成功,最新的时间为'.date('Y-m-d H:i:s'), 'token_log'); Log::record('用户尝试更新token时间token' . $token.',记录成功,最新的时间为'.date('Y-m-d H:i:s'), 'token_log');
return true; return ['state'=>true,'language'=>$user_login['language']];
}else{ }else{
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败数据库更新时间未成功', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败数据库更新时间未成功', 'token_log');
return true; return ['state'=>true,'language'=>$user_login['language']];
} }
} }
@ -709,6 +709,8 @@ class Base extends Controller{
public function ceshiyong($aa = 4,$gd = 0.2){ public function ceshiyong($aa = 4,$gd = 0.2){
$token = 'cd3f27cf4c4002170ea7bceeb723ac91'; $token = 'cd3f27cf4c4002170ea7bceeb723ac91';

View File

@ -88,7 +88,7 @@ class Card extends Base{
// 详细卡片信息 // 详细卡片信息
// $data = ['id'=>'2'] // $data = ['id'=>'2']
public function card_data_detailed($data=['aud_id'=>'38']){ public function card_data_detailed($data=['aud_id'=>'144']){
try { try {
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
@ -100,9 +100,10 @@ class Card extends Base{
if(!$this->verify_data_is_ok($data['aud_id'],'intnum')){ if(!$this->verify_data_is_ok($data['aud_id'],'intnum')){
return $this->msg(10005); return $this->msg(10005);
} }
// $return_data;
$return_data = $this->get_user_body_data($data); $return_data = $this->get_user_body_data($data);
// 成功 // $language_data = new Language();
$this->record_api_log($data, null, $return_data); // $return_data = $language_data->handling_languages_from_multiple_countries('en', $return_data->getData());
return $return_data; return $return_data;
} catch (\Exception $e) { } catch (\Exception $e) {
// 捕获异常 // 捕获异常
@ -591,9 +592,11 @@ class Card extends Base{
// 处理返回数据 // 处理返回数据
$result_end = $this->processing_return_data_new($result[0]); $result_end = $this->processing_return_data_new($result[0]);
$cardparts = new Cardparts; $cardparts = new Cardparts;
$result_end['gender'] = $result[0]['gender']; $result_end['gender'] = $result[0]['gender'];
$result_end['record_time'] = $result[0]['record_time']; $result_end['record_time'] = $result[0]['record_time'];
$result_end['score'] = $result_end['score']; $result_end['score'] = $result_end['score'];
$result_end['body_type'] = $result_end['body_type']; $result_end['body_type'] = $result_end['body_type'];
$result_end = $cardparts->conversion_interval($result_end); $result_end = $cardparts->conversion_interval($result_end);
@ -605,6 +608,7 @@ class Card extends Base{
'bmi'=>$result[0]['bmi'] 'bmi'=>$result[0]['bmi']
], ],
]); ]);
// 只有含有阻抗的记录才有数据参考 // 只有含有阻抗的记录才有数据参考
if($result[0]['record_type'] == 'by_device_adc'){ if($result[0]['record_type'] == 'by_device_adc'){
if(count($result_end['cplist']['nutritionlist']) <= 0){ if(count($result_end['cplist']['nutritionlist']) <= 0){
@ -628,7 +632,7 @@ class Card extends Base{
'initial_weight'=>$result[0]['initial_weight']>0?$result[0]['initial_weight']:0, 'initial_weight'=>$result[0]['initial_weight']>0?$result[0]['initial_weight']:0,
'initial_date'=>$result[0]['initial_date']!=null?$result[0]['initial_date']:0, 'initial_date'=>$result[0]['initial_date']!=null?$result[0]['initial_date']:0,
]); ]);
// dump($result_end);
if(count($result_end['top_list'][2]['list']) <= 0){ if(count($result_end['top_list'][2]['list']) <= 0){
// 这是16岁以上人群 // 这是16岁以上人群
$data = [ $data = [
@ -639,15 +643,20 @@ class Card extends Base{
]; ];
$temporary_arr_bmi_list = $this->card_bmi_evaluation($data,true); $temporary_arr_bmi_list = $this->card_bmi_evaluation($data,true);
// dump($temporary_arr_bmi_list);
$temporary_arr_bmi_list = $temporary_arr_bmi_list->getData(); $temporary_arr_bmi_list = $temporary_arr_bmi_list->getData();
// dump($temporary_arr_bmi_list);
// die;
if($temporary_arr_bmi_list['code'] == 0){ if($temporary_arr_bmi_list['code'] == 0){
$result_end['top_list'][2]['standard'] = $temporary_arr_bmi_list['data']['bmilevel']; $result_end['top_list'][2]['standard'] = $temporary_arr_bmi_list['data']['bmilevel'];
$result_end['top_list'][2]['color'] = $temporary_arr_bmi_list['data']['bmilevelcolor']; $result_end['top_list'][2]['color'] = $temporary_arr_bmi_list['data']['bmilevelcolor'];
$result_end['top_list'][2]['list'] = $temporary_arr_bmi_list['data']['bmilevellist']; $result_end['top_list'][2]['list'] = $temporary_arr_bmi_list['data']['bmilevellist'];
$result_end['top_list'][2]['offset'] = $temporary_arr_bmi_list['data']['offset']; $result_end['top_list'][2]['offset'] = $temporary_arr_bmi_list['data']['offset'];
} }
// dump($result_end);
// die;
} }
// 加入曲线板块底部的减肥计划数据end // 加入曲线板块底部的减肥计划数据end
// 添加头围数据如果有的话start // 添加头围数据如果有的话start
if($head_circumference !== false && $this->calculate_age($result[0]['birthday']) < 3){ if($head_circumference !== false && $this->calculate_age($result[0]['birthday']) < 3){
@ -664,7 +673,7 @@ class Card extends Base{
'color'=>'', 'color'=>'',
'list'=>$head_circumference['list2'], 'list'=>$head_circumference['list2'],
'key_name'=>'head_circumference', 'key_name'=>'head_circumference',
'desc'=>'头围是指绕头部一周的最大长度,头围的大小与的发育密切相关', 'desc'=>'头围是指绕头部一周的最大长度,头围的大小与的发育密切相关',
'offset'=>$offset 'offset'=>$offset
]); ]);
} }
@ -782,6 +791,7 @@ class Card extends Base{
$min_key = array_search($min_value,$temporary_arr); $min_key = array_search($min_value,$temporary_arr);
$type_num = $this->card_body_level[$min_key]['value']; $type_num = $this->card_body_level[$min_key]['value'];
$temporary_arr2 = Db::table($this->card_use_db_name['6'])->where(['Type'=>$type_num,'Level'=>$min_value,'IsDeleted'=>0])->field('Nutrition,Sport')->find(); $temporary_arr2 = Db::table($this->card_use_db_name['6'])->where(['Type'=>$type_num,'Level'=>$min_value,'IsDeleted'=>0])->field('Nutrition,Sport')->find();
// dump($temporary_arr2);
array_push($result['nutritionlist'],$temporary_arr2['Nutrition']); array_push($result['nutritionlist'],$temporary_arr2['Nutrition']);
array_push($result['sportlist'],$temporary_arr2['Sport']); array_push($result['sportlist'],$temporary_arr2['Sport']);
// $result['nutritionlist'] = $temporary_arr2['Nutrition']; // $result['nutritionlist'] = $temporary_arr2['Nutrition'];

View File

@ -191,10 +191,10 @@ class Cardparts extends Base{
'bottom_list'=>[], 'bottom_list'=>[],
]; ];
// die; // die;
$date_temporary = new \DateTime($temporary_arr['record_time']); // $date_temporary = new \DateTime($temporary_arr['record_time']);
// 使用 format 方法来指定新的日期和时间格式 // 使用 format 方法来指定新的日期和时间格式
$temporary_arr['record_time'] = $date_temporary->format('Y年m月d日 H:i:s'); // $temporary_arr['record_time'] = $date_temporary->format('Y年m月d日 H:i:s');
// 处理格式(顶部) // 处理格式(顶部)
foreach ($this->parameter_aggregate_top as $key => $value) { foreach ($this->parameter_aggregate_top as $key => $value) {
$data[$key]['key_name'] = $key; $data[$key]['key_name'] = $key;

View File

@ -4,6 +4,8 @@ namespace app\app\controller;
use think\Db; use think\Db;
use \think\Validate; use \think\Validate;
use app\app\controller\Language;
// use ip2region\Ip2Region;
class Index extends Base{ class Index extends Base{
protected $moren_gufen_diqu = '北京,北京'; protected $moren_gufen_diqu = '北京,北京';
@ -60,6 +62,39 @@ class Index extends Base{
['min'=>'3','max'=>'16','value'=>'儿童'], ['min'=>'3','max'=>'16','value'=>'儿童'],
['min'=>'16','max'=>'500','value'=>'成人'] ['min'=>'16','max'=>'500','value'=>'成人']
]; ];
protected $language_country = [
'en' => 'English', // 英语(通用)★
'zh-Hans' => '中文', // 中文(简体)★
// 'es' => 'Español', // 西班牙语(西班牙)★
// 'fr' => 'Français', // 法语(法国)★
// 'pt' => 'Português', // 葡萄牙语(巴西)★
// 'ar' => 'العربية', // 阿拉伯语(标准)★
// 'ru' => 'Русский', // 俄语(俄罗斯)★
// 'de' => 'Deutsch', // 德语(德国)★
// 'ja' => '日本語', // 日语
// 'ko' => '한국어', // 韩语
// 'it' => 'Italiano', // 意大利语
// 'nl' => 'Nederlands', // 荷兰语
// 'hi' => 'हिन्दी', // 印地语
// 'tr' => 'Türkçe', // 土耳其语
// 'vi' => 'Tiếng Việt', // 越南语
// 'th' => 'ไทย', // 泰语
// 'pl' => 'Polski', // 波兰语
// 'sv' => 'Svenska', // 瑞典语
// 'fi' => 'Suomi', // 芬兰语
// 'da' => 'Dansk', // 丹麦语
// 'no' => 'Norsk', // 挪威语
// 'he' => 'עברית', // 希伯来语
// 'id' => 'Bahasa Indonesia', // 印尼语
// 'ms' => 'Bahasa Melayu', // 马来语
// 'cs' => 'Čeština', // 捷克语
// 'hu' => 'Magyar', // 匈牙利语
// 'el' => 'Ελληνικά', // 希腊语
// 'ro' => 'Română', // 罗马尼亚语
// 'sk' => 'Slovenčina', // 斯洛伐克语
// 'uk' => 'Українська', // 乌克兰语
];
################################################################个人资料卡################################################################ ################################################################个人资料卡################################################################
@ -67,8 +102,35 @@ class Index extends Base{
################################################################个人资料卡################################################################ ################################################################个人资料卡################################################################
// 检测版本及判断是否登录失效 // 检测版本及判断是否登录失效
public function login_invalid_version($data = ['token'=>'']){ public function login_invalid_version($data = ['token'=>'2d4ea9b3f44b169ddf64b2f3d2725ceb']){
try { try {
// 获取客户端IP
$ip = request()->ip();
// 调用IP识别方法
$region = $this->getIpInfo($ip);
// 解析地区信息
$regionParts = explode('|', $region);
$country = $regionParts[0] ?? '';
// 判断国家是否在支持的语言列表中
$language = '';
if ($country && $country !== '0') {
$languageMap = [
'中国' => 'zh-Hans',
'美国' => 'en',
'英国' => 'en',
'西班牙' => 'es',
'法国' => 'fr',
'葡萄牙' => 'pt',
'阿拉伯联合酋长国' => 'ar',
'俄罗斯' => 'ru',
'德国' => 'de'
];
$language = $languageMap[$country] ?? '';
}
// 检查语言是否在支持列表中
$language_all = new Language();
$isSupportedLanguage = array_key_exists($language, $language_all->getSupportedLanguages());
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
$data = input('post.'); $data = input('post.');
@ -84,12 +146,13 @@ class Index extends Base{
$version = ''; $version = '';
$url = ''; $url = '';
} }
if($this->token_time_validate($data['token']) === false){ $user_token_state = $this->token_time_validate($data['token']);
$this->record_api_log($data, null, ['code'=>-1,'msg'=>'未登录',['version'=>$version,'url'=>$url]]);
return $this->msg(-1,'未登录',['version'=>$version,'url'=>$url]); $language_data = $this->pd_language($user_token_state['language'],$isSupportedLanguage,$language);
if($user_token_state['state'] === false){
return $this->msg(-1,'未登录',['version'=>$version,'url'=>$url,'language'=>$language_data,'language_arr'=>$this->language_country]);
}else{ }else{
$this->record_api_log($data, null, ['code'=>0,'msg'=>'success',['version'=>$version,'url'=>$url]]); return $this->msg(['version'=>$version,'url'=>$url,'language'=>$language_data,'language_arr'=>$this->language_country]);
return $this->msg(['version'=>$version,'url'=>$url]);
} }
} catch (\Exception $e) { } catch (\Exception $e) {
@ -100,12 +163,62 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
return $this->msg(99999); return $this->msg(99999);
} }
} }
// 添加IP信息获取方法
protected function getIpInfo($ip) {
// 默认IP
$ip = $ip ?: request()->ip();
try {
$ip2region = new \Ip2Region();
$info = $ip2region->memorySearch($ip);
// 返回国家信息
return $info['region'] ?: '未知';
} catch (\Exception $e) {
return '未知';
}
}
public function set_language_country($data = ['token'=>'caadd1be045a65f30b92aa805f1de54a','language'=>'zh']){
try {
// 你的业务逻辑
if(count(input('post.')) > 0){
$data = input('post.');
}
if(!array_key_exists('token', $data) || !array_key_exists('language', $data)){
return $this->msg(10001);
}
if(!array_key_exists($data['language'],$this->language_country)){
return $this->msg(10007);
}
$result = Db::table($this->index_use_db_name['7'])->where(['token'=>$data['token']])->update(['language'=>$data['language']]);
if($result){
return $this->msg([]);
}else{
return $this->msg(10002);
}
} catch (\Exception $e) {
$logContent["flie"] = $e->getFile();
$logContent["line"] = $e->getLine();
$logContent['all_content'] = "异常信息:\n";
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null);
return $this->msg(99999);
}
}
// 创建用户 // 创建用户
public function create_user_data($data = ['aan_id'=>1,'height'=>'152.3','weight'=>'35.4','nickname'=>'钮祜禄测试1','birthday'=>'2019-04-20','gender'=>1,'grade'=>'grade_s_3','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'57bd45e3a963b372ea2d873e4bd8d1f8']){ public function create_user_data($data = ['aan_id'=>1,'height'=>'152.3','weight'=>'35.4','nickname'=>'钮祜禄测试1','birthday'=>'2019-04-20','gender'=>1,'grade'=>'grade_s_3','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'57bd45e3a963b372ea2d873e4bd8d1f8']){
@ -143,14 +256,12 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
return $this->msg(99999); return $this->msg(99999);
} }
} }
// 修改用户 // 修改用户
public function update_user_data($data = ['id'=>66,'nickname'=>'王小二','birthday'=>'2019-01-01','gender'=>1,'grade'=>'二年级','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function update_user_data($data = ['id'=>66,'nickname'=>'王小二','birthday'=>'2019-01-01','gender'=>1,'grade'=>'二年级','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'0dafb98a10995c98b5a33b7d59d986ca']){
@ -187,6 +298,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -230,6 +342,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -238,7 +351,6 @@ class Index extends Base{
} }
// 获取账号下用户列表 // 获取账号下用户列表
// $type 1获取列表2获取详细信息 // $type 1获取列表2获取详细信息
public function get_user_card_list($data = ['aan_id'=>4,'type'=>2,'token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function get_user_card_list($data = ['aan_id'=>4,'type'=>2,'token'=>'0dafb98a10995c98b5a33b7d59d986ca']){
@ -298,6 +410,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -307,7 +420,7 @@ class Index extends Base{
} }
// 获取指定用户详细信息 // 获取指定用户详细信息
public function get_user_data_information($data = ['aud_id'=>113]){ public function get_user_data_information($data = ['aud_id'=>61]){
// try { // try {
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
@ -449,6 +562,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -498,6 +612,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -535,6 +650,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -583,6 +699,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -1025,6 +1142,20 @@ class Index extends Base{
return $parameter; return $parameter;
} }
public function pd_language($user_language,$isSupportedLanguage,$language){
if(!$user_language){
if($isSupportedLanguage){
$result = $language;
}else{
$result = 'zh-Hans'; // 默认语言为中文
}
}else{
$result = $user_language;
}
return $result;
}

View File

@ -0,0 +1,211 @@
<?php
namespace app\app\controller;
class Language extends Base
{
// 支持的语言列表
protected $supportedLanguages = [
'en' => 'English',
'zh-Hans' => 'Chinese',
'es' => 'Spanish',
'fr' => 'French',
'pt' => 'Portuguese',
'ar' => 'Arabic',
'ru' => 'Russian',
'de' => 'German'
];
// 语言映射表
protected $languageMap = [
'en' => [
'操作成功' => 'Success',
'体重' => 'Weight',
'身高' => 'Height',
'消瘦' => 'Slim',
'正常' => 'Normal',
'偏重' => 'Overweight',
'肥胖' => 'Obesity',
'反映和衡量一个人健康状况的重要标志之一' => "One of the important indicators reflecting and measuring a person's health status",
'人体纵向部分的长度,源于人体的纵向生长,受遗传因素的影响较大' => "The length of the longitudinal part of the human body is derived from its longitudinal growth and is greatly influenced by genetic factors",
'BMI是身体质量指数,是目前国际上常用的衡量人体胖瘦程度以及是否健康的一个标准。' => "BMI is the body mass index, which is currently a commonly used international standard for measuring the degree of body fat, thinness, and health.",
'公斤' => "kg",
'CM' => "cm",
'年' => "-",
'月' => "-",
'日' => "",
'身体得分' => "Physical score",
'分' => "score",
'身体类型' => "body type",
'健美肌肉型' => "Bodybuilding muscle type",
'低' => "Low",
'偏低' => "Slightly low",
'标准' => "Standard",
'偏高' => "Slightly high",
'高' => "High",
'矮' => "Short",
'偏矮' => "Slightly short",
'脂肪率' => "Body Fat Percentage",
'体脂率是指身体成分中,脂肪组织所占的比率。测量体脂率比单纯的只测量体重更能反映我们身体的脂肪水平(肥胖程度)。' => "Body fat percentage refers to the proportion of fat tissue in body composition. Measuring it provides a more accurate reflection of body fat levels (degree of obesity) than weight measurement alone.",
'脂肪量' => "Fat Mass",
'人体脂肪的重量' => "Body Fat Weight",
'肌肉率' => "Muscle Percentage",
'优' => "Excellent",
'根据人体肌肉总量和人体体重、身高等相结合得到的人体的一个比例值,这个值的范围决定一个人的身体健康状况以及力量的多少。' => "Muscle percentage is a ratio derived from total muscle mass, body weight, height, etc. Its range determines a person's health status and strength level.",
'肌肉量' => "Muscle Mass",
'不足' => "Insufficient",
'肌肉量=实际体重*肌肉率' => "Muscle Mass = Actual Weight × Muscle Percentage",
'水分' => "Body Water",
'指人体内水分比例。' => "Refers to the proportion of water in the human body.",
'蛋白量' => "Protein Mass",
'蛋白量=实际体重*蛋白率' => "Protein Mass = Actual Weight × Protein Percentage",
'骨重' => "Bone Mass",
'单位体积内,骨组织、骨矿物质(钙、磷等)和骨基质(骨胶原、蛋白率、无机盐等等)含量,骨量代表它们骨骼健康的情况。' => "Bone mass refers to the content of bone tissue, minerals (calcium, phosphorus, etc.), and bone matrix (collagen, proteins, inorganic salts, etc.) per unit volume, reflecting skeletal health.",
'蛋白率' => "Protein Percentage",
'人体内蛋白率含量。' => "The proportion of protein in the human body.",
'基础代谢' => "Basal Metabolic Rate (BMR)",
'指人体在清醒而又极端安静的状态下,不受肌肉活动、环境温度、食物及精神紧张等影响时的能量代谢率' => "The energy expenditure rate when the body is awake, completely at rest, and unaffected by muscle activity, ambient temperature, food intake, or mental stress.",
'内脏指数' => "Visceral Fat Index",
'警惕' => "Caution",
'危险' => "Danger",
'内脏脂肪指数' => "Visceral Fat Level",
'皮下脂肪' => "Subcutaneous Fat",
'皮下脂脂肪就是贮存于皮下的脂肪组织人体的脂肪大约有2/3贮存在皮下组织' => "Subcutaneous fat refers to adipose tissue stored under the skin. About two-thirds of body fat is stored subcutaneously.",
'肥胖等级' => "Obesity Level",
'体重不足' => "Underweight",
'肥胖的程度,表现实际体重与理想体重的差距。肥胖等级是判定肥胖症的一个指标。' => "Obesity level indicates the disparity between actual and ideal weight, serving as a diagnostic criterion for obesity.",
'孩子可能存在营养不良对于处在生长发育期的孩子而言蛋白质、碳水化合物、维生素和矿物质这四类营养素非常重要。建议补充足够的蛋白质、锌、钙、铁、维生素D、赖氨酸等营养。建议补充含鸡内金山楂膏健脾开胃类药食同源食物。' => "The child may be malnourished: For growing children, protein, carbohydrates, vitamins, and minerals are critical. Ensure adequate intake of protein, zinc, calcium, iron, vitamin D, lysine, etc. Consider herbal foods like chicken gizzard-hawthorn paste to improve digestion and appetite.",
'孩子可能存在营养不良对于处在生长发育期的孩子而言最有利于长高的营养素是蛋白质、碳水化合物、维生素和矿物质四类。建议补充足够的蛋白质、锌、铁、钙、维生素D、赖氨酸等营养。' => "The child may be malnourished: For children in their growth and development stage, the most beneficial nutrients for height growth are proteins, carbohydrates, vitamins, and minerals. It is recommended to ensure adequate intake of nutrients such as protein, zinc, iron, calcium, vitamin D, and lysine.",
'坚持适当、科学的跳跃运动能够科学地增加学生体重,能够改善学 生体重过低的情况;同时运动会消耗能量并加速胃肠蠕动,这会使孩子的食欲大开,再配合均衡的营养有利于孩子增重。' => "Moderate, scientifically designed jumping exercises can help underweight students gain weight by boosting energy expenditure and gastrointestinal motility, thereby increasing appetite. Combined with balanced nutrition, this supports healthy weight gain.",
'3-7岁的孩子骑两轮车、拍踢球、打篮球、游泳、爬山每天高强度运动不超过30分钟。' => "Ages 37: Bicycling, ball games, basketball, swimming, hiking. Limit high-intensity exercise to 30 minutes daily.",
'该年龄段睡眠时间建议9-11小时' => "Recommended sleep duration for this age group: 911 hours.",
'孩子开始对于赞赏、鼓励、认同和肯定有需求,而且此阶段父亲在孩子的性格塑造、情绪控制以及责任感培养方面扮演着重要的角色,必须告诉孩子什么事应该做、什么事不应该做,并经常性地给孩子一些积极地暗示。例如,可以时常向孩子表达“我会一直在你身边,不要害怕””我对你的进步都看在眼里等类似的话语。' => "Children begin to crave praise, encouragement, and validation. Fathers play a key role in shaping character, emotional regulation, and responsibility during this phase. Clearly define boundaries while offering positive affirmations (e.g., 'Im always here for you,' 'I see your progress').",
'《中华人民共和国卫生行业标准WS 423-2013》' => "《Chinese Health Industry Standard WS 423-2013》",
'《中华人民共和国卫生行业标准WS/T 612-2018》' => "《Chinese Health Industry Standard WS/T 612-2018》",
'《中华人民共和国卫生行业标准WS/T1586-2018》' => "《Chinese Health Industry Standard WS/T 1586-2018》",
'《WHO 5~19岁身高/体重判定标准》' => "《WHO Growth Reference for Children and Adolescents (519 Years)》",
'头围' => "Head Circumference",
'头围是指绕头部一周的最大长度,头围的大小与脑的发育密切相关' => "Head circumference refers to the maximum length around the head. Its measurement is closely related to brain development.",
],
// 可以添加更多语言映射
];
/**
* 处理多国语言翻译
*
* @param string $language 目标语言代码
* @param mixed $data 要翻译的数据(字符串或数组)
* @return mixed 翻译后的数据
*/
public function handling_languages_from_multiple_countries($language, $data)
{
// dump($data);
// 验证语言是否支持
if (!$this->isLanguageSupported($language)) {
return $this->msg($data['data']);
}
// 如果是数组,递归处理每个元素
if (is_array($data)) {
// dump(2);
$data = $this->translateArray($language, $data);
return $this->msg($data['data']);
}
// 如果是字符串,直接翻译
if (is_string($data)) {
// dump(3);
return $this->translateString($language, $data);
}
// dump($data);
// 其他类型直接返回
return $this->msg($data['data']);
}
/**
* 检查语言是否支持
*
* @param string $language 语言代码
* @return bool
*/
protected function isLanguageSupported($language)
{
return isset($this->supportedLanguages[$language]);
}
/**
* 翻译数组
*
* @param string $language 目标语言
* @param array $array 要翻译的数组
* @return array 翻译后的数组
*/
protected function translateArray($language, array $array)
{
$result = [];
foreach ($array as $key => $value) {
// 保持键不变,只翻译值
$result[$key] = is_array($value)
? $this->translateArray($language, $value)
: $this->translateString($language, $value);
}
return $result;
}
/**
* 翻译字符串
*
* @param string $language 目标语言
* @param string $string 要翻译的字符串
* @return string 翻译后的字符串
*/
protected function translateString($language, $string)
{
// dump($string);
// 检查是否有该语言的映射表
if (!isset($this->languageMap[$language])) {
return $string;
}
// 检查是否有对应的翻译
return $this->languageMap[$language][$string] ?? $string;
}
/**
* 获取支持的语言列表
*
* @return array
*/
public function getSupportedLanguages()
{
return $this->supportedLanguages;
}
/**
* 添加新的语言翻译
*
* @param string $language 语言代码
* @param array $translations 翻译映射数组
* @return bool
*/
public function addTranslations($language, array $translations)
{
if (!$this->isLanguageSupported($language)) {
return false;
}
if (!isset($this->languageMap[$language])) {
$this->languageMap[$language] = [];
}
$this->languageMap[$language] = array_merge(
$this->languageMap[$language],
$translations
);
return true;
}
}

View File

@ -91,7 +91,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: (register_action)" . "\n"; $logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -156,7 +156,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: (reset_password)" . "\n"; $logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -240,7 +240,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: (login_action)" . "\n"; $logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -318,7 +318,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: (wechat_quick_login)" . "\n"; $logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -356,7 +356,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: (user_quit_account)" . "\n"; $logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -392,7 +392,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: (delete_account)" . "\n"; $logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);

View File

@ -141,17 +141,17 @@ class Base extends Controller{
$length = strlen($token); $length = strlen($token);
if ($length < 10 ) { if ($length < 10 ) {
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败字符串长度小于10', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败字符串长度小于10', 'token_log');
return false; return ['state'=>false,'language'=>null];
} }
}else{ }else{
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败不是字符串', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败不是字符串', 'token_log');
return false; return ['state'=>false,'language'=>null];
} }
$user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->field('id,login_time')->find(); $user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->field('id,login_time,language')->find();
if(!$user_login){ if(!$user_login){
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败未找到用户token', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败未找到用户token', 'token_log');
return false; return ['state'=>false,'language'=>null];
} }
// 创建 DateTime 对象来表示指定的日期和时间 // 创建 DateTime 对象来表示指定的日期和时间
@ -174,16 +174,16 @@ class Base extends Controller{
if ($daysDifference > $this->token_time) { if ($daysDifference > $this->token_time) {
// echo "超过 {$specifiedDays} 天"; // echo "超过 {$specifiedDays} 天";
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败原因没有找到该token,或该token已经超过30天', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败原因没有找到该token,或该token已经超过30天', 'token_log');
return false; return ['state'=>false,'language'=>$user_login['language']];
} else { } else {
// echo "未超过 {$specifiedDays} 天"; // echo "未超过 {$specifiedDays} 天";
$user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->update(['login_time'=>date('Y-m-d H:i:s')]); $user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->update(['login_time'=>date('Y-m-d H:i:s')]);
if($user_login){ if($user_login){
Log::record('用户尝试更新token时间token' . $token.',记录成功,最新的时间为'.date('Y-m-d H:i:s'), 'token_log'); Log::record('用户尝试更新token时间token' . $token.',记录成功,最新的时间为'.date('Y-m-d H:i:s'), 'token_log');
return true; return ['state'=>true,'language'=>$user_login['language']];
}else{ }else{
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败数据库更新时间未成功', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败数据库更新时间未成功', 'token_log');
return true; return ['state'=>true,'language'=>$user_login['language']];
} }
} }
@ -612,6 +612,103 @@ class Base extends Controller{
} }
// 处理身高体重的单位转换它们为cm和kg。
public function convertHeightAndWeight($height, $weight) {
// 加 bcadd(,,20)
// 减 bcsub(,,20)
// 乘 bcmul(,,20)
// 除 bcdiv(,,20)
// 定义单位转换比例
$heightConversion = [
'cm' => 1,
'inch' => 2.54,
'ft-in' => function($value) {
list($ft, $in) = explode('-', $value);
return $ft * 30.48 + $in * 2.54; // 1 foot = 30.48 cm, 1 inch = 2.54 cm
}
];
$weightConversion = [
'kg' => 1,
'斤' => 0.5, // 1斤 = 0.5kg
'st:lb' => function($value) {
list($st, $lb) = explode(':', $value);
return $st * 6.35029318 + $lb * 0.45359237; // 1 stone = 6.35029318 kg, 1 lb = 0.45359237 kg
},
'lb' => 0.45359237 // 1 lb = 0.45359237 kg
];
// 处理 height
if (preg_match('/([\d.]+)(cm|inch|ft-in)/', $height, $matches)) {
// $heightValue = floatval($matches[1]);
$heightValue = $matches[1];
$heightUnit = $matches[2];
if($heightUnit == 'ft-in'){
// 如果单位为st:lb但是数据格式不对
$heightValue = str_replace($heightUnit, "", $height);
if(count(explode('-', $heightValue)) < 2){
$heightValue = str_replace("-", "", $heightValue);
$heightValue = $heightValue."-0";
}
}
if (isset($heightConversion[$heightUnit])) {
if (is_callable($heightConversion[$heightUnit])) {
$heightInCm = $heightConversion[$heightUnit]($heightValue);
} else {
$heightInCm = $heightValue * $heightConversion[$heightUnit];
}
} else {
// 未知单位,返回错误
$heightInCm = false;
}
} else {
// 未找到指定单位判断是否是数字
if (preg_match('/^-?\d+(\.\d+)?$/', $height)) {
$heightInCm = $height;
} else {
$heightInCm = false;
}
}
// 处理 weight
if (preg_match('/([\d.:]+)(kg|斤|st:lb|lb)/', $weight, $matches)) {
$weightValue = $matches[1];
$weightUnit = $matches[2];
if($weightUnit == 'st:lb'){
// 如果单位为st:lb但是数据格式不对
$weightValue = str_replace($weightUnit, "", $weight);
if(count(explode(':', $weightValue)) < 2){
$weightValue = str_replace(":", "", $weightValue);
$weightValue = $weightValue.":0";
}
}
if (isset($weightConversion[$weightUnit])) {
if (is_callable($weightConversion[$weightUnit])) {
$weightInKg = $weightConversion[$weightUnit]($weightValue);
} else {
$weightInKg = $weightValue * $weightConversion[$weightUnit];
}
} else {
// 未知单位,返回错误
$weightInKg = false;
}
} else {
// 未找到指定单位判断是否是数字
if (preg_match('/^-?\d+(\.\d+)?$/', $weight)) {
$weightInKg = $weight;
} else {
$weightInKg = false;
}
}
return [
'height_in_cm' => bcmul($heightInCm,1,2),
'weight_in_kg' => bcmul($weightInKg,1,2)
];
}
public function ceshiyong($aa = 4,$gd = 0.2){ public function ceshiyong($aa = 4,$gd = 0.2){

View File

@ -88,7 +88,7 @@ class Card extends Base{
// 详细卡片信息 // 详细卡片信息
// $data = ['id'=>'2'] // $data = ['id'=>'2']
public function card_data_detailed($data=['aud_id'=>'38']){ public function card_data_detailed($data=['aud_id'=>'144']){
try { try {
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
@ -100,9 +100,10 @@ class Card extends Base{
if(!$this->verify_data_is_ok($data['aud_id'],'intnum')){ if(!$this->verify_data_is_ok($data['aud_id'],'intnum')){
return $this->msg(10005); return $this->msg(10005);
} }
// $return_data;
$return_data = $this->get_user_body_data($data); $return_data = $this->get_user_body_data($data);
// 成功 // $language_data = new Language();
$this->record_api_log($data, null, $return_data); // $return_data = $language_data->handling_languages_from_multiple_countries('en', $return_data->getData());
return $return_data; return $return_data;
} catch (\Exception $e) { } catch (\Exception $e) {
// 捕获异常 // 捕获异常
@ -181,12 +182,21 @@ class Card extends Base{
if(!$this->verify_data_is_ok($data['time'],'datetime')){ if(!$this->verify_data_is_ok($data['time'],'datetime')){
return $this->msg(10005); return $this->msg(10005);
} }
if(!$this->verify_data_is_ok($data['height'],'num')){ $temporary_data = $this->convertHeightAndWeight($data['height'],$data['weight']);
return $this->msg(10005); if($temporary_data['height_in_cm'] == false){
return $this->msg(10005,'身高单位错误');
} }
if(!$this->verify_data_is_ok($data['weight'],'num')){ if($temporary_data['weight_in_kg'] == false){
return $this->msg(10005); return $this->msg(10005,'体重单位错误');
} }
$data['height'] = $temporary_data['height_in_cm'];
$data['weight'] = $temporary_data['weight_in_kg'];
// if(!$this->verify_data_is_ok($data['height'],'num')){
// return $this->msg(10005);
// }
// if(!$this->verify_data_is_ok($data['weight'],'num')){
// return $this->msg(10005);
// }
// $data['height'] = explode(',',$data['height']); // $data['height'] = explode(',',$data['height']);
// if(count($data['height']) < 2){ // if(count($data['height']) < 2){
// return $this->msg(10005); // return $this->msg(10005);
@ -232,7 +242,7 @@ class Card extends Base{
// 设备记录 // 设备记录
// $data = ['id'=>'2','time'=>'1991-04-20 10:10:10','height'=>'15.1','weight'=>'75.1'] // $data = ['id'=>'2','time'=>'1991-04-20 10:10:10','height'=>'15.1','weight'=>'75.1']
// public function card_manual_recording_device($data = ['aud_id'=>'37','height'=>'169.60,inch','weight'=>'52.45,lb','adc'=>'520.3','token'=>'591b70e0d80b5fa6d77e6e1384453ab9']){ // public function card_manual_recording_device($data = ['aud_id'=>'37','height'=>'169.60,inch','weight'=>'52.45,lb','adc'=>'520.3','token'=>'591b70e0d80b5fa6d77e6e1384453ab9']){
public function card_manual_recording_device($data = ['aud_id'=>'37','height'=>'169.60','weight'=>'52.45','adc'=>'520.3','token'=>'591b70e0d80b5fa6d77e6e1384453ab9']){ public function card_manual_recording_device($data = ['aud_id'=>'37','height'=>'169.60','weight'=>'52.45','adc'=>'520.3','token'=>'591b70e0d80b5fa6d77e6e1384453ab9']){
try { try {
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
@ -246,12 +256,25 @@ class Card extends Base{
if(!$this->verify_data_is_ok($data['aud_id'],'intnum')){ if(!$this->verify_data_is_ok($data['aud_id'],'intnum')){
return $this->msg(10005); return $this->msg(10005);
} }
if(!$this->verify_data_is_ok($data['height'],'num')){ if(!$this->verify_data_is_ok($data['adc'],'num')){
return $this->msg(10005); return $this->msg(10005);
} }
if(!$this->verify_data_is_ok($data['weight'],'num')){ $temporary_data = $this->convertHeightAndWeight($data['height'],$data['weight']);
return $this->msg(10005); if($temporary_data['height_in_cm'] == false){
return $this->msg(10005,'身高单位错误');
} }
if($temporary_data['weight_in_kg'] == false){
return $this->msg(10005,'体重单位错误');
}
$data['height'] = $temporary_data['height_in_cm'];
$data['weight'] = $temporary_data['weight_in_kg'];
// if(!$this->verify_data_is_ok($data['height'],'num')){
// return $this->msg(10005);
// }
// if(!$this->verify_data_is_ok($data['weight'],'num')){
// return $this->msg(10005);
// }
// $data['height'] = explode(',',$data['height']); // $data['height'] = explode(',',$data['height']);
// if(count($data['height']) < 2){ // if(count($data['height']) < 2){
// return $this->msg(10005); // return $this->msg(10005);
@ -272,9 +295,7 @@ class Card extends Base{
// if(!in_array($data['weight'][1],$this->unit_data['weight'])){ // if(!in_array($data['weight'][1],$this->unit_data['weight'])){
// return $this->msg(10005); // return $this->msg(10005);
// } // }
if(!$this->verify_data_is_ok($data['adc'],'num')){
return $this->msg(10005);
}
$data['time'] = date('Y-m-d H:i:s'); $data['time'] = date('Y-m-d H:i:s');
$data['acd_id'] = '2'; $data['acd_id'] = '2';
$return_data = $this->set_user_body_data($data,'by_device'); $return_data = $this->set_user_body_data($data,'by_device');
@ -571,9 +592,11 @@ class Card extends Base{
// 处理返回数据 // 处理返回数据
$result_end = $this->processing_return_data_new($result[0]); $result_end = $this->processing_return_data_new($result[0]);
$cardparts = new Cardparts; $cardparts = new Cardparts;
$result_end['gender'] = $result[0]['gender']; $result_end['gender'] = $result[0]['gender'];
$result_end['record_time'] = $result[0]['record_time']; $result_end['record_time'] = $result[0]['record_time'];
$result_end['score'] = $result_end['score']; $result_end['score'] = $result_end['score'];
$result_end['body_type'] = $result_end['body_type']; $result_end['body_type'] = $result_end['body_type'];
$result_end = $cardparts->conversion_interval($result_end); $result_end = $cardparts->conversion_interval($result_end);
@ -585,6 +608,7 @@ class Card extends Base{
'bmi'=>$result[0]['bmi'] 'bmi'=>$result[0]['bmi']
], ],
]); ]);
// 只有含有阻抗的记录才有数据参考 // 只有含有阻抗的记录才有数据参考
if($result[0]['record_type'] == 'by_device_adc'){ if($result[0]['record_type'] == 'by_device_adc'){
if(count($result_end['cplist']['nutritionlist']) <= 0){ if(count($result_end['cplist']['nutritionlist']) <= 0){
@ -608,7 +632,7 @@ class Card extends Base{
'initial_weight'=>$result[0]['initial_weight']>0?$result[0]['initial_weight']:0, 'initial_weight'=>$result[0]['initial_weight']>0?$result[0]['initial_weight']:0,
'initial_date'=>$result[0]['initial_date']!=null?$result[0]['initial_date']:0, 'initial_date'=>$result[0]['initial_date']!=null?$result[0]['initial_date']:0,
]); ]);
// dump($result_end);
if(count($result_end['top_list'][2]['list']) <= 0){ if(count($result_end['top_list'][2]['list']) <= 0){
// 这是16岁以上人群 // 这是16岁以上人群
$data = [ $data = [
@ -619,15 +643,20 @@ class Card extends Base{
]; ];
$temporary_arr_bmi_list = $this->card_bmi_evaluation($data,true); $temporary_arr_bmi_list = $this->card_bmi_evaluation($data,true);
// dump($temporary_arr_bmi_list);
$temporary_arr_bmi_list = $temporary_arr_bmi_list->getData(); $temporary_arr_bmi_list = $temporary_arr_bmi_list->getData();
// dump($temporary_arr_bmi_list);
// die;
if($temporary_arr_bmi_list['code'] == 0){ if($temporary_arr_bmi_list['code'] == 0){
$result_end['top_list'][2]['standard'] = $temporary_arr_bmi_list['data']['bmilevel']; $result_end['top_list'][2]['standard'] = $temporary_arr_bmi_list['data']['bmilevel'];
$result_end['top_list'][2]['color'] = $temporary_arr_bmi_list['data']['bmilevelcolor']; $result_end['top_list'][2]['color'] = $temporary_arr_bmi_list['data']['bmilevelcolor'];
$result_end['top_list'][2]['list'] = $temporary_arr_bmi_list['data']['bmilevellist']; $result_end['top_list'][2]['list'] = $temporary_arr_bmi_list['data']['bmilevellist'];
$result_end['top_list'][2]['offset'] = $temporary_arr_bmi_list['data']['offset']; $result_end['top_list'][2]['offset'] = $temporary_arr_bmi_list['data']['offset'];
} }
// dump($result_end);
// die;
} }
// 加入曲线板块底部的减肥计划数据end // 加入曲线板块底部的减肥计划数据end
// 添加头围数据如果有的话start // 添加头围数据如果有的话start
if($head_circumference !== false && $this->calculate_age($result[0]['birthday']) < 3){ if($head_circumference !== false && $this->calculate_age($result[0]['birthday']) < 3){
@ -644,7 +673,7 @@ class Card extends Base{
'color'=>'', 'color'=>'',
'list'=>$head_circumference['list2'], 'list'=>$head_circumference['list2'],
'key_name'=>'head_circumference', 'key_name'=>'head_circumference',
'desc'=>'头围是指绕头部一周的最大长度,头围的大小与的发育密切相关', 'desc'=>'头围是指绕头部一周的最大长度,头围的大小与的发育密切相关',
'offset'=>$offset 'offset'=>$offset
]); ]);
} }
@ -762,6 +791,7 @@ class Card extends Base{
$min_key = array_search($min_value,$temporary_arr); $min_key = array_search($min_value,$temporary_arr);
$type_num = $this->card_body_level[$min_key]['value']; $type_num = $this->card_body_level[$min_key]['value'];
$temporary_arr2 = Db::table($this->card_use_db_name['6'])->where(['Type'=>$type_num,'Level'=>$min_value,'IsDeleted'=>0])->field('Nutrition,Sport')->find(); $temporary_arr2 = Db::table($this->card_use_db_name['6'])->where(['Type'=>$type_num,'Level'=>$min_value,'IsDeleted'=>0])->field('Nutrition,Sport')->find();
// dump($temporary_arr2);
array_push($result['nutritionlist'],$temporary_arr2['Nutrition']); array_push($result['nutritionlist'],$temporary_arr2['Nutrition']);
array_push($result['sportlist'],$temporary_arr2['Sport']); array_push($result['sportlist'],$temporary_arr2['Sport']);
// $result['nutritionlist'] = $temporary_arr2['Nutrition']; // $result['nutritionlist'] = $temporary_arr2['Nutrition'];

View File

@ -191,10 +191,10 @@ class Cardparts extends Base{
'bottom_list'=>[], 'bottom_list'=>[],
]; ];
// die; // die;
$date_temporary = new \DateTime($temporary_arr['record_time']); // $date_temporary = new \DateTime($temporary_arr['record_time']);
// 使用 format 方法来指定新的日期和时间格式 // 使用 format 方法来指定新的日期和时间格式
$temporary_arr['record_time'] = $date_temporary->format('Y年m月d日 H:i:s'); // $temporary_arr['record_time'] = $date_temporary->format('Y年m月d日 H:i:s');
// 处理格式(顶部) // 处理格式(顶部)
foreach ($this->parameter_aggregate_top as $key => $value) { foreach ($this->parameter_aggregate_top as $key => $value) {
$data[$key]['key_name'] = $key; $data[$key]['key_name'] = $key;

View File

@ -0,0 +1,210 @@
<?php
namespace app\app\controller;
use think\Db;
class Deepseek extends Base{
protected $msginformation_use_db_name = [
'1'=>'admin_editor_text_content',
'2'=>'admin_editor_text_like_up_log',
'3'=>'admin_notice_banner',
'4'=>'admin_business_cooperation'
];
protected $page_num = 10;
// 加 bcadd(,,20)
// 减 bcsub(,,20)
// 乘 bcmul(,,20)
// 除 bcdiv(,,20)
################################################################接口################################################################
################################################################接口################################################################
################################################################接口################################################################
public function test_index(){
return $this->fetch();
}
// 获取板块,及板块下类型标签
public function send_msg_deepseek(){
// dump('456');
// die;
try {
$data = input('post.');
// dump($data);
// dump(array_key_exists('xinxi', $data));
if(!array_key_exists('xinxi', $data)){
return $this->msg(10001);
}
if(!$this->verify_data_is_ok($data['xinxi'],'str')){
return $this->msg(10005);
}
// $data['msg'] = "";
// dump($data);
// die;
$return_data = $this->deepseek_only_onec_action($data);
// $return_data = $this->deepseek_ceshiyongjiekou($data);
return $return_data;
} catch (\Exception $e) {
// 捕获异常
$logContent["flie"] = $e->getFile();
$logContent["line"] = $e->getLine();
$logContent['all_content'] = "异常信息:\n";
$logContent['all_content'] = "接口send_msg_deepseek\n";
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log([], $logContent, null);
return $this->msg(99999);
}
}
public function deepseek_only_onec_action($xinxi){
// DeepSeek API密钥
// $apiKey = 'sk-28dd23215ef84772b64d77011419e271';
$apiKey = 'bd739e8c-91af-40bb-85d4-0804060b2390';
// DeepSeek API的端点
// $apiUrl = 'https://api.deepseek.com/v1/chat/completions';
$apiUrl = 'https://ark.cn-beijing.volces.com/api/v3/chat/completions';
// 准备请求数据
$data = [
"messages" => [
[
"content" => "你是一个有关身体健康的专家,能根据用户提供的身体数据给出对应的分析和建议",
"role" => "system"
],
[
"content" => $xinxi['xinxi'],
"role" => "user"
]
],
// "model" => "deepseek-chat",
"model" => "ep-20250304141108-x9d7l",
"frequency_penalty" => 0,
"max_tokens" => 2048,
"presence_penalty" => 0,
"response_format" => [
"type" => "text" //指定生成文本的格式。"type": 指定格式类型,例如"text"(纯文本)或"json"JSON格式
],
"stop" => null,
"stream" => false,
"stream_options" => null,
"temperature" => 1,
"top_p" => 1,
"tools" => null,
"tool_choice" => "none",
"logprobs" => false,
"top_logprobs" => null
];
// 初始化cURL会话
$ch = curl_init();
// 设置cURL选项
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 禁用证书验证
curl_setopt($ch, CURLOPT_URL, $apiUrl); // 设置API URL
curl_setopt($ch, CURLOPT_POST, true); // 使用POST方法
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); // 设置POST数据
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $apiKey, // 设置API密钥
'Content-Type: application/json', // 设置请求头为JSON
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回响应而不是直接输出
// 执行cURL请求并获取响应
$response = curl_exec($ch);
// 检查是否有cURL错误
if (curl_errno($ch)) {
echo 'cURL请求失败: ' . curl_error($ch);
} else {
// 获取HTTP状态码
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode === 200) {
// 解析JSON响应
$result = json_decode($response, true);
// print_r($result); // 输出API响应
return $this->msg(0,$result['choices'][0]['message']['content']);
// dump($result);
} else {
return $this->msg(['code'=>$httpCode]);
// echo 'API请求失败HTTP状态码: ' . $httpCode;
// echo '响应内容: ' . $response;
}
}
// 关闭cURL会话
curl_close($ch);
}
public function deepseek_ceshiyongjiekou(){
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.deepseek.com/chat/completions',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"messages": [
{
"content": "You are a helpful assistant",
"role": "system"
},
{
"content": "Hi",
"role": "user"
}
],
"model": "deepseek-chat",
"frequency_penalty": 0,
"max_tokens": 2048,
"presence_penalty": 0,
"response_format": {
"type": "text"
},
"stop": null,
"stream": false,
"stream_options": null,
"temperature": 1,
"top_p": 1,
"tools": null,
"tool_choice": "none",
"logprobs": false,
"top_logprobs": null
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Accept: application/json',
'Authorization: Bearer <TOKEN>'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
}
}

View File

@ -31,6 +31,28 @@ class Download extends Base{
return $this->fetch(); return $this->fetch();
} }
public function business_cooperation(){
return $this->fetch();
}
public function business_cooperation_action(){
$data = input();
$result = Db::table('admin_business_cooperation_log')->insert([
'name'=>$data['name'],
'tel'=>$data['phone'],
'company'=>$data['company'],
'intention_data'=>implode(',',$data['selectedValues']),
'notes_data'=>$data['remark'],
'create_time'=>date('Y-m-d H:i:s'),
]);
if($result){
$this->send_email_api_error(["tsf3920322@126.com"],['title'=>'商户合作','from_user_name'=>'reedaw商务','content'=>'有一封商户合作']);
return json(['code'=>0,'msg'=>'提交成功']);
}else{
return json(['code'=>10001,'msg'=>'网络错误,请直接联系商务合作电话/微信13590959084']);
}
}
public function ceshi(){ public function ceshi(){
$data = input(); $data = input();
$url = 'https://klcz.pcxbc.com/open-api/calc/healthcalc/bodyfat3'; $url = 'https://klcz.pcxbc.com/open-api/calc/healthcalc/bodyfat3';

View File

@ -4,6 +4,8 @@ namespace app\app\controller;
use think\Db; use think\Db;
use \think\Validate; use \think\Validate;
use app\app\controller\Language;
// use ip2region\Ip2Region;
class Index extends Base{ class Index extends Base{
protected $moren_gufen_diqu = '北京,北京'; protected $moren_gufen_diqu = '北京,北京';
@ -60,6 +62,39 @@ class Index extends Base{
['min'=>'3','max'=>'16','value'=>'儿童'], ['min'=>'3','max'=>'16','value'=>'儿童'],
['min'=>'16','max'=>'500','value'=>'成人'] ['min'=>'16','max'=>'500','value'=>'成人']
]; ];
protected $language_country = [
'en' => 'English', // 英语(通用)★
'zh' => '中文', // 中文(简体)★
'es' => 'Español', // 西班牙语(西班牙)★
'fr' => 'Français', // 法语(法国)★
'pt' => 'Português', // 葡萄牙语(巴西)★
'ar' => 'العربية', // 阿拉伯语(标准)★
'ru' => 'Русский', // 俄语(俄罗斯)★
'de' => 'Deutsch', // 德语(德国)★
// 'ja' => '日本語', // 日语
// 'ko' => '한국어', // 韩语
// 'it' => 'Italiano', // 意大利语
// 'nl' => 'Nederlands', // 荷兰语
// 'hi' => 'हिन्दी', // 印地语
// 'tr' => 'Türkçe', // 土耳其语
// 'vi' => 'Tiếng Việt', // 越南语
// 'th' => 'ไทย', // 泰语
// 'pl' => 'Polski', // 波兰语
// 'sv' => 'Svenska', // 瑞典语
// 'fi' => 'Suomi', // 芬兰语
// 'da' => 'Dansk', // 丹麦语
// 'no' => 'Norsk', // 挪威语
// 'he' => 'עברית', // 希伯来语
// 'id' => 'Bahasa Indonesia', // 印尼语
// 'ms' => 'Bahasa Melayu', // 马来语
// 'cs' => 'Čeština', // 捷克语
// 'hu' => 'Magyar', // 匈牙利语
// 'el' => 'Ελληνικά', // 希腊语
// 'ro' => 'Română', // 罗马尼亚语
// 'sk' => 'Slovenčina', // 斯洛伐克语
// 'uk' => 'Українська', // 乌克兰语
];
################################################################个人资料卡################################################################ ################################################################个人资料卡################################################################
@ -67,8 +102,35 @@ class Index extends Base{
################################################################个人资料卡################################################################ ################################################################个人资料卡################################################################
// 检测版本及判断是否登录失效 // 检测版本及判断是否登录失效
public function login_invalid_version($data = ['token'=>'']){ public function login_invalid_version($data = ['token'=>'caadd1be045a65f30b92aa805f1de54a']){
try { try {
// 获取客户端IP
$ip = request()->ip();
// 调用IP识别方法
$region = $this->getIpInfo($ip);
// 解析地区信息
$regionParts = explode('|', $region);
$country = $regionParts[0] ?? '';
// 判断国家是否在支持的语言列表中
$language = '';
if ($country && $country !== '0') {
$languageMap = [
'中国' => 'zh',
'美国' => 'en',
'英国' => 'en',
'西班牙' => 'es',
'法国' => 'fr',
'葡萄牙' => 'pt',
'阿拉伯联合酋长国' => 'ar',
'俄罗斯' => 'ru',
'德国' => 'de'
];
$language = $languageMap[$country] ?? '';
}
// 检查语言是否在支持列表中
$language_all = new Language();
$isSupportedLanguage = array_key_exists($language, $language_all->getSupportedLanguages());
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
$data = input('post.'); $data = input('post.');
@ -84,12 +146,18 @@ class Index extends Base{
$version = ''; $version = '';
$url = ''; $url = '';
} }
if($this->token_time_validate($data['token']) === false){ $user_token_state = $this->token_time_validate($data['token']);
$this->record_api_log($data, null, ['code'=>-1,'msg'=>'未登录',['version'=>$version,'url'=>$url]]);
return $this->msg(-1,'未登录',['version'=>$version,'url'=>$url]); $user_language_data = Db::table($this->index_use_db_name['7'])->where(['token'=>$data['token']])->field('language')->find();
if($user_language_data != null){
$language_data = $user_language_data['language'];
}else{ }else{
$this->record_api_log($data, null, ['code'=>0,'msg'=>'success',['version'=>$version,'url'=>$url]]); $language_data = $this->pd_language($user_token_state['language'],$isSupportedLanguage,$language);
return $this->msg(['version'=>$version,'url'=>$url]); }
if($user_token_state['state'] === false){
return $this->msg(-1,'未登录',['version'=>$version,'url'=>$url,'language'=>$language_data,'language_arr'=>$this->language_country]);
}else{
return $this->msg(['version'=>$version,'url'=>$url,'language'=>$language_data,'language_arr'=>$this->language_country]);
} }
} catch (\Exception $e) { } catch (\Exception $e) {
@ -100,12 +168,62 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
return $this->msg(99999); return $this->msg(99999);
} }
} }
// 添加IP信息获取方法
protected function getIpInfo($ip) {
// 默认IP
$ip = $ip ?: request()->ip();
try {
$ip2region = new \Ip2Region();
$info = $ip2region->memorySearch($ip);
// 返回国家信息
return $info['region'] ?: '未知';
} catch (\Exception $e) {
return '未知';
}
}
public function set_language_country($data = ['token'=>'caadd1be045a65f30b92aa805f1de54a','language'=>'zh']){
try {
// 你的业务逻辑
if(count(input('post.')) > 0){
$data = input('post.');
}
if(!array_key_exists('token', $data) || !array_key_exists('language', $data)){
return $this->msg(10001);
}
if(!array_key_exists($data['language'],$this->language_country)){
return $this->msg(10007);
}
$result = Db::table($this->index_use_db_name['7'])->where(['token'=>$data['token']])->update(['language'=>$data['language']]);
if($result){
return $this->msg([]);
}else{
return $this->msg(10002);
}
} catch (\Exception $e) {
$logContent["flie"] = $e->getFile();
$logContent["line"] = $e->getLine();
$logContent['all_content'] = "异常信息:\n";
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null);
return $this->msg(99999);
}
}
// 创建用户 // 创建用户
public function create_user_data($data = ['aan_id'=>1,'height'=>'152.3','weight'=>'35.4','nickname'=>'钮祜禄测试1','birthday'=>'2019-04-20','gender'=>1,'grade'=>'grade_s_3','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'57bd45e3a963b372ea2d873e4bd8d1f8']){ public function create_user_data($data = ['aan_id'=>1,'height'=>'152.3','weight'=>'35.4','nickname'=>'钮祜禄测试1','birthday'=>'2019-04-20','gender'=>1,'grade'=>'grade_s_3','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'57bd45e3a963b372ea2d873e4bd8d1f8']){
@ -143,14 +261,12 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
return $this->msg(99999); return $this->msg(99999);
} }
} }
// 修改用户 // 修改用户
public function update_user_data($data = ['id'=>66,'nickname'=>'王小二','birthday'=>'2019-01-01','gender'=>1,'grade'=>'二年级','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function update_user_data($data = ['id'=>66,'nickname'=>'王小二','birthday'=>'2019-01-01','gender'=>1,'grade'=>'二年级','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'0dafb98a10995c98b5a33b7d59d986ca']){
@ -187,6 +303,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -230,6 +347,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -238,7 +356,6 @@ class Index extends Base{
} }
// 获取账号下用户列表 // 获取账号下用户列表
// $type 1获取列表2获取详细信息 // $type 1获取列表2获取详细信息
public function get_user_card_list($data = ['aan_id'=>4,'type'=>2,'token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function get_user_card_list($data = ['aan_id'=>4,'type'=>2,'token'=>'0dafb98a10995c98b5a33b7d59d986ca']){
@ -298,6 +415,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -307,8 +425,8 @@ class Index extends Base{
} }
// 获取指定用户详细信息 // 获取指定用户详细信息
public function get_user_data_information($data = ['aud_id'=>11]){ public function get_user_data_information($data = ['aud_id'=>61]){
try { // try {
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
$data = input('post.'); $data = input('post.');
@ -334,7 +452,7 @@ class Index extends Base{
} }
} }
// 从这里开始进入体脂还是体测的判断 // 从这里开始进入体脂还是体测的判断
$result['card_order'] = explode(',',$result['card_order']); $result['card_order'] = $result['card_order'] == ""?[]:explode(',',$result['card_order']);
if($result['measure_model'] == 1){// 这里是体测 if($result['measure_model'] == 1){// 这里是体测
$calculation_results = $this->get_user_card_data_list($result,$result['id']); $calculation_results = $this->get_user_card_data_list($result,$result['id']);
$result['card_data_list'] = $calculation_results[0]; $result['card_data_list'] = $calculation_results[0];
@ -377,19 +495,19 @@ class Index extends Base{
} }
$this->record_api_log($data, null, ['code'=>0,'msg'=>'success',$result]); $this->record_api_log($data, null, ['code'=>0,'msg'=>'success',$result]);
return $this->msg($result); return $this->msg($result);
} catch (\Exception $e) { // } catch (\Exception $e) {
// 捕获异常 // // 捕获异常
$logContent["flie"] = $e->getFile(); // $logContent["flie"] = $e->getFile();
$logContent["line"] = $e->getLine(); // $logContent["line"] = $e->getLine();
$logContent['all_content'] = "异常信息:\n"; // $logContent['all_content'] = "异常信息:\n";
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; // $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; // $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; // $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; // $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; // $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); // $this->record_api_log($data, $logContent, null);
return $this->msg(99999); // return $this->msg(99999);
} // }
} }
@ -449,6 +567,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -498,6 +617,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -535,6 +655,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -583,6 +704,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -594,8 +716,6 @@ class Index extends Base{
// 获取账号下首页卡片的基础数据 // 获取账号下首页卡片的基础数据
public function get_user_card_data_list($data,$aud_id){ public function get_user_card_data_list($data,$aud_id){
// try {
// 你的业务逻辑
$result = []; $result = [];
$db_arr = []; $db_arr = [];
foreach ($data['card_order'] as $key => $value) { foreach ($data['card_order'] as $key => $value) {
@ -641,7 +761,7 @@ class Index extends Base{
// 'initial_date'=>$data['initial_date']!=null?$data['initial_date']:0, // 'initial_date'=>$data['initial_date']!=null?$data['initial_date']:0,
// ]); // ]);
// } // }
if(count($db_arr) <= 0){ if(count($db_arr) <= 0){
// 没有数据,传递一个空的卡片 // 没有数据,传递一个空的卡片
foreach ($data['card_order'] as $key => $value) { foreach ($data['card_order'] as $key => $value) {
@ -726,13 +846,7 @@ class Index extends Base{
array_push($result,$temporary_arr); array_push($result,$temporary_arr);
} }
} }
// 成功
// $this->record_api_log($data, null, ['code'=>0,'msg'=>'success',[$result,$target_current]]);
return [$result,$data['card_order']]; return [$result,$data['card_order']];
// } catch (\Exception $e) {
// // 捕获异常
// $this->record_api_log($data, $e->getMessage(), null);
// }
} }
@ -1033,6 +1147,20 @@ class Index extends Base{
return $parameter; return $parameter;
} }
public function pd_language($user_language,$isSupportedLanguage,$language){
if(!$user_language){
if($isSupportedLanguage){
$result = $language;
}else{
$result = 'en'; // 默认语言为中文
}
}else{
$result = $user_language;
}
return $result;
}

View File

@ -0,0 +1,211 @@
<?php
namespace app\app\controller;
class Language extends Base
{
// 支持的语言列表
protected $supportedLanguages = [
'en' => 'English',
'zh' => 'Chinese',
'es' => 'Spanish',
'fr' => 'French',
'pt' => 'Portuguese',
'ar' => 'Arabic',
'ru' => 'Russian',
'de' => 'German'
];
// 语言映射表
protected $languageMap = [
'en' => [
'操作成功' => 'Success',
'体重' => 'Weight',
'身高' => 'Height',
'消瘦' => 'Slim',
'正常' => 'Normal',
'偏重' => 'Overweight',
'肥胖' => 'Obesity',
'反映和衡量一个人健康状况的重要标志之一' => "One of the important indicators reflecting and measuring a person's health status",
'人体纵向部分的长度,源于人体的纵向生长,受遗传因素的影响较大' => "The length of the longitudinal part of the human body is derived from its longitudinal growth and is greatly influenced by genetic factors",
'BMI是身体质量指数,是目前国际上常用的衡量人体胖瘦程度以及是否健康的一个标准。' => "BMI is the body mass index, which is currently a commonly used international standard for measuring the degree of body fat, thinness, and health.",
'公斤' => "kg",
'CM' => "cm",
'年' => "-",
'月' => "-",
'日' => "",
'身体得分' => "Physical score",
'分' => "score",
'身体类型' => "body type",
'健美肌肉型' => "Bodybuilding muscle type",
'低' => "Low",
'偏低' => "Slightly low",
'标准' => "Standard",
'偏高' => "Slightly high",
'高' => "High",
'矮' => "Short",
'偏矮' => "Slightly short",
'脂肪率' => "Body Fat Percentage",
'体脂率是指身体成分中,脂肪组织所占的比率。测量体脂率比单纯的只测量体重更能反映我们身体的脂肪水平(肥胖程度)。' => "Body fat percentage refers to the proportion of fat tissue in body composition. Measuring it provides a more accurate reflection of body fat levels (degree of obesity) than weight measurement alone.",
'脂肪量' => "Fat Mass",
'人体脂肪的重量' => "Body Fat Weight",
'肌肉率' => "Muscle Percentage",
'优' => "Excellent",
'根据人体肌肉总量和人体体重、身高等相结合得到的人体的一个比例值,这个值的范围决定一个人的身体健康状况以及力量的多少。' => "Muscle percentage is a ratio derived from total muscle mass, body weight, height, etc. Its range determines a person's health status and strength level.",
'肌肉量' => "Muscle Mass",
'不足' => "Insufficient",
'肌肉量=实际体重*肌肉率' => "Muscle Mass = Actual Weight × Muscle Percentage",
'水分' => "Body Water",
'指人体内水分比例。' => "Refers to the proportion of water in the human body.",
'蛋白量' => "Protein Mass",
'蛋白量=实际体重*蛋白率' => "Protein Mass = Actual Weight × Protein Percentage",
'骨重' => "Bone Mass",
'单位体积内,骨组织、骨矿物质(钙、磷等)和骨基质(骨胶原、蛋白率、无机盐等等)含量,骨量代表它们骨骼健康的情况。' => "Bone mass refers to the content of bone tissue, minerals (calcium, phosphorus, etc.), and bone matrix (collagen, proteins, inorganic salts, etc.) per unit volume, reflecting skeletal health.",
'蛋白率' => "Protein Percentage",
'人体内蛋白率含量。' => "The proportion of protein in the human body.",
'基础代谢' => "Basal Metabolic Rate (BMR)",
'指人体在清醒而又极端安静的状态下,不受肌肉活动、环境温度、食物及精神紧张等影响时的能量代谢率' => "The energy expenditure rate when the body is awake, completely at rest, and unaffected by muscle activity, ambient temperature, food intake, or mental stress.",
'内脏指数' => "Visceral Fat Index",
'警惕' => "Caution",
'危险' => "Danger",
'内脏脂肪指数' => "Visceral Fat Level",
'皮下脂肪' => "Subcutaneous Fat",
'皮下脂脂肪就是贮存于皮下的脂肪组织人体的脂肪大约有2/3贮存在皮下组织' => "Subcutaneous fat refers to adipose tissue stored under the skin. About two-thirds of body fat is stored subcutaneously.",
'肥胖等级' => "Obesity Level",
'体重不足' => "Underweight",
'肥胖的程度,表现实际体重与理想体重的差距。肥胖等级是判定肥胖症的一个指标。' => "Obesity level indicates the disparity between actual and ideal weight, serving as a diagnostic criterion for obesity.",
'孩子可能存在营养不良对于处在生长发育期的孩子而言蛋白质、碳水化合物、维生素和矿物质这四类营养素非常重要。建议补充足够的蛋白质、锌、钙、铁、维生素D、赖氨酸等营养。建议补充含鸡内金山楂膏健脾开胃类药食同源食物。' => "The child may be malnourished: For growing children, protein, carbohydrates, vitamins, and minerals are critical. Ensure adequate intake of protein, zinc, calcium, iron, vitamin D, lysine, etc. Consider herbal foods like chicken gizzard-hawthorn paste to improve digestion and appetite.",
'孩子可能存在营养不良对于处在生长发育期的孩子而言最有利于长高的营养素是蛋白质、碳水化合物、维生素和矿物质四类。建议补充足够的蛋白质、锌、铁、钙、维生素D、赖氨酸等营养。' => "The child may be malnourished: For children in their growth and development stage, the most beneficial nutrients for height growth are proteins, carbohydrates, vitamins, and minerals. It is recommended to ensure adequate intake of nutrients such as protein, zinc, iron, calcium, vitamin D, and lysine.",
'坚持适当、科学的跳跃运动能够科学地增加学生体重,能够改善学 生体重过低的情况;同时运动会消耗能量并加速胃肠蠕动,这会使孩子的食欲大开,再配合均衡的营养有利于孩子增重。' => "Moderate, scientifically designed jumping exercises can help underweight students gain weight by boosting energy expenditure and gastrointestinal motility, thereby increasing appetite. Combined with balanced nutrition, this supports healthy weight gain.",
'3-7岁的孩子骑两轮车、拍踢球、打篮球、游泳、爬山每天高强度运动不超过30分钟。' => "Ages 37: Bicycling, ball games, basketball, swimming, hiking. Limit high-intensity exercise to 30 minutes daily.",
'该年龄段睡眠时间建议9-11小时' => "Recommended sleep duration for this age group: 911 hours.",
'孩子开始对于赞赏、鼓励、认同和肯定有需求,而且此阶段父亲在孩子的性格塑造、情绪控制以及责任感培养方面扮演着重要的角色,必须告诉孩子什么事应该做、什么事不应该做,并经常性地给孩子一些积极地暗示。例如,可以时常向孩子表达“我会一直在你身边,不要害怕””我对你的进步都看在眼里等类似的话语。' => "Children begin to crave praise, encouragement, and validation. Fathers play a key role in shaping character, emotional regulation, and responsibility during this phase. Clearly define boundaries while offering positive affirmations (e.g., 'Im always here for you,' 'I see your progress').",
'《中华人民共和国卫生行业标准WS 423-2013》' => "《Chinese Health Industry Standard WS 423-2013》",
'《中华人民共和国卫生行业标准WS/T 612-2018》' => "《Chinese Health Industry Standard WS/T 612-2018》",
'《中华人民共和国卫生行业标准WS/T1586-2018》' => "《Chinese Health Industry Standard WS/T 1586-2018》",
'《WHO 5~19岁身高/体重判定标准》' => "《WHO Growth Reference for Children and Adolescents (519 Years)》",
'头围' => "Head Circumference",
'头围是指绕头部一周的最大长度,头围的大小与脑的发育密切相关' => "Head circumference refers to the maximum length around the head. Its measurement is closely related to brain development.",
],
// 可以添加更多语言映射
];
/**
* 处理多国语言翻译
*
* @param string $language 目标语言代码
* @param mixed $data 要翻译的数据(字符串或数组)
* @return mixed 翻译后的数据
*/
public function handling_languages_from_multiple_countries($language, $data)
{
// dump($data);
// 验证语言是否支持
if (!$this->isLanguageSupported($language)) {
return $this->msg($data['data']);
}
// 如果是数组,递归处理每个元素
if (is_array($data)) {
// dump(2);
$data = $this->translateArray($language, $data);
return $this->msg($data['data']);
}
// 如果是字符串,直接翻译
if (is_string($data)) {
// dump(3);
return $this->translateString($language, $data);
}
// dump($data);
// 其他类型直接返回
return $this->msg($data['data']);
}
/**
* 检查语言是否支持
*
* @param string $language 语言代码
* @return bool
*/
protected function isLanguageSupported($language)
{
return isset($this->supportedLanguages[$language]);
}
/**
* 翻译数组
*
* @param string $language 目标语言
* @param array $array 要翻译的数组
* @return array 翻译后的数组
*/
protected function translateArray($language, array $array)
{
$result = [];
foreach ($array as $key => $value) {
// 保持键不变,只翻译值
$result[$key] = is_array($value)
? $this->translateArray($language, $value)
: $this->translateString($language, $value);
}
return $result;
}
/**
* 翻译字符串
*
* @param string $language 目标语言
* @param string $string 要翻译的字符串
* @return string 翻译后的字符串
*/
protected function translateString($language, $string)
{
// dump($string);
// 检查是否有该语言的映射表
if (!isset($this->languageMap[$language])) {
return $string;
}
// 检查是否有对应的翻译
return $this->languageMap[$language][$string] ?? $string;
}
/**
* 获取支持的语言列表
*
* @return array
*/
public function getSupportedLanguages()
{
return $this->supportedLanguages;
}
/**
* 添加新的语言翻译
*
* @param string $language 语言代码
* @param array $translations 翻译映射数组
* @return bool
*/
public function addTranslations($language, array $translations)
{
if (!$this->isLanguageSupported($language)) {
return false;
}
if (!isset($this->languageMap[$language])) {
$this->languageMap[$language] = [];
}
$this->languageMap[$language] = array_merge(
$this->languageMap[$language],
$translations
);
return true;
}
}

View File

@ -5,6 +5,7 @@ namespace app\app\controller;
use think\Db; use think\Db;
use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\PHPMailer;
use app\app\controller\Wechat;// 引入Wechat服务类
class Login extends Base{ class Login extends Base{
@ -20,7 +21,7 @@ class Login extends Base{
################################################################接口################################################################ ################################################################接口################################################################
// 注册 // 注册
public function register_action($data = ['data'=>18530934717,'password'=>'ceshi','code'=>'746119']){ public function register_action($data = ['data'=>13408173311,'password'=>'123','code'=>'746119']){
try { try {
// 你的业务逻辑 // 你的业务逻辑
// 验证是否前段发送过来的数据 // 验证是否前段发送过来的数据
@ -46,11 +47,14 @@ class Login extends Base{
if($montage_data == false){ if($montage_data == false){
return $this->msg(10005); return $this->msg(10005);
} }
// 查询账号是否已经注册 // 查询账号是否已经注册
$inspect_repeat = Db::table($this->login_use_db_name['1'])->where([$montage_data=>$data['data'],'is_del'=>0])->count(); $inspect_repeat = Db::table($this->login_use_db_name['1'])->where([$montage_data=>$data['data'],'is_del'=>0])->count();
if($inspect_repeat >= 0){
if($inspect_repeat > 0){
return $this->msg(10002,'注册失败,账号已存在'); return $this->msg(10002,'注册失败,账号已存在');
} }
// 检查验证码 // 检查验证码
$code_result = $this->check_code($data['data'],$data['code']); $code_result = $this->check_code($data['data'],$data['code']);
if($code_result !== true){ if($code_result !== true){
@ -87,6 +91,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -151,6 +156,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -158,7 +164,6 @@ class Login extends Base{
} }
} }
// 登录 // 登录
public function login_action($data = ['data'=>'18530934717','validate_data'=>'0932','type'=>'login','validate_type'=>'password']){ public function login_action($data = ['data'=>'18530934717','validate_data'=>'0932','type'=>'login','validate_type'=>'password']){
try { try {
@ -235,6 +240,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -242,6 +248,82 @@ class Login extends Base{
} }
}
// 微信手机号快捷登录
public function wechat_quick_login(){
try {
// 你的业务逻辑
if(count(input('post.')) > 0){
$data = input('post.');
}
if(!array_key_exists('code', $data)){
// return $this->msg(10001,'');
return $this->msg(10001,'code is miss');
}
if(!array_key_exists('encryptedData', $data)){
return $this->msg(10001,'encryptedData is miss');
}
if(!array_key_exists('iv', $data)){
return $this->msg(10001,'iv is miss');
}
// 校验参数
if (empty($data['code'])) {
return $this->msg(10001,'code is miss.');
}
if (empty($data['encryptedData'])) {
return $this->msg(10001,'encryptedData is miss.');
}
if (empty($data['iv'])) {
return $this->msg(10001,'iv is miss.');
}
// 调用Wechat服务类处理微信登录逻辑
$wechatService = new Wechat();
$result = $wechatService->handleWechatLogin($data['code'], $data['encryptedData'], $data['iv']);
// die;
if($result['code'] == 0){
// return $this->msg($result['code'],$result['msg']);
$user_data = Db::table($this->login_use_db_name['1'])->where(['tel'=>$result['data']['phoneNumber'],'is_del'=>0])->find();
if($user_data){
Db::table($this->login_use_db_name['1'])->where(['token'=>$user_data['token']])->update(['login_time'=>date('Y-m-d H:i:s')]);
$return_data = $this->msg(['token'=>$user_data['token'],'aan_id'=>$user_data['id']]);
}else{
$set_data['password'] = '';
$set_data['tel'] = $result['data']['phoneNumber'];
$set_data['head_pic'] = $this->default_head_pic;
$set_data['nickname'] = '用户'.$result['data']['phoneNumber'];
$set_data['create_time'] = date('Y-m-d H:i:s');
$set_data['login_time'] = date('Y-m-d H:i:s');
$set_data['token'] = md5($result['data']['phoneNumber'].$this->create_random_string(12).time());
$set_user_result = Db::table($this->login_use_db_name['1'])->insertGetId($set_data);
if($set_user_result){
$return_data = $this->msg(['token'=>$set_data['token'],'aan_id'=>$set_user_result],'登录成功');
}else{
$return_data = $this->msg(10002);
}
}
return $return_data;
}else{
return $this->msg($result['code'],$result['msg']);
}
} catch (\Exception $e) {
// 捕获异常
$logContent["flie"] = $e->getFile();
$logContent["line"] = $e->getLine();
$logContent['all_content'] = "异常信息:\n";
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null);
return $this->msg(99999);
}
} }
// 退出登录操作 // 退出登录操作
public function user_quit_account($data=['token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function user_quit_account($data=['token'=>'0dafb98a10995c98b5a33b7d59d986ca']){
@ -263,8 +345,6 @@ class Login extends Base{
}else{ }else{
$return_data = $this->msg(10002); $return_data = $this->msg(10002);
} }
// 成功 // 成功
$this->record_api_log($data, null, $return_data); $this->record_api_log($data, null, $return_data);
return $return_data; return $return_data;
@ -276,6 +356,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -283,8 +364,6 @@ class Login extends Base{
} }
} }
// 删除账号 // 删除账号
public function delete_account($data=['token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function delete_account($data=['token'=>'0dafb98a10995c98b5a33b7d59d986ca']){
try { try {
@ -313,6 +392,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -333,7 +413,7 @@ class Login extends Base{
* $type验证类型是注册用还是其他用途 字符串 默认register注册register、login、reset_password * $type验证类型是注册用还是其他用途 字符串 默认register注册register、login、reset_password
* $road是手机还是邮箱还是其他 字符串 默认tel或email * $road是手机还是邮箱还是其他 字符串 默认tel或email
*/ */
public function send_phone_email_code($data = ['data'=>'18530934717']){ public function send_phone_email_code($data = ['data'=>'18736019909']){
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
$data = input('post.'); $data = input('post.');
@ -349,6 +429,7 @@ class Login extends Base{
$num = mt_rand(100000,999999); $num = mt_rand(100000,999999);
if (preg_match('/^\d{11}$/', $data['data'])) { if (preg_match('/^\d{11}$/', $data['data'])) {
$result = $this->send_tel_code($data['data'],$num); $result = $this->send_tel_code($data['data'],$num);
// return $this->msg($result);
$road = 'tel'; $road = 'tel';
}else{ }else{
$result = $this->send_email_code([$data['data']],['title'=>'体测APP验证码','from_user_name'=>'体测APP','content'=>$num]); $result = $this->send_email_code([$data['data']],['title'=>'体测APP验证码','from_user_name'=>'体测APP','content'=>$num]);
@ -383,26 +464,31 @@ class Login extends Base{
curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_URL, $url);
// 设置为POST请求 // 设置为POST请求
curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POST, 1);
// 设置POST数据 // 设置POST数据
$postData = array( $postData = array(
'phone' => $tel, 'phone' => $tel,
// 'content' => '您好欢迎使用Reedaw,您的手机验证码是:'.$code.',验证码三分钟内有效,若非本人操作,请忽略!' // 'content' => '您好欢迎使用Reedaw,您的手机验证码是:'.$code.',验证码三分钟内有效,若非本人操作,请忽略!'
'content' => '【Reedaw】您好欢迎使用Reedaw您的验证码是'.$code.',验证码一分钟内有效,若非本人操作,请忽略本短信' // 'content' => '【Reedaw】您好欢迎使用Reedaw您的验证码是'.$code.',验证码一分钟内有效,若非本人操作,请忽略本短信'
); 'content' => '【巨天】您好欢迎使用Reedaw您的手机验证码是'.$code.',验证码一分钟内有效,若非本人操作,请忽略本短信'
// 'content' => '【小白秤】您好欢迎使用Reedaw您的手机验证码是'.$code.',验证码一分钟内有效,若非本人操作,请忽略本短信'
// 'content' => '【品传科技】您好欢迎使用Reedaw您的手机验证码是'.$code.',验证码一分钟内有效,若非本人操作,请忽略本短信'
// 'content' => '【巨天】您好,欢迎使用巨天,您的手机验证码是:'.$code.',验证码一分钟内有效,若非本人操作,请忽略!'
);
$postData = json_encode($postData); $postData = json_encode($postData);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
// 设置返回结果不直接输出,而是返回到变量中 // 设置返回结果不直接输出,而是返回到变量中
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 发送请求并获取响应 // 发送请求并获取响应
$response = curl_exec($ch); $response = curl_exec($ch);
// 检查是否有错误发生 // 检查是否有错误发生
if (curl_errno($ch)) { if (curl_errno($ch)) {
$error_message = curl_error($ch); $error_message = curl_error($ch);
return "请求错误: " . $error_message; return "请求错误: " . $error_message;
} }
// 关闭cURL会话 // 关闭cURL会话
curl_close($ch); curl_close($ch);
// 处理响应 // 处理响应
if ($response) { if ($response) {
return json_decode($response,true); return json_decode($response,true);

View File

@ -7,6 +7,9 @@ use think\Db;
class Msginformation extends Base{ class Msginformation extends Base{
protected $judge_wechat_release = false;
protected $msginformation_use_db_name = [ protected $msginformation_use_db_name = [
'1'=>'admin_editor_text_content', '1'=>'admin_editor_text_content',
'2'=>'admin_editor_text_like_up_log', '2'=>'admin_editor_text_like_up_log',
@ -25,9 +28,7 @@ class Msginformation extends Base{
// 获取板块,及板块下类型标签 // 获取板块,及板块下类型标签
public function get_sector_label_msg($data = ['token'=>'6441bf7dabea7b3360a30240d3b19fc5']){ public function get_sector_label_msg($data = ['token'=>'6441bf7dabea7b3360a30240d3b19fc5']){
try { try {
if(count(input('post.')) > 0){ $data = input('post.');
$data = input('post.');
}
if(!array_key_exists('token', $data)){ if(!array_key_exists('token', $data)){
return $this->msg(10001); return $this->msg(10001);
} }
@ -72,6 +73,10 @@ class Msginformation extends Base{
} }
if(!$this->verify_data_is_ok($data['page'],'intnum')){ if(!$this->verify_data_is_ok($data['page'],'intnum')){
return $this->msg(10005); return $this->msg(10005);
}else{
if($data['page'] < 1){
return $this->msg(10005,'页码不能小于1');
}
} }
$return_data = $this->get_sector_content_msg_action($data); $return_data = $this->get_sector_content_msg_action($data);
@ -131,7 +136,7 @@ class Msginformation extends Base{
} }
// 获取公告文章信息列表&banner // 获取公告文章信息列表&banner
public function get_recommend_information($data=['token'=>'6441bf7dabea7b3360a30240d3b19fc5']){ public function get_recommend_information($data=['token'=>'6441bf7dabea7b3360a30240d3b19fc5']){
// try { try {
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
$data = input('post.'); $data = input('post.');
} }
@ -145,19 +150,19 @@ class Msginformation extends Base{
$return_result = $this->get_recommend_information_action($data); $return_result = $this->get_recommend_information_action($data);
$this->record_api_log($data, null, $return_result); $this->record_api_log($data, null, $return_result);
return $return_result; return $return_result;
// } catch (\Exception $e) { } catch (\Exception $e) {
// // 捕获异常 // 捕获异常
// $logContent["flie"] = $e->getFile(); $logContent["flie"] = $e->getFile();
// $logContent["line"] = $e->getLine(); $logContent["line"] = $e->getLine();
// $logContent['all_content'] = "异常信息:\n"; $logContent['all_content'] = "异常信息:\n";
// $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
// $logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
// $logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
// $logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
// $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
// $this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
// return $this->msg(99999); return $this->msg(99999);
// } }
} }
// 获取商务合作链接 // 获取商务合作链接
@ -214,9 +219,44 @@ class Msginformation extends Base{
return $this->msg(99999); return $this->msg(99999);
} }
} }
// 给微信使用的中间页(拉起微信)
// public function open_wechat_content($data=['id'=>8]){
public function open_wechat_content(){
try {
$data = input();
if(!array_key_exists('id', $data)){
$this->record_api_log($data, null, ['code'=>10001,'msg'=>'',[]]);
return $this->msg(10001);
}
$url = Db::table('admin_notice_banner')->where(['id'=>$data['id']])->field('type,jump_url')->find();
if(!$url['type'] || $url['type'] != 2){
echo '<div style="font-size: 30px;font-weight: bold;">页面跑丢了... =。=</div>';
die;
}
header('Location: '.$url['jump_url']);
} catch (\Exception $e) {
// 捕获异常
$logContent["flie"] = $e->getFile();
$logContent["line"] = $e->getLine();
$logContent['all_content'] = "异常信息:\n";
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null);
return $this->msg(99999);
}
}
################################################################业务################################################################ ################################################################业务################################################################
################################################################get_sector_label_msg ################################################################get_sector_label_msg
public function get_sector_label_msg_action($data){ public function get_sector_label_msg_action($data){
$Template_arr = [ $Template_arr = [
1=>[ 1=>[
'id'=>'1', 'id'=>'1',
@ -232,6 +272,17 @@ class Msginformation extends Base{
] ]
], ],
]; ];
if($this->judge_wechat_release === true){
$Template_arr = [
1=>[
'id'=>'1',
'name'=>'推荐',
'loop_data'=>[],
'list'=>[
]
],
];
}
// 获取需要版块id start // 获取需要版块id start
$sector = Db::query(" $sector = Db::query("
SELECT SELECT
@ -251,7 +302,6 @@ class Msginformation extends Base{
// 填充进去版块的轮播start // 填充进去版块的轮播start
$return_data = []; $return_data = [];
foreach ($sector_all as $key => $value) { foreach ($sector_all as $key => $value) {
$loop_result = Db::query(" $loop_result = Db::query("
SELECT SELECT
id, id,
@ -265,12 +315,14 @@ class Msginformation extends Base{
"); ");
if(count($loop_result) > 0){ if(count($loop_result) > 0){
foreach ($loop_result as $k => $v) { foreach ($loop_result as $k => $v) {
$loop_result[$key]['jump_url'] = "https://tc.pcxbc.com/editortext/model_content?id=".$v['id']."&token=".$data['token']; // $loop_result[$key]['jump_url'] = "https://tc.pcxbc.com/editortext/model_content?id=".$v['id']."&token=".$data['token'];
$loop_result[$key]['jump_url'] = "https://tc.pcxbc.com/editortext/model_content";
} }
} }
$Template_arr[$value]['loop_data'] = $loop_result; $Template_arr[$value]['loop_data'] = $loop_result;
array_push($return_data, $Template_arr[$value]); array_push($return_data, $Template_arr[$value]);
} }
// 填充进去版块的轮播end // 填充进去版块的轮播end
return $this->msg($return_data); return $this->msg($return_data);
} }
@ -281,6 +333,9 @@ class Msginformation extends Base{
'page_num'=>$this->page_num, 'page_num'=>$this->page_num,
'content_data'=>[] 'content_data'=>[]
]; ];
if($this->judge_wechat_release === true){
return $this->msg($return_result);
}
if($data['type'] != 0){ if($data['type'] != 0){
$type_str = " AND type LIKE '%".$data['type']."%'"; $type_str = " AND type LIKE '%".$data['type']."%'";
}else{ }else{
@ -307,7 +362,8 @@ class Msginformation extends Base{
"); ");
if(count($content_result) > 0){ if(count($content_result) > 0){
foreach ($content_result as $key => $value) { foreach ($content_result as $key => $value) {
$content_result[$key]['jump_url'] = "https://tc.pcxbc.com/editortext/model_content?id=".$value['id']."&token=".$data['token']; // $content_result[$key]['jump_url'] = "https://tc.pcxbc.com/editortext/model_content?id=".$value['id']."&token=".$data['token'];
$content_result[$key]['jump_url'] = "https://tc.pcxbc.com/editortext/model_content";
} }
} }
$return_result['content_data'] = $content_result; $return_result['content_data'] = $content_result;
@ -390,8 +446,9 @@ class Msginformation extends Base{
'notice'=>[], 'notice'=>[],
'banner'=>[] 'banner'=>[]
]; ];
// 所有可用记录 // return $this->msg($return_data);
$all_data = Db::table($this->msginformation_use_db_name['3'])->where(['is_del'=>0])->select(); // 所有可用记录.
$all_data = Db::table($this->msginformation_use_db_name['3'])->where("is_del = 0 AND scene_data IN (1,2,3)")->select();
// 用户阅读记录 // 用户阅读记录
$user_read_log = Db::table($this->msginformation_use_db_name['2'])->where(['token'=>$data['token']])->field('aetc_id')->select(); $user_read_log = Db::table($this->msginformation_use_db_name['2'])->where(['token'=>$data['token']])->field('aetc_id')->select();
$user_read_data = []; $user_read_data = [];
@ -406,12 +463,14 @@ class Msginformation extends Base{
if($value['scene_data'] != 3){ if($value['scene_data'] != 3){
unset($all_data[$key]); unset($all_data[$key]);
}else{ }else{
$all_data[$key]['jump_url'] = $all_data[$key]['jump_url']."&token=".$data['token']; // $all_data[$key]['jump_url'] = $all_data[$key]['jump_url']."&token=".$data['token'];
$all_data[$key]['jump_url'] = $all_data[$key]['jump_url'];
$all_data[$key]['type'] = 'h5'; $all_data[$key]['type'] = 'h5';
$all_data[$key]['id'] = $value['parameter_data']; $all_data[$key]['id'] = $value['parameter_data'];
} }
}else{ }else{
$all_data[$key]['jump_url'] = $all_data[$key]['jump_url']."&token=".$data['token']; // $all_data[$key]['jump_url'] = $all_data[$key]['jump_url']."&token=".$data['token'];
$all_data[$key]['jump_url'] = $all_data[$key]['jump_url'];
$all_data[$key]['type'] = 'h5'; $all_data[$key]['type'] = 'h5';
$all_data[$key]['id'] = $value['parameter_data']; $all_data[$key]['id'] = $value['parameter_data'];
} }
@ -429,6 +488,9 @@ class Msginformation extends Base{
$all_data[$key]['appid'] = $appid; $all_data[$key]['appid'] = $appid;
$all_data[$key]['path'] = $path; $all_data[$key]['path'] = $path;
// 重新定义跳转链接为中间页
$all_data[$key]['jump_url'] = "https://tc.pcxbc.com/open_wechat_content";
} }
// $all_data[$key]['id'] = $all_data[$key]['parameter_data']; // $all_data[$key]['id'] = $all_data[$key]['parameter_data'];
unset($all_data[$key]['parameter_data']); unset($all_data[$key]['parameter_data']);
@ -454,7 +516,18 @@ class Msginformation extends Base{
return $this->msg($return_data); return $this->msg($return_data);
} }
################################################################小工具################################################################
################################################################小工具################################################################
################################################################小工具################################################################
################################################################小工具################################################################
################################################################小工具################################################################
// 判断微信发版工具
public function judge_wechat_release(){
}
} }

View File

@ -20,7 +20,7 @@ class Myinformation extends Base{
################################################################接口################################################################ ################################################################接口################################################################
// 获取账号下信息 // 获取账号下信息
public function get_my_account_msg($data = ['token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function get_my_account_msg($data = ['token'=>'e0966788d02cc93290d9d674921d9715']){
try { try {
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){

View File

@ -24,13 +24,13 @@ class Pagingcontrast extends Base{
################################################请求接口################################################ ################################################请求接口################################################
################################################请求接口################################################ ################################################请求接口################################################
// 获取记录信息(分组)(包含身体、跳绳、肺活量) // 获取记录信息(分组)(包含身体、跳绳、肺活量)
public function get_all_record_data_group($data = ['aud_id'=>'26','s_time'=>'2024-04-01','e_time'=>'2024-06-12','token'=>'0dafb98a10995c98b5a33b7d59d986ca','type'=>'6']){ public function get_all_record_data_group($data = ['aud_id'=>'202','s_time'=>'2024-04-01','e_time'=>'2025-06-12','type'=>'2']){
try { try {
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
$data = input('post.'); $data = input('post.');
} }
if(!array_key_exists('aud_id', $data) || !array_key_exists('s_time', $data) || !array_key_exists('e_time', $data) || !array_key_exists('token', $data) || !array_key_exists('type', $data)){ if(!array_key_exists('aud_id', $data) || !array_key_exists('s_time', $data) || !array_key_exists('e_time', $data) || !array_key_exists('type', $data)){
$return_data = $this->msg(10001); $return_data = $this->msg(10001);
} }
if(!$this->verify_data_is_ok($data['aud_id'],'intnum')){ if(!$this->verify_data_is_ok($data['aud_id'],'intnum')){
@ -45,7 +45,6 @@ class Pagingcontrast extends Base{
if(!$this->verify_data_is_ok($data['type'],'intnum')){ if(!$this->verify_data_is_ok($data['type'],'intnum')){
return $this->msg(10005); return $this->msg(10005);
} }
unset($data['token']);
if(array_key_exists($data['type'],$this->db_name)){ if(array_key_exists($data['type'],$this->db_name)){
$return_data = $this->jump_transfer_interface_record($data,'group'); $return_data = $this->jump_transfer_interface_record($data,'group');
}else{ }else{
@ -281,9 +280,9 @@ class Pagingcontrast extends Base{
foreach ($result as $key => $value) { foreach ($result as $key => $value) {
array_push($return_result, [ array_push($return_result, [
'id'=>$value['id'], 'id'=>$value['id'],
'v1'=>$value['v1'], 'v1'=>floatval(sprintf("%.2f", $value['v1'])),
'v2'=>$value['v2'], 'v2'=>floatval(sprintf("%.2f", $value['v2'])),
'v3'=>$value['v3'], 'v3'=>floatval(sprintf("%.2f", $value['v3'])),
'v1_name'=>'身高', 'v1_name'=>'身高',
'v2_name'=>'体重', 'v2_name'=>'体重',
'v3_name'=>'BMI', 'v3_name'=>'BMI',
@ -301,9 +300,9 @@ class Pagingcontrast extends Base{
foreach ($result as $key => $value) { foreach ($result as $key => $value) {
array_push($return_result['rows'],[ array_push($return_result['rows'],[
'id'=>$value['id'], 'id'=>$value['id'],
'v1'=>$value['height_val'], 'v1'=>floatval(sprintf("%.2f", $value['height_val'])),
'v2'=>$value['weight_val'], 'v2'=>floatval(sprintf("%.2f", $value['weight_val'])),
'v3'=>$value['bmi_val'], 'v3'=>floatval(sprintf("%.2f", $value['bmi_val'])),
'v1_name'=>'身高', 'v1_name'=>'身高',
'v2_name'=>'体重', 'v2_name'=>'体重',
'v3_name'=>'BMI', 'v3_name'=>'BMI',

View File

@ -47,7 +47,11 @@ class Skip extends Base{
if(!$this->verify_data_is_ok($data['type'],'str')){ if(!$this->verify_data_is_ok($data['type'],'str')){
return $this->msg(10005); return $this->msg(10005);
} }
if(!$this->isValidInteger($data['num']+0) || !$this->isValidInteger($data['time_m']+0) || !$this->isValidInteger($data['time_s']+0)){ // {"aud_id":"331","num":"100","r_time":"2025-01-15","time_m":"","time_s":"","type":"free","token":"2581d40766e7cfd25ca140f3514072bd","aan_id":"254"}
// if(!$this->isValidInteger($data['num']+0) || !$this->isValidInteger($data['time_m']+0) || !$this->isValidInteger($data['time_s']+0)){
// $return_data = $this->msg(10005,'跳绳数量或者分钟、秒钟值必须为整数');
// }
if(!$this->verify_data_is_ok($data['num'],'intnum') || !$this->verify_data_is_ok($data['time_m'],'intnum') || !$this->verify_data_is_ok($data['time_s'],'intnum')){
$return_data = $this->msg(10005,'跳绳数量或者分钟、秒钟值必须为整数'); $return_data = $this->msg(10005,'跳绳数量或者分钟、秒钟值必须为整数');
} }
if($data['num'] <= 0){ if($data['num'] <= 0){

View File

@ -0,0 +1,124 @@
<?php
namespace app\app\controller;
use think\Db;
use PHPMailer\PHPMailer\PHPMailer;
class Wechat extends Base{
// reedaw的小程序信息
private $app_id = 'wx9c0b7a436ada6d1e'; // 微信小程序的AppID
private $app_secret = 'ed7cda5874f0eef3360e782a3db73c80'; // 微信小程序的AppSecret
// ed7cda5874f0eef3360e782a3db73c80
################################################################接口################################################################
################################################################接口################################################################
################################################################接口################################################################
/**
* 处理微信登录
*
* @param string $code 微信登录凭证
* @param string $encryptedData 加密的用户信息
* @param string $iv 解密算法的初始向量
* @return array
*/
public function handleWechatLogin($code, $encryptedData, $iv)
{
// try {
// 1. 通过code获取openid和session_key
$sessionData = $this->getSessionKey($code);
if (empty($sessionData['openid']) || empty($sessionData['session_key'])) {
// throw new Exception('获取openid或session_key失败');
// return false;
// return $this->msg(10001);
return ['code'=>10002,'msg'=>'获取openid或session_key失败'];
}
// 2. 解密用户信息
$userInfo = $this->decryptData($encryptedData, $iv, $sessionData['session_key']);
if(array_key_exists('phoneNumber',$userInfo)){
return ['code'=>0,'msg'=>'seccess','data'=>$userInfo];
}else{
return ['code'=>10002,'msg'=>'解密用户信息失败'];
}
// if (empty($userInfo['phoneNumber'])) {
// // throw new Exception('获取手机号失败');
// }else{
// }
// // 3. 保存或更新用户信息
// $user = User::where('openid', $sessionData['openid'])->find();
// if (!$user) {
// $user = new User();
// $user->openid = $sessionData['openid'];
// }
// $user->phone = $userInfo['phoneNumber'];
// $user->save();
// 返回成功信息
// return ['code' => 0, 'msg' => '登录成功', 'data' => $user];
// } catch (Exception $e) {
// // 返回错误信息
// return ['code' => 500, 'msg' => $e->getMessage()];
// }
}
/**
* 通过code获取openid和session_key
*
* @param string $code
* @return array
* @throws Exception
*/
private function getSessionKey($code)
{
$url = "https://api.weixin.qq.com/sns/jscode2session?appid={$this->app_id}&secret={$this->app_secret}&js_code={$code}&grant_type=authorization_code";
$result = file_get_contents($url);
$data = json_decode($result, true);
if (isset($data['openid']) && isset($data['session_key'])) {
return $data;
} else {
return ['code'=>10002,'msg'=>'获取openid或session_key失败'];
}
}
/**
* 解密用户信息
*
* @param string $encryptedData
* @param string $iv
* @param string $sessionKey
* @return array
* @throws Exception
*/
private function decryptData($encryptedData, $iv, $sessionKey)
{
// require_once 'wx_crypt/WXBizDataCrypt.php'; // 引入微信解密类
// require_once env('root_path') . 'extend/wx_crypt/WXBizDataCrypt.php';
// dump(ROOT_PATH . 'extend\wx_crypt\wxBizDataCrypt.php');
require_once ROOT_PATH . 'extend\wx_crypt\wxBizDataCrypt.php';
$pc = new \WXBizDataCrypt($this->app_id, $sessionKey);
$errCode = $pc->decryptData($encryptedData, $iv, $data);
if ($errCode == 0) {
return json_decode($data, true);
} else {
return ['code'=>10002,'msg'=>'解密用户信息失败('.$errCode.')'];
// throw new Exception('解密失败: ' . $errCode);
}
}
// 注册
}

View File

@ -0,0 +1,171 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1,minimum-scale=1, maximum-scale=1,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta http-equiv="Access-Control-Allow-Origin" content="*">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no, email=no">
<meta name="full-screen" content="true">
<meta name="screen-orientation" content="portrait">
<meta name="x5-fullscreen" content="true">
<meta name="360-fullscreen" content="true">
<title>deepseek测试页面</title>
<script src="/x_admin/js/jq.js"></script>
<style>
*{
padding: 0 0;
margin: 0 0;
}
.big_box{
width: 100vw;
height: 100vh;
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
}
.chat_box {
flex: 1;
/* overflow-y: auto; */
overflow-y: scroll;
padding: 10px;
border-bottom: 1px solid #ccc;
}
.input_box {
display: flex;
padding: 10px;
border-top: 1px solid #ccc;
}
.input_box input {
flex: 1;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
.input_box button {
margin-left: 10px;
padding: 10px 20px;
border: none;
background-color: #007bff;
color: white;
border-radius: 5px;
cursor: pointer;
}
.message {
margin: 10px 0;
display: flex;
}
.message.user {
justify-content: flex-end;
}
.message.bot {
justify-content: flex-start;
}
.message .content {
max-width: 70%;
padding: 10px;
border-radius: 5px;
background-color: #f1f0f0;
}
.message.user .content {
background-color: #dcf8c6;
}
.fugai{
display: none;
position: absolute;
width: 100vw;
height: 100vh;
text-align: center;
line-height: 100vh;
color: white;
font-size: 10vw;
font-weight: bold;
background-color: rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body id="box_k">
<div class="big_box">
<div class="chat_box" id="chat_box">
<!-- 对话内容将在这里展示 -->
</div>
<div class="input_box">
<input type="text" id="message_input" placeholder="输入消息..." value="我是一个河南的25岁女性身高64.52cm体重68.00kg,请根据我的这个信息,从睡眠、饮食、运动三个方向给我一些健康建议。">
<button id="send_button">发送</button>
</div>
<div class='fugai'></div>
</div>
</body>
</html>
<script>
$(document).ready(function() {
var pd = true;
$('#send_button').click(function() {
if(pd == false){
return;
}
pd = false;
var message = $('#message_input').val();
if (message.trim() === '') {
$('.fugai').html('您没有填写内容')
$('.fugai').show()
setTimeout(() => {
$('.fugai').hide()
}, 1000);
return;
}
// 显示用户消息
$('#chat_box').append('<div class="message user"><div class="content">' + message + '</div></div>');
// document.getElementById('scroll_button').addEventListener('click', function() {
// var chatBox = document.getElementById('chat_box');
// chatBox.scrollTop = chatBox.scrollHeight;
// });
// 清空输入框
$('#message_input').val('');
$('.fugai').html('思考中请稍等')
$('.fugai').show()
$.ajax({
url:"https://tc.pcxbc.com/ai/send_msg_deepseek", //请求的url地址
dataType:"json", //返回格式为json
async:true,//请求是否异步默认为异步这也是ajax重要特性
data:{"xinxi":message}, //参数值
type:"POST", //请求方式
success:function(req){
$('.fugai').hide()
pd = true;
//请求成功时处理
if(req.code == 0){
$('#chat_box').append('<div class="message bot"><div class="content">' + req.msg + '</div></div>');
}
},
error:function(){
//请求出错处理
}});
// 模拟对方回复
// setTimeout(function() {
// var reply = '对方回复: ' + message;
// $('#chat_box').append('<div class="message bot"><div class="content">' + reply + '</div></div>');
// }, 1000);
});
// // 按下回车键发送消息
// $('#message_input').keypress(function(e) {
// console.log(e)
// // if (e.which == 13) {
// // $('#send_button').click();
// // }
// });
});
</script>

View File

@ -0,0 +1,398 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1,minimum-scale=1, maximum-scale=1,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta http-equiv="Access-Control-Allow-Origin" content="*">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no, email=no">
<meta name="full-screen" content="true">
<meta name="screen-orientation" content="portrait">
<meta name="x5-fullscreen" content="true">
<meta name="360-fullscreen" content="true">
<title>商务合作</title>
<script src="/x_admin/js/jq.js"></script>
<script type="text/javascript" src="/x_admin/lib/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="/x_admin/js/xadmin.js"></script>
<style>
*{
padding: 0 0;
margin: 0 0;
}
.big_box{
width: 100vw;
min-height: 100vh;
position: absolute;
top: 0;
left: 0;
background: url(/tsf/business_bg.jpg) no-repeat;
background-size: 100% 100%;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
align-items: center;
}
.content{
width: 85vw;
max-width: 880px;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
border-radius: 1vw;
background-color: white;
margin: 24px 0;
overflow: hidden;
align-items: center;
}
.content img{
width: 100%;
height: auto;
}
.content_c{
width: 100%;
padding: 2% 12%;
box-sizing: border-box;
}
.title_t{
border: none;
text-align: center;
color: rgba(8, 14, 23, 0.9);
font-weight: 600;
font-size: 28px;
line-height: 40px;
word-break: break-all;
white-space: pre-wrap;
overflow: visible;
margin: 4% 0;
}
.title_c2{
font-size: 12px;
margin-bottom: 10%;
}
.title_c2 span{
color: rgb(17, 106, 240);
}
.write_box{
width: 100%;
font-size: 16px;
margin: 10% 0;
}
.write_box_t{
font-weight: 600;
}
.write_box_r{
color: red;
}
.write_k{
padding: 8px 12px;
position: relative;
border-radius: 6px;
border: 1px solid rgba(8, 14, 23, 0.24);
display: flex;
outline: 0 !important;
word-break: break-all;
margin: 2% 0;
}
.write_k textarea{
width: 100%;
resize: none;
text-overflow: ellipsis;
line-height: 22px;
border: none !important;
border-radius: 0;
background: transparent !important;
box-shadow: none !important;
outline: 0 !important;
cursor: auto;
padding: 0;
min-height: 22px;
margin: 0 1%;
}
.ksapc-select-write {
width: 100%;
}
.ksapc-select-write-tip {
margin-bottom: 10px;
font-size: 14px;
color: #8E9095;
}
.ksapc-select-write-tile {
width: 100%;
}
.ksapc-checkboxgroup {
width: 100%;
}
.ksapc-row {
display: flex;
flex-wrap: wrap;
gap: 14px;
}
.ksapc-col {
flex: 1 1 48%; /* 两列布局 */
}
.ksapc-checkbox {
display: flex;
align-items: center;
}
.ksapc-checkbox input {
margin-right: 8px;
}
.ksapc-checkbox span{
font-size: 14px;
cursor: pointer;
}
#onload{
width: 20vw;
height: 5vw;
min-width: 200px;
min-height: 45px;
background-color: #0A6CFF;
color: white;
border-radius: 10px;
line-height: 5vw;
text-align: center;
font-size: 15px;
font-weight: bold;
margin-bottom: 35px;
cursor: pointer; /* 添加小手图标 */
}
</style>
</head>
<body id="box_k">
<div class="big_box">
<div class="content">
<img src="/tsf/business_title.jpg" alt="">
<div class="content_c">
<div class="title_t">商务合作意向登记表</div>
<div class="title_c2">
智能设备产品包<span>含身高测量仪、体重体脂秤、宠物秤, 母婴秤,厨房秤,商业秤,身高体重/体脂秤,八电极体脂秤,运动训练设备</span>等;软件包含就智能健康管理系统,智能硬件管理系统等,支持智能设备选购/定制、健康系统对接/定制行业解决方案等您也可以直接拨打或微信联系13590959084期待与您合作
</div>
<div class="write_box">
<div class="write_box_t">
<span class="write_box_r">*</span>&nbsp; 1.客户姓名
</div>
<div class="write_k">
<textarea placeholder="请输入" rows="1" oninput="autoResize(this)" class="name-input"></textarea>
</div>
</div>
<div class="write_box">
<div class="write_box_t">
<span class="write_box_r">*</span>&nbsp; 2.联系电话
</div>
<div class="write_k">
<textarea placeholder="请输入手机号" rows="1" oninput="autoResize(this)" class="phone-input"></textarea>
</div>
</div>
<div class="write_box">
<div class="write_box_t">
<span class="write_box_r">*</span>&nbsp; 3.公司名称
</div>
<div class="write_k">
<textarea placeholder="请输入" rows="1" oninput="autoResize(this)" class="company-input"></textarea>
</div>
</div>
<div class="write_box">
<div class="write_box_t">
<span class="write_box_r">*</span>&nbsp; 4.合作意向
</div>
<div class="write_k" style="border: none;">
<div class="ksapc-select-write">
<div class="ksapc-select-write-tip" id="selectedCount">此题已选择 0/6 项</div>
<div class="ksapc-select-write-tile">
<div class="ksapc-checkboxgroup">
<div class="ksapc-row">
<div class="ksapc-col">
<label class="ksapc-checkbox">
<input type="checkbox" class="option-checkbox" value="智能设备">
<span>智能设备</span>
</label>
</div>
<div class="ksapc-col">
<label class="ksapc-checkbox">
<input type="checkbox" class="option-checkbox" value="健康软件">
<span>健康软件</span>
</label>
</div>
<div class="ksapc-col">
<label class="ksapc-checkbox">
<input type="checkbox" class="option-checkbox" value="解决方案">
<span>解决方案</span>
</label>
</div>
<div class="ksapc-col">
<label class="ksapc-checkbox">
<input type="checkbox" class="option-checkbox" value="系统定制">
<span>系统定制</span>
</label>
</div>
<div class="ksapc-col">
<label class="ksapc-checkbox">
<input type="checkbox" class="option-checkbox" value="设备定制">
<span>设备定制</span>
</label>
</div>
<div class="ksapc-col">
<label class="ksapc-checkbox">
<input type="checkbox" class="option-checkbox" value="其它">
<span>其它可联系商务合作13590959084</span>
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="write_box">
<div class="write_box_t">
<span class="write_box_r">*</span>&nbsp; 5.备注
</div>
<div class="write_k">
<textarea placeholder="请输入" rows="1" oninput="autoResize(this)" class="remark-input"></textarea>
</div>
</div>
<div class="write_box" style="color: #8E9095;">
商务合作电话/微信13590959084
</div>
</div>
<div id="onload">提交</div>
</div>
</div>
</body>
</html>
<script>
var selectedValues = [];
function autoResize(textarea) {
textarea.style.height = 'auto'; // 重置高度
textarea.style.height = textarea.scrollHeight + 'px'; // 设置为内容高度
}
document.addEventListener('DOMContentLoaded', function() {
// 获取 #onload 元素
const onloadElement = document.getElementById('onload');
// 计算 #onload 元素的高度
const height = onloadElement.offsetHeight;
// 设置 #onload 元素的行高与高度一致
onloadElement.style.lineHeight = height + 'px';
const checkboxes = document.querySelectorAll('.option-checkbox');
const selectedCountElement = document.getElementById('selectedCount');
let selectedCount = 0;
function updateSelectedCount() {
selectedCount = 0;
selectedValues = [];
checkboxes.forEach(checkbox => {
if (checkbox.checked) {
selectedCount++;
selectedValues.push(checkbox.value);
}
});
selectedCountElement.textContent = `此题已选择 ${selectedCount}/6 项`;
console.log('Selected Values:', selectedValues);
}
checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', updateSelectedCount);
});
$('#onload').on('click', function() {
// 获取所有需要检查的输入字段
const nameInput = document.querySelector('.name-input');
const phoneInput = document.querySelector('.phone-input');
const companyInput = document.querySelector('.company-input');
const remarkInput = document.querySelector('.remark-input');
// 检查每个字段是否为空
let hasError = false;
let errorMessage = '';
if (!nameInput || nameInput.value.trim() === '') {
hasError = true;
errorMessage += '1. 客户姓名\n';
}
if (!phoneInput || phoneInput.value.trim() === '') {
hasError = true;
errorMessage += '2. 联系电话\n';
}
if (!companyInput || companyInput.value.trim() === '') {
hasError = true;
errorMessage += '3. 公司名称\n';
}
if (selectedCount === 0) {
hasError = true;
errorMessage += '4. 合作意向\n';
}
if (!remarkInput || remarkInput.value.trim() === '') {
hasError = true;
errorMessage += '5. 备注\n';
}
if (hasError) {
layer.msg('以下项目未填写或未选择:\n' + errorMessage, {icon: 2});
// alert('以下项目未填写或未选择:\n' + errorMessage);
return;
}
var index = layer.load(1, {
shade: [0.1, '#fff'] //0.1透明度的白色背景
});
// 如果所有字段都填写了,执行提交操作
$.ajax({
url: "business_cooperation_action", // 请求的url地址
dataType: "json", // 返回格式为json
async: true, // 请求是否异步默认为异步这也是ajax重要特性
data: {
"name": nameInput.value,
"phone": phoneInput.value,
"company": companyInput.value,
"selectedValues": selectedValues,
"remark": remarkInput.value
},
type: "POST", // 请求方式
success: function(req) {
layer.close(layer.index)
// 请求成功时处理
if(req.code == 0){
layer.msg(req.msg, {icon: 1});
setTimeout(() => {
window.location.reload();
}, 2000);
}else{
layer.msg(req.msg, {icon: 2});
}
},
error: function() {
layer.close(layer.index)
// 请求出错处理
layer.msg('网络错误了,请直接联系商务合作电话/微信13590959084', {icon: 2});
}
});
});
});
</script>

View File

@ -16,7 +16,7 @@
<title>下载页面</title> <title>下载页面</title>
<script src="/x_admin/js/jq.js"></script> <script src="/x_admin/js/jq.js"></script>
<style> <style>
*{ *{
padding: 0 0; padding: 0 0;
margin: 0 0; margin: 0 0;
} }

View File

@ -210,7 +210,9 @@ Route::any('/testedition/card_del_record_data', 'testapp/pagingcontrast/del_all_
// 检测版本及判断是否登录失效 // 检测版本及判断是否登录失效
Route::any('/login_invalid_version', 'app/index/login_invalid_version'); Route::any('/login_invalid_version', 'app/index/login_invalid_version');
Route::any('/testedition/login_invalid_version', 'testapp/index/login_invalid_version'); Route::any('/testedition/login_invalid_version', 'testapp/index/login_invalid_version');
// 设置语言
Route::any('/set_language_country', 'app/index/set_language_country');
Route::any('/testedition/set_language_country', 'testapp/index/set_language_country');
// ################################登录接口################################ // ################################登录接口################################
// 注册接口12 // 注册接口12

View File

@ -1,6 +1,6 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Controller; use think\Controller;
use think\Db; use think\Db;
@ -11,12 +11,12 @@ use PHPMailer\PHPMailer\PHPMailer;
class Base extends Controller{ class Base extends Controller{
protected $base_use_db_name = [ protected $base_use_db_name = [
'1'=>'test_app_data_log', '1'=>'app_data_log',
'2'=>'test_app_card_data', '2'=>'app_card_data',
'3'=>'test_app_user_data', '3'=>'app_user_data',
'4'=>'test_pc_vitalcapacity_standard', '4'=>'pc_vitalcapacity_standard',
'5'=>'test_admin_estimate', '5'=>'admin_estimate',
'6'=>'test_app_account_number' '6'=>'app_account_number'
]; ];
protected $ceshiyong_token = ['57bd45e3a963b372ea2d873e4bd8d1f8','e0966788d02cc93290d9d674921d9715']; protected $ceshiyong_token = ['57bd45e3a963b372ea2d873e4bd8d1f8','e0966788d02cc93290d9d674921d9715'];
@ -141,17 +141,17 @@ class Base extends Controller{
$length = strlen($token); $length = strlen($token);
if ($length < 10 ) { if ($length < 10 ) {
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败字符串长度小于10', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败字符串长度小于10', 'token_log');
return false; return ['state'=>false,'language'=>null];
} }
}else{ }else{
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败不是字符串', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败不是字符串', 'token_log');
return false; return ['state'=>false,'language'=>null];
} }
$user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->field('id,login_time')->find(); $user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->field('id,login_time,language')->find();
if(!$user_login){ if(!$user_login){
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败未找到用户token', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败未找到用户token', 'token_log');
return false; return ['state'=>false,'language'=>null];
} }
// 创建 DateTime 对象来表示指定的日期和时间 // 创建 DateTime 对象来表示指定的日期和时间
@ -174,16 +174,16 @@ class Base extends Controller{
if ($daysDifference > $this->token_time) { if ($daysDifference > $this->token_time) {
// echo "超过 {$specifiedDays} 天"; // echo "超过 {$specifiedDays} 天";
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败原因没有找到该token,或该token已经超过30天', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败原因没有找到该token,或该token已经超过30天', 'token_log');
return false; return ['state'=>false,'language'=>$user_login['language']];
} else { } else {
// echo "未超过 {$specifiedDays} 天"; // echo "未超过 {$specifiedDays} 天";
$user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->update(['login_time'=>date('Y-m-d H:i:s')]); $user_login = Db::table($this->base_use_db_name['6'])->where(['token'=>$token])->update(['login_time'=>date('Y-m-d H:i:s')]);
if($user_login){ if($user_login){
Log::record('用户尝试更新token时间token' . $token.',记录成功,最新的时间为'.date('Y-m-d H:i:s'), 'token_log'); Log::record('用户尝试更新token时间token' . $token.',记录成功,最新的时间为'.date('Y-m-d H:i:s'), 'token_log');
return true; return ['state'=>true,'language'=>$user_login['language']];
}else{ }else{
Log::record('用户尝试更新token时间token' . $token.',但是更新token失败数据库更新时间未成功', 'token_log'); Log::record('用户尝试更新token时间token' . $token.',但是更新token失败数据库更新时间未成功', 'token_log');
return true; return ['state'=>true,'language'=>$user_login['language']];
} }
} }
@ -614,7 +614,7 @@ class Base extends Controller{
// 处理身高体重的单位转换它们为cm和kg。 // 处理身高体重的单位转换它们为cm和kg。
function convertHeightAndWeight($height, $weight) { public function convertHeightAndWeight($height, $weight) {
// 加 bcadd(,,20) // 加 bcadd(,,20)
// 减 bcsub(,,20) // 减 bcsub(,,20)
// 乘 bcmul(,,20) // 乘 bcmul(,,20)
@ -709,6 +709,8 @@ class Base extends Controller{
public function ceshiyong($aa = 4,$gd = 0.2){ public function ceshiyong($aa = 4,$gd = 0.2){
$token = 'cd3f27cf4c4002170ea7bceeb723ac91'; $token = 'cd3f27cf4c4002170ea7bceeb723ac91';

View File

@ -1,6 +1,6 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Controller; use think\Controller;

View File

@ -1,25 +1,25 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Db; use think\Db;
use app\testapp\controller\Calculatebody; use app\app\controller\Calculatebody;
use app\testapp\controller\Cardparts; use app\app\controller\Cardparts;
class Card extends Base{ class Card extends Base{
protected $color = ['#FF5656','#FFAB00','#5AD06D','#6492F6','#3967D6']; protected $color = ['#FF5656','#FFAB00','#5AD06D','#6492F6','#3967D6'];
protected $card_use_db_name = [ protected $card_use_db_name = [
'1'=>'test_app_card_body_data', '1'=>'app_card_body_data',
'2'=>'test_app_user_data', '2'=>'app_user_data',
'3'=>'test_pc_bmistand', '3'=>'pc_bmistand',
'4'=>'test_pc_heightstand', '4'=>'pc_heightstand',
'5'=>'test_pc_weightstand', '5'=>'pc_weightstand',
'6'=>'test_pc_childrenprescription', '6'=>'pc_childrenprescription',
'7'=>'test_pc_childprescriptionbyage', '7'=>'pc_childprescriptionbyage',
'8'=>'test_pc_heightstand', '8'=>'pc_heightstand',
'9'=>'test_pc_weightstand', '9'=>'pc_weightstand',
'10'=>'test_pc_bmistand', '10'=>'pc_bmistand',
]; ];
protected $age_limit = 16; protected $age_limit = 16;
protected $unit_symbol = ['score'=>'分','height'=>'CM','weight'=>'公斤','bmi'=>'','fat_r'=>'%','fat_w'=>'kg','muscle'=>'%','muscleval'=>'kg','water'=>'kg','bone'=>'kg','protein'=>'%','proteinval'=>'kg','kcal'=>'kcal','visceral'=>'','sfr'=>'%',]; protected $unit_symbol = ['score'=>'分','height'=>'CM','weight'=>'公斤','bmi'=>'','fat_r'=>'%','fat_w'=>'kg','muscle'=>'%','muscleval'=>'kg','water'=>'kg','bone'=>'kg','protein'=>'%','proteinval'=>'kg','kcal'=>'kcal','visceral'=>'','sfr'=>'%',];
@ -88,7 +88,7 @@ class Card extends Base{
// 详细卡片信息 // 详细卡片信息
// $data = ['id'=>'2'] // $data = ['id'=>'2']
public function card_data_detailed($data=['aud_id'=>'38']){ public function card_data_detailed($data=['aud_id'=>'144']){
try { try {
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
@ -100,9 +100,10 @@ class Card extends Base{
if(!$this->verify_data_is_ok($data['aud_id'],'intnum')){ if(!$this->verify_data_is_ok($data['aud_id'],'intnum')){
return $this->msg(10005); return $this->msg(10005);
} }
// $return_data;
$return_data = $this->get_user_body_data($data); $return_data = $this->get_user_body_data($data);
// 成功 // $language_data = new Language();
$this->record_api_log($data, null, $return_data); // $return_data = $language_data->handling_languages_from_multiple_countries('en', $return_data->getData());
return $return_data; return $return_data;
} catch (\Exception $e) { } catch (\Exception $e) {
// 捕获异常 // 捕获异常
@ -241,7 +242,7 @@ class Card extends Base{
// 设备记录 // 设备记录
// $data = ['id'=>'2','time'=>'1991-04-20 10:10:10','height'=>'15.1','weight'=>'75.1'] // $data = ['id'=>'2','time'=>'1991-04-20 10:10:10','height'=>'15.1','weight'=>'75.1']
// public function card_manual_recording_device($data = ['aud_id'=>'37','height'=>'169.60,inch','weight'=>'52.45,lb','adc'=>'520.3','token'=>'591b70e0d80b5fa6d77e6e1384453ab9']){ // public function card_manual_recording_device($data = ['aud_id'=>'37','height'=>'169.60,inch','weight'=>'52.45,lb','adc'=>'520.3','token'=>'591b70e0d80b5fa6d77e6e1384453ab9']){
public function card_manual_recording_device($data = ['aud_id'=>'37','height'=>'6-10ft-in','weight'=>'2:5.07st:lb','adc'=>'520.3','token'=>'591b70e0d80b5fa6d77e6e1384453ab9']){ public function card_manual_recording_device($data = ['aud_id'=>'37','height'=>'169.60斤','weight'=>'52.45斤','adc'=>'520.3','token'=>'591b70e0d80b5fa6d77e6e1384453ab9']){
try { try {
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
@ -267,7 +268,34 @@ class Card extends Base{
} }
$data['height'] = $temporary_data['height_in_cm']; $data['height'] = $temporary_data['height_in_cm'];
$data['weight'] = $temporary_data['weight_in_kg']; $data['weight'] = $temporary_data['weight_in_kg'];
die;
// if(!$this->verify_data_is_ok($data['height'],'num')){
// return $this->msg(10005);
// }
// if(!$this->verify_data_is_ok($data['weight'],'num')){
// return $this->msg(10005);
// }
// $data['height'] = explode(',',$data['height']);
// if(count($data['height']) < 2){
// return $this->msg(10005);
// }
// if(!$this->verify_data_is_ok($data['height'][0],'num')){
// return $this->msg(10005);
// }
// if(!in_array($data['height'][1],$this->unit_data['height'])){
// return $this->msg(10005);
// }
// $data['weight'] = explode(',',$data['weight']);
// if(count($data['height']) < 2){
// return $this->msg(10005);
// }
// if(!$this->verify_data_is_ok($data['weight'][0],'num')){
// return $this->msg(10005);
// }
// if(!in_array($data['weight'][1],$this->unit_data['weight'])){
// return $this->msg(10005);
// }
$data['time'] = date('Y-m-d H:i:s'); $data['time'] = date('Y-m-d H:i:s');
$data['acd_id'] = '2'; $data['acd_id'] = '2';
$return_data = $this->set_user_body_data($data,'by_device'); $return_data = $this->set_user_body_data($data,'by_device');
@ -564,9 +592,11 @@ class Card extends Base{
// 处理返回数据 // 处理返回数据
$result_end = $this->processing_return_data_new($result[0]); $result_end = $this->processing_return_data_new($result[0]);
$cardparts = new Cardparts; $cardparts = new Cardparts;
$result_end['gender'] = $result[0]['gender']; $result_end['gender'] = $result[0]['gender'];
$result_end['record_time'] = $result[0]['record_time']; $result_end['record_time'] = $result[0]['record_time'];
$result_end['score'] = $result_end['score']; $result_end['score'] = $result_end['score'];
$result_end['body_type'] = $result_end['body_type']; $result_end['body_type'] = $result_end['body_type'];
$result_end = $cardparts->conversion_interval($result_end); $result_end = $cardparts->conversion_interval($result_end);
@ -578,6 +608,7 @@ class Card extends Base{
'bmi'=>$result[0]['bmi'] 'bmi'=>$result[0]['bmi']
], ],
]); ]);
// 只有含有阻抗的记录才有数据参考 // 只有含有阻抗的记录才有数据参考
if($result[0]['record_type'] == 'by_device_adc'){ if($result[0]['record_type'] == 'by_device_adc'){
if(count($result_end['cplist']['nutritionlist']) <= 0){ if(count($result_end['cplist']['nutritionlist']) <= 0){
@ -601,7 +632,7 @@ class Card extends Base{
'initial_weight'=>$result[0]['initial_weight']>0?$result[0]['initial_weight']:0, 'initial_weight'=>$result[0]['initial_weight']>0?$result[0]['initial_weight']:0,
'initial_date'=>$result[0]['initial_date']!=null?$result[0]['initial_date']:0, 'initial_date'=>$result[0]['initial_date']!=null?$result[0]['initial_date']:0,
]); ]);
// dump($result_end);
if(count($result_end['top_list'][2]['list']) <= 0){ if(count($result_end['top_list'][2]['list']) <= 0){
// 这是16岁以上人群 // 这是16岁以上人群
$data = [ $data = [
@ -612,15 +643,20 @@ class Card extends Base{
]; ];
$temporary_arr_bmi_list = $this->card_bmi_evaluation($data,true); $temporary_arr_bmi_list = $this->card_bmi_evaluation($data,true);
// dump($temporary_arr_bmi_list);
$temporary_arr_bmi_list = $temporary_arr_bmi_list->getData(); $temporary_arr_bmi_list = $temporary_arr_bmi_list->getData();
// dump($temporary_arr_bmi_list);
// die;
if($temporary_arr_bmi_list['code'] == 0){ if($temporary_arr_bmi_list['code'] == 0){
$result_end['top_list'][2]['standard'] = $temporary_arr_bmi_list['data']['bmilevel']; $result_end['top_list'][2]['standard'] = $temporary_arr_bmi_list['data']['bmilevel'];
$result_end['top_list'][2]['color'] = $temporary_arr_bmi_list['data']['bmilevelcolor']; $result_end['top_list'][2]['color'] = $temporary_arr_bmi_list['data']['bmilevelcolor'];
$result_end['top_list'][2]['list'] = $temporary_arr_bmi_list['data']['bmilevellist']; $result_end['top_list'][2]['list'] = $temporary_arr_bmi_list['data']['bmilevellist'];
$result_end['top_list'][2]['offset'] = $temporary_arr_bmi_list['data']['offset']; $result_end['top_list'][2]['offset'] = $temporary_arr_bmi_list['data']['offset'];
} }
// dump($result_end);
// die;
} }
// 加入曲线板块底部的减肥计划数据end // 加入曲线板块底部的减肥计划数据end
// 添加头围数据如果有的话start // 添加头围数据如果有的话start
if($head_circumference !== false && $this->calculate_age($result[0]['birthday']) < 3){ if($head_circumference !== false && $this->calculate_age($result[0]['birthday']) < 3){
@ -637,7 +673,7 @@ class Card extends Base{
'color'=>'', 'color'=>'',
'list'=>$head_circumference['list2'], 'list'=>$head_circumference['list2'],
'key_name'=>'head_circumference', 'key_name'=>'head_circumference',
'desc'=>'头围是指绕头部一周的最大长度,头围的大小与的发育密切相关', 'desc'=>'头围是指绕头部一周的最大长度,头围的大小与的发育密切相关',
'offset'=>$offset 'offset'=>$offset
]); ]);
} }
@ -755,6 +791,7 @@ class Card extends Base{
$min_key = array_search($min_value,$temporary_arr); $min_key = array_search($min_value,$temporary_arr);
$type_num = $this->card_body_level[$min_key]['value']; $type_num = $this->card_body_level[$min_key]['value'];
$temporary_arr2 = Db::table($this->card_use_db_name['6'])->where(['Type'=>$type_num,'Level'=>$min_value,'IsDeleted'=>0])->field('Nutrition,Sport')->find(); $temporary_arr2 = Db::table($this->card_use_db_name['6'])->where(['Type'=>$type_num,'Level'=>$min_value,'IsDeleted'=>0])->field('Nutrition,Sport')->find();
// dump($temporary_arr2);
array_push($result['nutritionlist'],$temporary_arr2['Nutrition']); array_push($result['nutritionlist'],$temporary_arr2['Nutrition']);
array_push($result['sportlist'],$temporary_arr2['Sport']); array_push($result['sportlist'],$temporary_arr2['Sport']);
// $result['nutritionlist'] = $temporary_arr2['Nutrition']; // $result['nutritionlist'] = $temporary_arr2['Nutrition'];
@ -871,6 +908,7 @@ class Card extends Base{
// // 这里开始转换不同单位的身高体重为cm跟kgend // // 这里开始转换不同单位的身高体重为cm跟kgend
// $adc_type = $type; // $adc_type = $type;
// $data['type'] = 1; // $data['type'] = 1;
// 判断头围数据是否存在是否合理 // 判断头围数据是否存在是否合理
if(array_key_exists('head_data', $data)){ if(array_key_exists('head_data', $data)){
if(!$this->verify_data_is_ok($data['head_data'],'num')){ if(!$this->verify_data_is_ok($data['head_data'],'num')){

View File

@ -1,6 +1,6 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
class Cardparts extends Base{ class Cardparts extends Base{
@ -191,10 +191,10 @@ class Cardparts extends Base{
'bottom_list'=>[], 'bottom_list'=>[],
]; ];
// die; // die;
$date_temporary = new \DateTime($temporary_arr['record_time']); // $date_temporary = new \DateTime($temporary_arr['record_time']);
// 使用 format 方法来指定新的日期和时间格式 // 使用 format 方法来指定新的日期和时间格式
$temporary_arr['record_time'] = $date_temporary->format('Y年m月d日 H:i:s'); // $temporary_arr['record_time'] = $date_temporary->format('Y年m月d日 H:i:s');
// 处理格式(顶部) // 处理格式(顶部)
foreach ($this->parameter_aggregate_top as $key => $value) { foreach ($this->parameter_aggregate_top as $key => $value) {
$data[$key]['key_name'] = $key; $data[$key]['key_name'] = $key;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Db; use think\Db;
use Exception; use Exception;
@ -8,11 +8,11 @@ use Exception;
class Cardpublic extends Base{ class Cardpublic extends Base{
protected $cardpublic_use_db_name = [ protected $cardpublic_use_db_name = [
'1'=>'test_app_user_data', '1'=>'app_user_data',
'2'=>'test_app_card_data_sub_item', '2'=>'app_card_data_sub_item',
'3'=>'test_app_card_data_sub_item_data', '3'=>'app_card_data_sub_item_data',
'4'=>'test_admin_estimate', '4'=>'admin_estimate',
'5'=>'test_app_card_data' '5'=>'app_card_data'
]; ];
protected $curve_color = ['#f7b03e','#fb7b92','#ff9f40','#3fcba7',]; protected $curve_color = ['#f7b03e','#fb7b92','#ff9f40','#3fcba7',];

View File

@ -0,0 +1,210 @@
<?php
namespace app\app\controller;
use think\Db;
class Deepseek extends Base{
protected $msginformation_use_db_name = [
'1'=>'admin_editor_text_content',
'2'=>'admin_editor_text_like_up_log',
'3'=>'admin_notice_banner',
'4'=>'admin_business_cooperation'
];
protected $page_num = 10;
// 加 bcadd(,,20)
// 减 bcsub(,,20)
// 乘 bcmul(,,20)
// 除 bcdiv(,,20)
################################################################接口################################################################
################################################################接口################################################################
################################################################接口################################################################
public function test_index(){
return $this->fetch();
}
// 获取板块,及板块下类型标签
public function send_msg_deepseek(){
// dump('456');
// die;
try {
$data = input('post.');
// dump($data);
// dump(array_key_exists('xinxi', $data));
if(!array_key_exists('xinxi', $data)){
return $this->msg(10001);
}
if(!$this->verify_data_is_ok($data['xinxi'],'str')){
return $this->msg(10005);
}
// $data['msg'] = "";
// dump($data);
// die;
$return_data = $this->deepseek_only_onec_action($data);
// $return_data = $this->deepseek_ceshiyongjiekou($data);
return $return_data;
} catch (\Exception $e) {
// 捕获异常
$logContent["flie"] = $e->getFile();
$logContent["line"] = $e->getLine();
$logContent['all_content'] = "异常信息:\n";
$logContent['all_content'] = "接口send_msg_deepseek\n";
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log([], $logContent, null);
return $this->msg(99999);
}
}
public function deepseek_only_onec_action($xinxi){
// DeepSeek API密钥
// $apiKey = 'sk-28dd23215ef84772b64d77011419e271';
$apiKey = 'bd739e8c-91af-40bb-85d4-0804060b2390';
// DeepSeek API的端点
// $apiUrl = 'https://api.deepseek.com/v1/chat/completions';
$apiUrl = 'https://ark.cn-beijing.volces.com/api/v3/chat/completions';
// 准备请求数据
$data = [
"messages" => [
[
"content" => "你是一个有关身体健康的专家,能根据用户提供的身体数据给出对应的分析和建议",
"role" => "system"
],
[
"content" => $xinxi['xinxi'],
"role" => "user"
]
],
// "model" => "deepseek-chat",
"model" => "ep-20250304141108-x9d7l",
"frequency_penalty" => 0,
"max_tokens" => 2048,
"presence_penalty" => 0,
"response_format" => [
"type" => "text" //指定生成文本的格式。"type": 指定格式类型,例如"text"(纯文本)或"json"JSON格式
],
"stop" => null,
"stream" => false,
"stream_options" => null,
"temperature" => 1,
"top_p" => 1,
"tools" => null,
"tool_choice" => "none",
"logprobs" => false,
"top_logprobs" => null
];
// 初始化cURL会话
$ch = curl_init();
// 设置cURL选项
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 禁用证书验证
curl_setopt($ch, CURLOPT_URL, $apiUrl); // 设置API URL
curl_setopt($ch, CURLOPT_POST, true); // 使用POST方法
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); // 设置POST数据
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $apiKey, // 设置API密钥
'Content-Type: application/json', // 设置请求头为JSON
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回响应而不是直接输出
// 执行cURL请求并获取响应
$response = curl_exec($ch);
// 检查是否有cURL错误
if (curl_errno($ch)) {
echo 'cURL请求失败: ' . curl_error($ch);
} else {
// 获取HTTP状态码
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode === 200) {
// 解析JSON响应
$result = json_decode($response, true);
// print_r($result); // 输出API响应
return $this->msg(0,$result['choices'][0]['message']['content']);
// dump($result);
} else {
return $this->msg(['code'=>$httpCode]);
// echo 'API请求失败HTTP状态码: ' . $httpCode;
// echo '响应内容: ' . $response;
}
}
// 关闭cURL会话
curl_close($ch);
}
public function deepseek_ceshiyongjiekou(){
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.deepseek.com/chat/completions',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"messages": [
{
"content": "You are a helpful assistant",
"role": "system"
},
{
"content": "Hi",
"role": "user"
}
],
"model": "deepseek-chat",
"frequency_penalty": 0,
"max_tokens": 2048,
"presence_penalty": 0,
"response_format": {
"type": "text"
},
"stop": null,
"stream": false,
"stream_options": null,
"temperature": 1,
"top_p": 1,
"tools": null,
"tool_choice": "none",
"logprobs": false,
"top_logprobs": null
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Accept: application/json',
'Authorization: Bearer <TOKEN>'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
}
}

View File

@ -1,6 +1,6 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Db; use think\Db;
use think\Log; use think\Log;
@ -10,9 +10,9 @@ class Device extends Base{
protected $color = ['#FF5656','#FFAB00','#5AD06D','#6492F6','#3967D6']; protected $color = ['#FF5656','#FFAB00','#5AD06D','#6492F6','#3967D6'];
protected $device_use_db_name = [ protected $device_use_db_name = [
'1'=>'test_app_device_data', '1'=>'app_device_data',
'2'=>'test_app_account_number', '2'=>'app_account_number',
'3'=>'test_app_device_code_data', '3'=>'app_device_code_data',
]; ];

View File

@ -1,22 +1,31 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Controller; use think\Controller;
use think\Db; use think\Db;
class Download extends Base{ class Download extends Base{
public function demo(){ public function demo(){
// $num = Db::table('app_version_log')->order('id desc')->find();
// echo '你好,这里仅仅是个下载展示页面-1';
// echo '<br><a href="'.$num['download_url'].'">点击下载</a>';
$url = Db::table('app_version_log')->order('id desc')->find(); $url = Db::table('app_version_log')->order('id desc')->find();
$this->assign([ $this->assign([
'url' => $url['download_url'], 'url' => $url['download_url'],
]); ]);
return $this->fetch(); return $this->fetch();
} }
public function demo2(){ public function demo2(){
$url = Db::table('app_version_log')->order('id desc')->find(); $url = Db::table('app_version_log')->order('id desc')->find();
$this->assign([ $this->assign([
'url' => $url['download_url'], 'url' => $url['download_url'],
]); ]);
return $this->fetch(); return $this->fetch();
@ -37,21 +46,13 @@ class Download extends Base{
'create_time'=>date('Y-m-d H:i:s'), 'create_time'=>date('Y-m-d H:i:s'),
]); ]);
if($result){ if($result){
$this->send_email_api_error(["tsf3920322@126.com"],['title'=>'商户合作','from_user_name'=>'reedaw商务','content'=>'有一封商户合作']);
return json(['code'=>0,'msg'=>'提交成功']); return json(['code'=>0,'msg'=>'提交成功']);
}else{ }else{
return json(['code'=>10001,'msg'=>'网络错误,请直接联系商务合作电话/微信13590959084']); return json(['code'=>10001,'msg'=>'网络错误,请直接联系商务合作电话/微信13590959084']);
} }
} }
#########################################################################其它#########################################################################
#########################################################################其它#########################################################################
#########################################################################其它#########################################################################
public function ceshi(){ public function ceshi(){
$data = input(); $data = input();
$url = 'https://klcz.pcxbc.com/open-api/calc/healthcalc/bodyfat3'; $url = 'https://klcz.pcxbc.com/open-api/calc/healthcalc/bodyfat3';

View File

@ -1,24 +1,26 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Db; use think\Db;
use \think\Validate; use \think\Validate;
use app\app\controller\Language;
// use ip2region\Ip2Region;
class Index extends Base{ class Index extends Base{
protected $moren_gufen_diqu = '北京,北京'; protected $moren_gufen_diqu = '北京,北京';
protected $db_name = ['2'=>'test_app_card_body_data','6'=>'test_app_card_skip_data','8'=>'test_app_card_vitalcapacity_data','10'=>'test_app_card_data_sub_item_data']; protected $db_name = ['2'=>'app_card_body_data','6'=>'app_card_skip_data','8'=>'app_card_vitalcapacity_data','10'=>'app_card_data_sub_item_data'];
protected $index_use_db_name = [ protected $index_use_db_name = [
'1'=>'test_app_version_log', '1'=>'app_version_log',
'2'=>'test_app_user_data', '2'=>'app_user_data',
'3'=>'test_app_card_body_data', '3'=>'app_card_body_data',
'4'=>'test_app_device_code_data', '4'=>'app_device_code_data',
'5'=>'test_app_device_data', '5'=>'app_device_data',
'6'=>'test_app_card_data', '6'=>'app_card_data',
'7'=>'test_app_account_number', '7'=>'app_account_number',
'8'=>'test_app_card_data_sub_item', '8'=>'app_card_data_sub_item',
'9'=>'test_app_card_data_sub_item_data', '9'=>'app_card_data_sub_item_data',
'10'=>'test_admin_estimate' '10'=>'admin_estimate'
]; ];
// protected $card_key = ['2'=>'body','6'=>'skip','8'=>'vitalcapacity']; // protected $card_key = ['2'=>'body','6'=>'skip','8'=>'vitalcapacity'];
protected $default_card = ['2','6','8']; protected $default_card = ['2','6','8'];
@ -30,10 +32,10 @@ class Index extends Base{
]; ];
protected $data_name_unit = [ protected $data_name_unit = [
'height'=>['身高','cm','test_pc_heightstand2'], 'height'=>['身高','cm','pc_heightstand2'],
'weight'=>['体重','公斤','test_pc_weightstand2'], 'weight'=>['体重','公斤','pc_weightstand2'],
'bmi'=>['BMI','','test_pc_bmistand2'], 'bmi'=>['BMI','','pc_bmistand2'],
'average'=>['肺活量','ml','test_pc_vitalcapacity_standard'] 'average'=>['肺活量','ml','pc_vitalcapacity_standard']
]; ];
protected $identity_list = ['P0'=>'陌生人','P1'=>'爸爸','P2'=>'妈妈','P3'=>'大宝','P4'=>'二宝','P5'=>'三宝','P6'=>'四宝','P7'=>'爷爷','P8'=>'奶奶']; protected $identity_list = ['P0'=>'陌生人','P1'=>'爸爸','P2'=>'妈妈','P3'=>'大宝','P4'=>'二宝','P5'=>'三宝','P6'=>'四宝','P7'=>'爷爷','P8'=>'奶奶'];
// protected $nickname_data2 = ['爸爸','妈妈','大宝','二宝','爷爷','奶奶','外公','外婆']; // protected $nickname_data2 = ['爸爸','妈妈','大宝','二宝','爷爷','奶奶','外公','外婆'];
@ -60,6 +62,39 @@ class Index extends Base{
['min'=>'3','max'=>'16','value'=>'儿童'], ['min'=>'3','max'=>'16','value'=>'儿童'],
['min'=>'16','max'=>'500','value'=>'成人'] ['min'=>'16','max'=>'500','value'=>'成人']
]; ];
protected $language_country = [
'en' => 'English', // 英语(通用)★
'zh' => '中文', // 中文(简体)★
// 'es' => 'Español', // 西班牙语(西班牙)★
// 'fr' => 'Français', // 法语(法国)★
// 'pt' => 'Português', // 葡萄牙语(巴西)★
// 'ar' => 'العربية', // 阿拉伯语(标准)★
// 'ru' => 'Русский', // 俄语(俄罗斯)★
// 'de' => 'Deutsch', // 德语(德国)★
// 'ja' => '日本語', // 日语
// 'ko' => '한국어', // 韩语
// 'it' => 'Italiano', // 意大利语
// 'nl' => 'Nederlands', // 荷兰语
// 'hi' => 'हिन्दी', // 印地语
// 'tr' => 'Türkçe', // 土耳其语
// 'vi' => 'Tiếng Việt', // 越南语
// 'th' => 'ไทย', // 泰语
// 'pl' => 'Polski', // 波兰语
// 'sv' => 'Svenska', // 瑞典语
// 'fi' => 'Suomi', // 芬兰语
// 'da' => 'Dansk', // 丹麦语
// 'no' => 'Norsk', // 挪威语
// 'he' => 'עברית', // 希伯来语
// 'id' => 'Bahasa Indonesia', // 印尼语
// 'ms' => 'Bahasa Melayu', // 马来语
// 'cs' => 'Čeština', // 捷克语
// 'hu' => 'Magyar', // 匈牙利语
// 'el' => 'Ελληνικά', // 希腊语
// 'ro' => 'Română', // 罗马尼亚语
// 'sk' => 'Slovenčina', // 斯洛伐克语
// 'uk' => 'Українська', // 乌克兰语
];
################################################################个人资料卡################################################################ ################################################################个人资料卡################################################################
@ -67,8 +102,35 @@ class Index extends Base{
################################################################个人资料卡################################################################ ################################################################个人资料卡################################################################
// 检测版本及判断是否登录失效 // 检测版本及判断是否登录失效
public function login_invalid_version($data = ['token'=>'']){ public function login_invalid_version($data = ['token'=>'caadd1be045a65f30b92aa805f1de54a']){
try { try {
// 获取客户端IP
$ip = request()->ip();
// 调用IP识别方法
$region = $this->getIpInfo($ip);
// 解析地区信息
$regionParts = explode('|', $region);
$country = $regionParts[0] ?? '';
// 判断国家是否在支持的语言列表中
$language = '';
if ($country && $country !== '0') {
$languageMap = [
'中国' => 'zh-Hans',
'美国' => 'en',
'英国' => 'en',
'西班牙' => 'es',
'法国' => 'fr',
'葡萄牙' => 'pt',
'阿拉伯联合酋长国' => 'ar',
'俄罗斯' => 'ru',
'德国' => 'de'
];
$language = $languageMap[$country] ?? '';
}
// 检查语言是否在支持列表中
$language_all = new Language();
$isSupportedLanguage = array_key_exists($language, $language_all->getSupportedLanguages());
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
$data = input('post.'); $data = input('post.');
@ -84,12 +146,18 @@ class Index extends Base{
$version = ''; $version = '';
$url = ''; $url = '';
} }
if($this->token_time_validate($data['token']) === false){ $user_token_state = $this->token_time_validate($data['token']);
$this->record_api_log($data, null, ['code'=>-1,'msg'=>'未登录',['version'=>$version,'url'=>$url]]);
return $this->msg(-1,'未登录',['version'=>$version,'url'=>$url]); $user_language_data = Db::table($this->index_use_db_name['7'])->where(['token'=>$data['token']])->field('language')->find();
if($user_language_data != null){
$language_data = $user_language_data['language'];
}else{ }else{
$this->record_api_log($data, null, ['code'=>0,'msg'=>'success',['version'=>$version,'url'=>$url]]); $language_data = $this->pd_language($user_token_state['language'],$isSupportedLanguage,$language);
return $this->msg(['version'=>$version,'url'=>$url]); }
if($user_token_state['state'] === false){
return $this->msg(-1,'未登录',['version'=>$version,'url'=>$url,'language'=>$language_data,'language_arr'=>$this->language_country]);
}else{
return $this->msg(['version'=>$version,'url'=>$url,'language'=>$language_data,'language_arr'=>$this->language_country]);
} }
} catch (\Exception $e) { } catch (\Exception $e) {
@ -100,12 +168,62 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
return $this->msg(99999); return $this->msg(99999);
} }
} }
// 添加IP信息获取方法
protected function getIpInfo($ip) {
// 默认IP
$ip = $ip ?: request()->ip();
try {
$ip2region = new \Ip2Region();
$info = $ip2region->memorySearch($ip);
// 返回国家信息
return $info['region'] ?: '未知';
} catch (\Exception $e) {
return '未知';
}
}
public function set_language_country($data = ['token'=>'caadd1be045a65f30b92aa805f1de54a','language'=>'zh']){
try {
// 你的业务逻辑
if(count(input('post.')) > 0){
$data = input('post.');
}
if(!array_key_exists('token', $data) || !array_key_exists('language', $data)){
return $this->msg(10001);
}
if(!array_key_exists($data['language'],$this->language_country)){
return $this->msg(10007);
}
$result = Db::table($this->index_use_db_name['7'])->where(['token'=>$data['token']])->update(['language'=>$data['language']]);
if($result){
return $this->msg([]);
}else{
return $this->msg(10002);
}
} catch (\Exception $e) {
$logContent["flie"] = $e->getFile();
$logContent["line"] = $e->getLine();
$logContent['all_content'] = "异常信息:\n";
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null);
return $this->msg(99999);
}
}
// 创建用户 // 创建用户
public function create_user_data($data = ['aan_id'=>1,'height'=>'152.3','weight'=>'35.4','nickname'=>'钮祜禄测试1','birthday'=>'2019-04-20','gender'=>1,'grade'=>'grade_s_3','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'57bd45e3a963b372ea2d873e4bd8d1f8']){ public function create_user_data($data = ['aan_id'=>1,'height'=>'152.3','weight'=>'35.4','nickname'=>'钮祜禄测试1','birthday'=>'2019-04-20','gender'=>1,'grade'=>'grade_s_3','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'57bd45e3a963b372ea2d873e4bd8d1f8']){
@ -143,14 +261,12 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
return $this->msg(99999); return $this->msg(99999);
} }
} }
// 修改用户 // 修改用户
public function update_user_data($data = ['id'=>66,'nickname'=>'王小二','birthday'=>'2019-01-01','gender'=>1,'grade'=>'二年级','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function update_user_data($data = ['id'=>66,'nickname'=>'王小二','birthday'=>'2019-01-01','gender'=>1,'grade'=>'二年级','identity_id'=>'P3','identity_name'=>'大宝','address'=>'河南,郑州','token'=>'0dafb98a10995c98b5a33b7d59d986ca']){
@ -187,6 +303,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -230,6 +347,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -238,7 +356,6 @@ class Index extends Base{
} }
// 获取账号下用户列表 // 获取账号下用户列表
// $type 1获取列表2获取详细信息 // $type 1获取列表2获取详细信息
public function get_user_card_list($data = ['aan_id'=>4,'type'=>2,'token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function get_user_card_list($data = ['aan_id'=>4,'type'=>2,'token'=>'0dafb98a10995c98b5a33b7d59d986ca']){
@ -298,6 +415,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -307,8 +425,8 @@ class Index extends Base{
} }
// 获取指定用户详细信息 // 获取指定用户详细信息
public function get_user_data_information($data = ['aud_id'=>11]){ public function get_user_data_information($data = ['aud_id'=>61]){
try { // try {
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
$data = input('post.'); $data = input('post.');
@ -377,19 +495,19 @@ class Index extends Base{
} }
$this->record_api_log($data, null, ['code'=>0,'msg'=>'success',$result]); $this->record_api_log($data, null, ['code'=>0,'msg'=>'success',$result]);
return $this->msg($result); return $this->msg($result);
} catch (\Exception $e) { // } catch (\Exception $e) {
// 捕获异常 // // 捕获异常
$logContent["flie"] = $e->getFile(); // $logContent["flie"] = $e->getFile();
$logContent["line"] = $e->getLine(); // $logContent["line"] = $e->getLine();
$logContent['all_content'] = "异常信息:\n"; // $logContent['all_content'] = "异常信息:\n";
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; // $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; // $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; // $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; // $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; // $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); // $this->record_api_log($data, $logContent, null);
return $this->msg(99999); // return $this->msg(99999);
} // }
} }
@ -449,6 +567,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -498,6 +617,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -535,6 +655,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -583,6 +704,7 @@ class Index extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -594,8 +716,6 @@ class Index extends Base{
// 获取账号下首页卡片的基础数据 // 获取账号下首页卡片的基础数据
public function get_user_card_data_list($data,$aud_id){ public function get_user_card_data_list($data,$aud_id){
// try {
// 你的业务逻辑
$result = []; $result = [];
$db_arr = []; $db_arr = [];
foreach ($data['card_order'] as $key => $value) { foreach ($data['card_order'] as $key => $value) {
@ -641,7 +761,7 @@ class Index extends Base{
// 'initial_date'=>$data['initial_date']!=null?$data['initial_date']:0, // 'initial_date'=>$data['initial_date']!=null?$data['initial_date']:0,
// ]); // ]);
// } // }
if(count($db_arr) <= 0){ if(count($db_arr) <= 0){
// 没有数据,传递一个空的卡片 // 没有数据,传递一个空的卡片
foreach ($data['card_order'] as $key => $value) { foreach ($data['card_order'] as $key => $value) {
@ -726,13 +846,7 @@ class Index extends Base{
array_push($result,$temporary_arr); array_push($result,$temporary_arr);
} }
} }
// 成功
// $this->record_api_log($data, null, ['code'=>0,'msg'=>'success',[$result,$target_current]]);
return [$result,$data['card_order']]; return [$result,$data['card_order']];
// } catch (\Exception $e) {
// // 捕获异常
// $this->record_api_log($data, $e->getMessage(), null);
// }
} }
@ -1033,6 +1147,20 @@ class Index extends Base{
return $parameter; return $parameter;
} }
public function pd_language($user_language,$isSupportedLanguage,$language){
if(!$user_language){
if($isSupportedLanguage){
$result = $language;
}else{
$result = 'en'; // 默认语言为中文
}
}else{
$result = $user_language;
}
return $result;
}

View File

@ -0,0 +1,211 @@
<?php
namespace app\app\controller;
class Language extends Base
{
// 支持的语言列表
protected $supportedLanguages = [
'en' => 'English',
'zh-Hans' => 'Chinese',
'es' => 'Spanish',
'fr' => 'French',
'pt' => 'Portuguese',
'ar' => 'Arabic',
'ru' => 'Russian',
'de' => 'German'
];
// 语言映射表
protected $languageMap = [
'en' => [
'操作成功' => 'Success',
'体重' => 'Weight',
'身高' => 'Height',
'消瘦' => 'Slim',
'正常' => 'Normal',
'偏重' => 'Overweight',
'肥胖' => 'Obesity',
'反映和衡量一个人健康状况的重要标志之一' => "One of the important indicators reflecting and measuring a person's health status",
'人体纵向部分的长度,源于人体的纵向生长,受遗传因素的影响较大' => "The length of the longitudinal part of the human body is derived from its longitudinal growth and is greatly influenced by genetic factors",
'BMI是身体质量指数,是目前国际上常用的衡量人体胖瘦程度以及是否健康的一个标准。' => "BMI is the body mass index, which is currently a commonly used international standard for measuring the degree of body fat, thinness, and health.",
'公斤' => "kg",
'CM' => "cm",
'年' => "-",
'月' => "-",
'日' => "",
'身体得分' => "Physical score",
'分' => "score",
'身体类型' => "body type",
'健美肌肉型' => "Bodybuilding muscle type",
'低' => "Low",
'偏低' => "Slightly low",
'标准' => "Standard",
'偏高' => "Slightly high",
'高' => "High",
'矮' => "Short",
'偏矮' => "Slightly short",
'脂肪率' => "Body Fat Percentage",
'体脂率是指身体成分中,脂肪组织所占的比率。测量体脂率比单纯的只测量体重更能反映我们身体的脂肪水平(肥胖程度)。' => "Body fat percentage refers to the proportion of fat tissue in body composition. Measuring it provides a more accurate reflection of body fat levels (degree of obesity) than weight measurement alone.",
'脂肪量' => "Fat Mass",
'人体脂肪的重量' => "Body Fat Weight",
'肌肉率' => "Muscle Percentage",
'优' => "Excellent",
'根据人体肌肉总量和人体体重、身高等相结合得到的人体的一个比例值,这个值的范围决定一个人的身体健康状况以及力量的多少。' => "Muscle percentage is a ratio derived from total muscle mass, body weight, height, etc. Its range determines a person's health status and strength level.",
'肌肉量' => "Muscle Mass",
'不足' => "Insufficient",
'肌肉量=实际体重*肌肉率' => "Muscle Mass = Actual Weight × Muscle Percentage",
'水分' => "Body Water",
'指人体内水分比例。' => "Refers to the proportion of water in the human body.",
'蛋白量' => "Protein Mass",
'蛋白量=实际体重*蛋白率' => "Protein Mass = Actual Weight × Protein Percentage",
'骨重' => "Bone Mass",
'单位体积内,骨组织、骨矿物质(钙、磷等)和骨基质(骨胶原、蛋白率、无机盐等等)含量,骨量代表它们骨骼健康的情况。' => "Bone mass refers to the content of bone tissue, minerals (calcium, phosphorus, etc.), and bone matrix (collagen, proteins, inorganic salts, etc.) per unit volume, reflecting skeletal health.",
'蛋白率' => "Protein Percentage",
'人体内蛋白率含量。' => "The proportion of protein in the human body.",
'基础代谢' => "Basal Metabolic Rate (BMR)",
'指人体在清醒而又极端安静的状态下,不受肌肉活动、环境温度、食物及精神紧张等影响时的能量代谢率' => "The energy expenditure rate when the body is awake, completely at rest, and unaffected by muscle activity, ambient temperature, food intake, or mental stress.",
'内脏指数' => "Visceral Fat Index",
'警惕' => "Caution",
'危险' => "Danger",
'内脏脂肪指数' => "Visceral Fat Level",
'皮下脂肪' => "Subcutaneous Fat",
'皮下脂脂肪就是贮存于皮下的脂肪组织人体的脂肪大约有2/3贮存在皮下组织' => "Subcutaneous fat refers to adipose tissue stored under the skin. About two-thirds of body fat is stored subcutaneously.",
'肥胖等级' => "Obesity Level",
'体重不足' => "Underweight",
'肥胖的程度,表现实际体重与理想体重的差距。肥胖等级是判定肥胖症的一个指标。' => "Obesity level indicates the disparity between actual and ideal weight, serving as a diagnostic criterion for obesity.",
'孩子可能存在营养不良对于处在生长发育期的孩子而言蛋白质、碳水化合物、维生素和矿物质这四类营养素非常重要。建议补充足够的蛋白质、锌、钙、铁、维生素D、赖氨酸等营养。建议补充含鸡内金山楂膏健脾开胃类药食同源食物。' => "The child may be malnourished: For growing children, protein, carbohydrates, vitamins, and minerals are critical. Ensure adequate intake of protein, zinc, calcium, iron, vitamin D, lysine, etc. Consider herbal foods like chicken gizzard-hawthorn paste to improve digestion and appetite.",
'孩子可能存在营养不良对于处在生长发育期的孩子而言最有利于长高的营养素是蛋白质、碳水化合物、维生素和矿物质四类。建议补充足够的蛋白质、锌、铁、钙、维生素D、赖氨酸等营养。' => "The child may be malnourished: For children in their growth and development stage, the most beneficial nutrients for height growth are proteins, carbohydrates, vitamins, and minerals. It is recommended to ensure adequate intake of nutrients such as protein, zinc, iron, calcium, vitamin D, and lysine.",
'坚持适当、科学的跳跃运动能够科学地增加学生体重,能够改善学 生体重过低的情况;同时运动会消耗能量并加速胃肠蠕动,这会使孩子的食欲大开,再配合均衡的营养有利于孩子增重。' => "Moderate, scientifically designed jumping exercises can help underweight students gain weight by boosting energy expenditure and gastrointestinal motility, thereby increasing appetite. Combined with balanced nutrition, this supports healthy weight gain.",
'3-7岁的孩子骑两轮车、拍踢球、打篮球、游泳、爬山每天高强度运动不超过30分钟。' => "Ages 37: Bicycling, ball games, basketball, swimming, hiking. Limit high-intensity exercise to 30 minutes daily.",
'该年龄段睡眠时间建议9-11小时' => "Recommended sleep duration for this age group: 911 hours.",
'孩子开始对于赞赏、鼓励、认同和肯定有需求,而且此阶段父亲在孩子的性格塑造、情绪控制以及责任感培养方面扮演着重要的角色,必须告诉孩子什么事应该做、什么事不应该做,并经常性地给孩子一些积极地暗示。例如,可以时常向孩子表达“我会一直在你身边,不要害怕””我对你的进步都看在眼里等类似的话语。' => "Children begin to crave praise, encouragement, and validation. Fathers play a key role in shaping character, emotional regulation, and responsibility during this phase. Clearly define boundaries while offering positive affirmations (e.g., 'Im always here for you,' 'I see your progress').",
'《中华人民共和国卫生行业标准WS 423-2013》' => "《Chinese Health Industry Standard WS 423-2013》",
'《中华人民共和国卫生行业标准WS/T 612-2018》' => "《Chinese Health Industry Standard WS/T 612-2018》",
'《中华人民共和国卫生行业标准WS/T1586-2018》' => "《Chinese Health Industry Standard WS/T 1586-2018》",
'《WHO 5~19岁身高/体重判定标准》' => "《WHO Growth Reference for Children and Adolescents (519 Years)》",
'头围' => "Head Circumference",
'头围是指绕头部一周的最大长度,头围的大小与脑的发育密切相关' => "Head circumference refers to the maximum length around the head. Its measurement is closely related to brain development.",
],
// 可以添加更多语言映射
];
/**
* 处理多国语言翻译
*
* @param string $language 目标语言代码
* @param mixed $data 要翻译的数据(字符串或数组)
* @return mixed 翻译后的数据
*/
public function handling_languages_from_multiple_countries($language, $data)
{
// dump($data);
// 验证语言是否支持
if (!$this->isLanguageSupported($language)) {
return $this->msg($data['data']);
}
// 如果是数组,递归处理每个元素
if (is_array($data)) {
// dump(2);
$data = $this->translateArray($language, $data);
return $this->msg($data['data']);
}
// 如果是字符串,直接翻译
if (is_string($data)) {
// dump(3);
return $this->translateString($language, $data);
}
// dump($data);
// 其他类型直接返回
return $this->msg($data['data']);
}
/**
* 检查语言是否支持
*
* @param string $language 语言代码
* @return bool
*/
protected function isLanguageSupported($language)
{
return isset($this->supportedLanguages[$language]);
}
/**
* 翻译数组
*
* @param string $language 目标语言
* @param array $array 要翻译的数组
* @return array 翻译后的数组
*/
protected function translateArray($language, array $array)
{
$result = [];
foreach ($array as $key => $value) {
// 保持键不变,只翻译值
$result[$key] = is_array($value)
? $this->translateArray($language, $value)
: $this->translateString($language, $value);
}
return $result;
}
/**
* 翻译字符串
*
* @param string $language 目标语言
* @param string $string 要翻译的字符串
* @return string 翻译后的字符串
*/
protected function translateString($language, $string)
{
// dump($string);
// 检查是否有该语言的映射表
if (!isset($this->languageMap[$language])) {
return $string;
}
// 检查是否有对应的翻译
return $this->languageMap[$language][$string] ?? $string;
}
/**
* 获取支持的语言列表
*
* @return array
*/
public function getSupportedLanguages()
{
return $this->supportedLanguages;
}
/**
* 添加新的语言翻译
*
* @param string $language 语言代码
* @param array $translations 翻译映射数组
* @return bool
*/
public function addTranslations($language, array $translations)
{
if (!$this->isLanguageSupported($language)) {
return false;
}
if (!isset($this->languageMap[$language])) {
$this->languageMap[$language] = [];
}
$this->languageMap[$language] = array_merge(
$this->languageMap[$language],
$translations
);
return true;
}
}

View File

@ -1,10 +1,11 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Db; use think\Db;
use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\PHPMailer;
use app\app\controller\Wechat;// 引入Wechat服务类
class Login extends Base{ class Login extends Base{
@ -12,7 +13,7 @@ class Login extends Base{
// protected $token_time = 2592000;//30天的秒数 // protected $token_time = 2592000;//30天的秒数
protected $default_head_pic = 'http://tc.pcxbc.com/tsf/head_pic.png'; protected $default_head_pic = 'http://tc.pcxbc.com/tsf/head_pic.png';
protected $login_use_db_name = [ protected $login_use_db_name = [
'1'=>'test_app_account_number', '1'=>'app_account_number',
]; ];
################################################################接口################################################################ ################################################################接口################################################################
@ -20,7 +21,7 @@ class Login extends Base{
################################################################接口################################################################ ################################################################接口################################################################
// 注册 // 注册
public function register_action($data = ['data'=>18530934717,'password'=>'ceshi','code'=>'746119']){ public function register_action($data = ['data'=>13408173311,'password'=>'123','code'=>'746119']){
try { try {
// 你的业务逻辑 // 你的业务逻辑
// 验证是否前段发送过来的数据 // 验证是否前段发送过来的数据
@ -46,11 +47,14 @@ class Login extends Base{
if($montage_data == false){ if($montage_data == false){
return $this->msg(10005); return $this->msg(10005);
} }
// 查询账号是否已经注册 // 查询账号是否已经注册
$inspect_repeat = Db::table($this->login_use_db_name['1'])->where([$montage_data=>$data['data'],'is_del'=>0])->count(); $inspect_repeat = Db::table($this->login_use_db_name['1'])->where([$montage_data=>$data['data'],'is_del'=>0])->count();
if($inspect_repeat >= 0){
if($inspect_repeat > 0){
return $this->msg(10002,'注册失败,账号已存在'); return $this->msg(10002,'注册失败,账号已存在');
} }
// 检查验证码 // 检查验证码
$code_result = $this->check_code($data['data'],$data['code']); $code_result = $this->check_code($data['data'],$data['code']);
if($code_result !== true){ if($code_result !== true){
@ -87,6 +91,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -151,6 +156,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -158,7 +164,6 @@ class Login extends Base{
} }
} }
// 登录 // 登录
public function login_action($data = ['data'=>'18530934717','validate_data'=>'0932','type'=>'login','validate_type'=>'password']){ public function login_action($data = ['data'=>'18530934717','validate_data'=>'0932','type'=>'login','validate_type'=>'password']){
try { try {
@ -235,6 +240,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -242,6 +248,82 @@ class Login extends Base{
} }
}
// 微信手机号快捷登录
public function wechat_quick_login(){
try {
// 你的业务逻辑
if(count(input('post.')) > 0){
$data = input('post.');
}
if(!array_key_exists('code', $data)){
// return $this->msg(10001,'');
return $this->msg(10001,'code is miss');
}
if(!array_key_exists('encryptedData', $data)){
return $this->msg(10001,'encryptedData is miss');
}
if(!array_key_exists('iv', $data)){
return $this->msg(10001,'iv is miss');
}
// 校验参数
if (empty($data['code'])) {
return $this->msg(10001,'code is miss.');
}
if (empty($data['encryptedData'])) {
return $this->msg(10001,'encryptedData is miss.');
}
if (empty($data['iv'])) {
return $this->msg(10001,'iv is miss.');
}
// 调用Wechat服务类处理微信登录逻辑
$wechatService = new Wechat();
$result = $wechatService->handleWechatLogin($data['code'], $data['encryptedData'], $data['iv']);
// die;
if($result['code'] == 0){
// return $this->msg($result['code'],$result['msg']);
$user_data = Db::table($this->login_use_db_name['1'])->where(['tel'=>$result['data']['phoneNumber'],'is_del'=>0])->find();
if($user_data){
Db::table($this->login_use_db_name['1'])->where(['token'=>$user_data['token']])->update(['login_time'=>date('Y-m-d H:i:s')]);
$return_data = $this->msg(['token'=>$user_data['token'],'aan_id'=>$user_data['id']]);
}else{
$set_data['password'] = '';
$set_data['tel'] = $result['data']['phoneNumber'];
$set_data['head_pic'] = $this->default_head_pic;
$set_data['nickname'] = '用户'.$result['data']['phoneNumber'];
$set_data['create_time'] = date('Y-m-d H:i:s');
$set_data['login_time'] = date('Y-m-d H:i:s');
$set_data['token'] = md5($result['data']['phoneNumber'].$this->create_random_string(12).time());
$set_user_result = Db::table($this->login_use_db_name['1'])->insertGetId($set_data);
if($set_user_result){
$return_data = $this->msg(['token'=>$set_data['token'],'aan_id'=>$set_user_result],'登录成功');
}else{
$return_data = $this->msg(10002);
}
}
return $return_data;
}else{
return $this->msg($result['code'],$result['msg']);
}
} catch (\Exception $e) {
// 捕获异常
$logContent["flie"] = $e->getFile();
$logContent["line"] = $e->getLine();
$logContent['all_content'] = "异常信息:\n";
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null);
return $this->msg(99999);
}
} }
// 退出登录操作 // 退出登录操作
public function user_quit_account($data=['token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function user_quit_account($data=['token'=>'0dafb98a10995c98b5a33b7d59d986ca']){
@ -263,8 +345,6 @@ class Login extends Base{
}else{ }else{
$return_data = $this->msg(10002); $return_data = $this->msg(10002);
} }
// 成功 // 成功
$this->record_api_log($data, null, $return_data); $this->record_api_log($data, null, $return_data);
return $return_data; return $return_data;
@ -276,6 +356,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -283,8 +364,6 @@ class Login extends Base{
} }
} }
// 删除账号 // 删除账号
public function delete_account($data=['token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function delete_account($data=['token'=>'0dafb98a10995c98b5a33b7d59d986ca']){
try { try {
@ -313,6 +392,7 @@ class Login extends Base{
$logContent['all_content'] .= "消息: " . $e->getMessage() . "\n"; $logContent['all_content'] .= "消息: " . $e->getMessage() . "\n";
$logContent['all_content'] .= "代码: " . $e->getCode() . "\n"; $logContent['all_content'] .= "代码: " . $e->getCode() . "\n";
$logContent['all_content'] .= "文件: " . $e->getFile() . "\n"; $logContent['all_content'] .= "文件: " . $e->getFile() . "\n";
$logContent['all_content'] .= "方法: " . __METHOD__ . "\n";
$logContent['all_content'] .= "行号: " . $e->getLine() . "\n"; $logContent['all_content'] .= "行号: " . $e->getLine() . "\n";
$logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n"; $logContent['all_content'] .= "跟踪信息:\n" . $e->getTraceAsString() . "\n";
$this->record_api_log($data, $logContent, null); $this->record_api_log($data, $logContent, null);
@ -333,7 +413,7 @@ class Login extends Base{
* $type验证类型是注册用还是其他用途 字符串 默认register注册register、login、reset_password * $type验证类型是注册用还是其他用途 字符串 默认register注册register、login、reset_password
* $road是手机还是邮箱还是其他 字符串 默认tel或email * $road是手机还是邮箱还是其他 字符串 默认tel或email
*/ */
public function send_phone_email_code($data = ['data'=>'18530934717']){ public function send_phone_email_code($data = ['data'=>'18736019909']){
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){
$data = input('post.'); $data = input('post.');
@ -349,6 +429,7 @@ class Login extends Base{
$num = mt_rand(100000,999999); $num = mt_rand(100000,999999);
if (preg_match('/^\d{11}$/', $data['data'])) { if (preg_match('/^\d{11}$/', $data['data'])) {
$result = $this->send_tel_code($data['data'],$num); $result = $this->send_tel_code($data['data'],$num);
// return $this->msg($result);
$road = 'tel'; $road = 'tel';
}else{ }else{
$result = $this->send_email_code([$data['data']],['title'=>'体测APP验证码','from_user_name'=>'体测APP','content'=>$num]); $result = $this->send_email_code([$data['data']],['title'=>'体测APP验证码','from_user_name'=>'体测APP','content'=>$num]);
@ -383,26 +464,31 @@ class Login extends Base{
curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_URL, $url);
// 设置为POST请求 // 设置为POST请求
curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POST, 1);
// 设置POST数据 // 设置POST数据
$postData = array( $postData = array(
'phone' => $tel, 'phone' => $tel,
// 'content' => '您好欢迎使用Reedaw,您的手机验证码是:'.$code.',验证码三分钟内有效,若非本人操作,请忽略!' // 'content' => '您好欢迎使用Reedaw,您的手机验证码是:'.$code.',验证码三分钟内有效,若非本人操作,请忽略!'
'content' => '【Reedaw】您好欢迎使用Reedaw您的验证码是'.$code.',验证码一分钟内有效,若非本人操作,请忽略本短信' // 'content' => '【Reedaw】您好欢迎使用Reedaw您的验证码是'.$code.',验证码一分钟内有效,若非本人操作,请忽略本短信'
); 'content' => '【巨天】您好欢迎使用Reedaw您的手机验证码是'.$code.',验证码一分钟内有效,若非本人操作,请忽略本短信'
// 'content' => '【小白秤】您好欢迎使用Reedaw您的手机验证码是'.$code.',验证码一分钟内有效,若非本人操作,请忽略本短信'
// 'content' => '【品传科技】您好欢迎使用Reedaw您的手机验证码是'.$code.',验证码一分钟内有效,若非本人操作,请忽略本短信'
// 'content' => '【巨天】您好,欢迎使用巨天,您的手机验证码是:'.$code.',验证码一分钟内有效,若非本人操作,请忽略!'
);
$postData = json_encode($postData); $postData = json_encode($postData);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
// 设置返回结果不直接输出,而是返回到变量中 // 设置返回结果不直接输出,而是返回到变量中
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 发送请求并获取响应 // 发送请求并获取响应
$response = curl_exec($ch); $response = curl_exec($ch);
// 检查是否有错误发生 // 检查是否有错误发生
if (curl_errno($ch)) { if (curl_errno($ch)) {
$error_message = curl_error($ch); $error_message = curl_error($ch);
return "请求错误: " . $error_message; return "请求错误: " . $error_message;
} }
// 关闭cURL会话 // 关闭cURL会话
curl_close($ch); curl_close($ch);
// 处理响应 // 处理响应
if ($response) { if ($response) {
return json_decode($response,true); return json_decode($response,true);

View File

@ -7,6 +7,9 @@ use think\Db;
class Msginformation extends Base{ class Msginformation extends Base{
protected $judge_wechat_release = false;
protected $msginformation_use_db_name = [ protected $msginformation_use_db_name = [
'1'=>'admin_editor_text_content', '1'=>'admin_editor_text_content',
'2'=>'admin_editor_text_like_up_log', '2'=>'admin_editor_text_like_up_log',
@ -251,6 +254,9 @@ class Msginformation extends Base{
################################################################业务################################################################ ################################################################业务################################################################
################################################################get_sector_label_msg ################################################################get_sector_label_msg
public function get_sector_label_msg_action($data){ public function get_sector_label_msg_action($data){
$Template_arr = [ $Template_arr = [
1=>[ 1=>[
'id'=>'1', 'id'=>'1',
@ -266,6 +272,17 @@ class Msginformation extends Base{
] ]
], ],
]; ];
if($this->judge_wechat_release === true){
$Template_arr = [
1=>[
'id'=>'1',
'name'=>'推荐',
'loop_data'=>[],
'list'=>[
]
],
];
}
// 获取需要版块id start // 获取需要版块id start
$sector = Db::query(" $sector = Db::query("
SELECT SELECT
@ -316,6 +333,9 @@ class Msginformation extends Base{
'page_num'=>$this->page_num, 'page_num'=>$this->page_num,
'content_data'=>[] 'content_data'=>[]
]; ];
if($this->judge_wechat_release === true){
return $this->msg($return_result);
}
if($data['type'] != 0){ if($data['type'] != 0){
$type_str = " AND type LIKE '%".$data['type']."%'"; $type_str = " AND type LIKE '%".$data['type']."%'";
}else{ }else{
@ -427,8 +447,8 @@ class Msginformation extends Base{
'banner'=>[] 'banner'=>[]
]; ];
// return $this->msg($return_data); // return $this->msg($return_data);
// 所有可用记录 // 所有可用记录.
$all_data = Db::table($this->msginformation_use_db_name['3'])->where(['is_del'=>0])->select(); $all_data = Db::table($this->msginformation_use_db_name['3'])->where("is_del = 0 AND scene_data IN (1,2,3)")->select();
// 用户阅读记录 // 用户阅读记录
$user_read_log = Db::table($this->msginformation_use_db_name['2'])->where(['token'=>$data['token']])->field('aetc_id')->select(); $user_read_log = Db::table($this->msginformation_use_db_name['2'])->where(['token'=>$data['token']])->field('aetc_id')->select();
$user_read_data = []; $user_read_data = [];
@ -496,7 +516,18 @@ class Msginformation extends Base{
return $this->msg($return_data); return $this->msg($return_data);
} }
################################################################小工具################################################################
################################################################小工具################################################################
################################################################小工具################################################################
################################################################小工具################################################################
################################################################小工具################################################################
// 判断微信发版工具
public function judge_wechat_release(){
}
} }

View File

@ -1,15 +1,15 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Db; use think\Db;
use app\testapp\controller\Login; use app\app\controller\Login;
class Myinformation extends Base{ class Myinformation extends Base{
protected $myinformation_use_db_name = [ protected $myinformation_use_db_name = [
'1'=>'test_app_account_number', '1'=>'app_account_number',
]; ];
// 加 bcadd(,,20) // 加 bcadd(,,20)
// 减 bcsub(,,20) // 减 bcsub(,,20)
@ -20,7 +20,7 @@ class Myinformation extends Base{
################################################################接口################################################################ ################################################################接口################################################################
// 获取账号下信息 // 获取账号下信息
public function get_my_account_msg($data = ['token'=>'0dafb98a10995c98b5a33b7d59d986ca']){ public function get_my_account_msg($data = ['token'=>'e0966788d02cc93290d9d674921d9715']){
try { try {
// 你的业务逻辑 // 你的业务逻辑
if(count(input('post.')) > 0){ if(count(input('post.')) > 0){

View File

@ -1,19 +1,18 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Db; use think\Db;
class Pagingcontrast extends Base{ class Pagingcontrast extends Base{
protected $color = ['#FF5656','#FFAB00','#5AD06D','#6492F6','#3967D6']; protected $color = ['#FF5656','#FFAB00','#5AD06D','#6492F6','#3967D6'];
protected $db_name = ['2'=>'test_app_card_body_data','6'=>'test_app_card_skip_data','8'=>'test_app_card_vitalcapacity_data']; protected $db_name = ['2'=>'app_card_body_data','6'=>'app_card_skip_data','8'=>'app_card_vitalcapacity_data'];
protected $pagingcontrast_use_db_name = [ protected $pagingcontrast_use_db_name = [
'1'=>'test_app_card_body_data', '1'=>'app_card_body_data',
'2'=>'test_app_card_skip_data', '2'=>'app_card_skip_data',
'3'=>'test_app_card_vitalcapacity_data', '3'=>'app_card_vitalcapacity_data',
'4'=>'test_app_user_data', '4'=>'app_user_data',
// '4'=>'test_app_user_data',
]; ];
protected $request_result = [ protected $request_result = [
'2'=>['height'=>['身高','cm'],'weight'=>['体重','kg'],'age'=>['年龄','岁'],'bmi'=>['BMI',''],'head'=>['头围',''],'fat_w'=>['脂肪量','kg'],'fat_r'=>['脂肪率','%'],'muscleval'=>['肌肉量','kg'],'muscle'=>['肌肉率','%'],'proteinval'=>['蛋白量','kg'],'protein'=>['蛋白率','%'],'water'=>['水分',''],'bone'=>['骨重','kg'],'visceral'=>['内脏指数',''],'sfr'=>['皮下脂肪','%'],'kcal'=>['基础代谢','kcal'],'un_fat_w_weight'=>['去脂体重','kg'],'body_age'=>['体龄',''],'body_level'=>['肥胖等级',''],'body_type'=>['体型','']], '2'=>['height'=>['身高','cm'],'weight'=>['体重','kg'],'age'=>['年龄','岁'],'bmi'=>['BMI',''],'head'=>['头围',''],'fat_w'=>['脂肪量','kg'],'fat_r'=>['脂肪率','%'],'muscleval'=>['肌肉量','kg'],'muscle'=>['肌肉率','%'],'proteinval'=>['蛋白量','kg'],'protein'=>['蛋白率','%'],'water'=>['水分',''],'bone'=>['骨重','kg'],'visceral'=>['内脏指数',''],'sfr'=>['皮下脂肪','%'],'kcal'=>['基础代谢','kcal'],'un_fat_w_weight'=>['去脂体重','kg'],'body_age'=>['体龄',''],'body_level'=>['肥胖等级',''],'body_type'=>['体型','']],

View File

@ -1,6 +1,6 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Db; use think\Db;
@ -9,9 +9,9 @@ class Skip extends Base{
protected $color = ['#FF5656','#FFAB00','#5AD06D','#6492F6','#3967D6']; protected $color = ['#FF5656','#FFAB00','#5AD06D','#6492F6','#3967D6'];
protected $curve_data_format = ['jump_num'=>['跳绳个数','个','#009DFF'],'jump_time'=>['跳绳时长','分钟','#009DFF'],'jump_kcal'=>['消耗卡路里','kcal','#009DFF']]; protected $curve_data_format = ['jump_num'=>['跳绳个数','个','#009DFF'],'jump_time'=>['跳绳时长','分钟','#009DFF'],'jump_kcal'=>['消耗卡路里','kcal','#009DFF']];
protected $skip_use_db_name = [ protected $skip_use_db_name = [
'1'=>'test_app_card_skip_data', '1'=>'app_card_skip_data',
'2'=>'test_app_user_data', '2'=>'app_user_data',
'3'=>'test_app_card_body_data', '3'=>'app_card_body_data',
]; ];
protected $result_end_data_mould = [ protected $result_end_data_mould = [
'name'=>'', 'name'=>'',
@ -47,7 +47,11 @@ class Skip extends Base{
if(!$this->verify_data_is_ok($data['type'],'str')){ if(!$this->verify_data_is_ok($data['type'],'str')){
return $this->msg(10005); return $this->msg(10005);
} }
if(!$this->isValidInteger($data['num']+0) || !$this->isValidInteger($data['time_m']+0) || !$this->isValidInteger($data['time_s']+0)){ // {"aud_id":"331","num":"100","r_time":"2025-01-15","time_m":"","time_s":"","type":"free","token":"2581d40766e7cfd25ca140f3514072bd","aan_id":"254"}
// if(!$this->isValidInteger($data['num']+0) || !$this->isValidInteger($data['time_m']+0) || !$this->isValidInteger($data['time_s']+0)){
// $return_data = $this->msg(10005,'跳绳数量或者分钟、秒钟值必须为整数');
// }
if(!$this->verify_data_is_ok($data['num'],'intnum') || !$this->verify_data_is_ok($data['time_m'],'intnum') || !$this->verify_data_is_ok($data['time_s'],'intnum')){
$return_data = $this->msg(10005,'跳绳数量或者分钟、秒钟值必须为整数'); $return_data = $this->msg(10005,'跳绳数量或者分钟、秒钟值必须为整数');
} }
if($data['num'] <= 0){ if($data['num'] <= 0){

View File

@ -1,6 +1,6 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Db; use think\Db;
@ -12,8 +12,8 @@ class Sportstesting extends Base{
protected $color = ['#FF5656','#FF5656','#5AD06D','#6492F6','#3967D6']; protected $color = ['#FF5656','#FF5656','#5AD06D','#6492F6','#3967D6'];
protected $sportstesting_use_db_name = [ protected $sportstesting_use_db_name = [
'1'=>'admin_estimate', '1'=>'admin_estimate',
'2'=>'test_app_sportstesting_data', '2'=>'app_sportstesting_data',
'3'=>'test_app_user_data', '3'=>'app_user_data',
]; ];
protected $page_num = 10; protected $page_num = 10;
protected $default_address = '上海'; protected $default_address = '上海';

View File

@ -1,6 +1,6 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Db; use think\Db;
@ -17,9 +17,9 @@ class Vitalcapacity extends Base{
['min_val'=>'0','max_val'=>'9','text'=>'无效','color'=>'#FF5656'], ['min_val'=>'0','max_val'=>'9','text'=>'无效','color'=>'#FF5656'],
]; ];
protected $vitalcapacity_use_db_name = [ protected $vitalcapacity_use_db_name = [
'1'=>'test_app_user_data', '1'=>'app_user_data',
'2'=>'test_app_card_vitalcapacity_data', '2'=>'app_card_vitalcapacity_data',
'3'=>'test_pc_vitalcapacity_standard', '3'=>'pc_vitalcapacity_standard',
]; ];
protected $result_end_data_mould = [ protected $result_end_data_mould = [
'name'=>'', 'name'=>'',

View File

@ -0,0 +1,124 @@
<?php
namespace app\app\controller;
use think\Db;
use PHPMailer\PHPMailer\PHPMailer;
class Wechat extends Base{
// reedaw的小程序信息
private $app_id = 'wx9c0b7a436ada6d1e'; // 微信小程序的AppID
private $app_secret = 'ed7cda5874f0eef3360e782a3db73c80'; // 微信小程序的AppSecret
// ed7cda5874f0eef3360e782a3db73c80
################################################################接口################################################################
################################################################接口################################################################
################################################################接口################################################################
/**
* 处理微信登录
*
* @param string $code 微信登录凭证
* @param string $encryptedData 加密的用户信息
* @param string $iv 解密算法的初始向量
* @return array
*/
public function handleWechatLogin($code, $encryptedData, $iv)
{
// try {
// 1. 通过code获取openid和session_key
$sessionData = $this->getSessionKey($code);
if (empty($sessionData['openid']) || empty($sessionData['session_key'])) {
// throw new Exception('获取openid或session_key失败');
// return false;
// return $this->msg(10001);
return ['code'=>10002,'msg'=>'获取openid或session_key失败'];
}
// 2. 解密用户信息
$userInfo = $this->decryptData($encryptedData, $iv, $sessionData['session_key']);
if(array_key_exists('phoneNumber',$userInfo)){
return ['code'=>0,'msg'=>'seccess','data'=>$userInfo];
}else{
return ['code'=>10002,'msg'=>'解密用户信息失败'];
}
// if (empty($userInfo['phoneNumber'])) {
// // throw new Exception('获取手机号失败');
// }else{
// }
// // 3. 保存或更新用户信息
// $user = User::where('openid', $sessionData['openid'])->find();
// if (!$user) {
// $user = new User();
// $user->openid = $sessionData['openid'];
// }
// $user->phone = $userInfo['phoneNumber'];
// $user->save();
// 返回成功信息
// return ['code' => 0, 'msg' => '登录成功', 'data' => $user];
// } catch (Exception $e) {
// // 返回错误信息
// return ['code' => 500, 'msg' => $e->getMessage()];
// }
}
/**
* 通过code获取openid和session_key
*
* @param string $code
* @return array
* @throws Exception
*/
private function getSessionKey($code)
{
$url = "https://api.weixin.qq.com/sns/jscode2session?appid={$this->app_id}&secret={$this->app_secret}&js_code={$code}&grant_type=authorization_code";
$result = file_get_contents($url);
$data = json_decode($result, true);
if (isset($data['openid']) && isset($data['session_key'])) {
return $data;
} else {
return ['code'=>10002,'msg'=>'获取openid或session_key失败'];
}
}
/**
* 解密用户信息
*
* @param string $encryptedData
* @param string $iv
* @param string $sessionKey
* @return array
* @throws Exception
*/
private function decryptData($encryptedData, $iv, $sessionKey)
{
// require_once 'wx_crypt/WXBizDataCrypt.php'; // 引入微信解密类
// require_once env('root_path') . 'extend/wx_crypt/WXBizDataCrypt.php';
// dump(ROOT_PATH . 'extend\wx_crypt\wxBizDataCrypt.php');
require_once ROOT_PATH . 'extend\wx_crypt\wxBizDataCrypt.php';
$pc = new \WXBizDataCrypt($this->app_id, $sessionKey);
$errCode = $pc->decryptData($encryptedData, $iv, $data);
if ($errCode == 0) {
return json_decode($data, true);
} else {
return ['code'=>10002,'msg'=>'解密用户信息失败('.$errCode.')'];
// throw new Exception('解密失败: ' . $errCode);
}
}
// 注册
}

View File

@ -1,6 +1,6 @@
<?php <?php
namespace app\testapp\controller; namespace app\app\controller;
use think\Db; use think\Db;

View File

@ -0,0 +1,171 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1,minimum-scale=1, maximum-scale=1,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta http-equiv="Access-Control-Allow-Origin" content="*">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no, email=no">
<meta name="full-screen" content="true">
<meta name="screen-orientation" content="portrait">
<meta name="x5-fullscreen" content="true">
<meta name="360-fullscreen" content="true">
<title>deepseek测试页面</title>
<script src="/x_admin/js/jq.js"></script>
<style>
*{
padding: 0 0;
margin: 0 0;
}
.big_box{
width: 100vw;
height: 100vh;
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
}
.chat_box {
flex: 1;
/* overflow-y: auto; */
overflow-y: scroll;
padding: 10px;
border-bottom: 1px solid #ccc;
}
.input_box {
display: flex;
padding: 10px;
border-top: 1px solid #ccc;
}
.input_box input {
flex: 1;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
.input_box button {
margin-left: 10px;
padding: 10px 20px;
border: none;
background-color: #007bff;
color: white;
border-radius: 5px;
cursor: pointer;
}
.message {
margin: 10px 0;
display: flex;
}
.message.user {
justify-content: flex-end;
}
.message.bot {
justify-content: flex-start;
}
.message .content {
max-width: 70%;
padding: 10px;
border-radius: 5px;
background-color: #f1f0f0;
}
.message.user .content {
background-color: #dcf8c6;
}
.fugai{
display: none;
position: absolute;
width: 100vw;
height: 100vh;
text-align: center;
line-height: 100vh;
color: white;
font-size: 10vw;
font-weight: bold;
background-color: rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body id="box_k">
<div class="big_box">
<div class="chat_box" id="chat_box">
<!-- 对话内容将在这里展示 -->
</div>
<div class="input_box">
<input type="text" id="message_input" placeholder="输入消息..." value="我是一个河南的25岁女性身高64.52cm体重68.00kg,请根据我的这个信息,从睡眠、饮食、运动三个方向给我一些健康建议。">
<button id="send_button">发送</button>
</div>
<div class='fugai'></div>
</div>
</body>
</html>
<script>
$(document).ready(function() {
var pd = true;
$('#send_button').click(function() {
if(pd == false){
return;
}
pd = false;
var message = $('#message_input').val();
if (message.trim() === '') {
$('.fugai').html('您没有填写内容')
$('.fugai').show()
setTimeout(() => {
$('.fugai').hide()
}, 1000);
return;
}
// 显示用户消息
$('#chat_box').append('<div class="message user"><div class="content">' + message + '</div></div>');
// document.getElementById('scroll_button').addEventListener('click', function() {
// var chatBox = document.getElementById('chat_box');
// chatBox.scrollTop = chatBox.scrollHeight;
// });
// 清空输入框
$('#message_input').val('');
$('.fugai').html('思考中请稍等')
$('.fugai').show()
$.ajax({
url:"https://tc.pcxbc.com/ai/send_msg_deepseek", //请求的url地址
dataType:"json", //返回格式为json
async:true,//请求是否异步默认为异步这也是ajax重要特性
data:{"xinxi":message}, //参数值
type:"POST", //请求方式
success:function(req){
$('.fugai').hide()
pd = true;
//请求成功时处理
if(req.code == 0){
$('#chat_box').append('<div class="message bot"><div class="content">' + req.msg + '</div></div>');
}
},
error:function(){
//请求出错处理
}});
// 模拟对方回复
// setTimeout(function() {
// var reply = '对方回复: ' + message;
// $('#chat_box').append('<div class="message bot"><div class="content">' + reply + '</div></div>');
// }, 1000);
});
// // 按下回车键发送消息
// $('#message_input').keypress(function(e) {
// console.log(e)
// // if (e.which == 13) {
// // $('#send_button').click();
// // }
// });
});
</script>

View File

@ -15,6 +15,8 @@
<meta name="360-fullscreen" content="true"> <meta name="360-fullscreen" content="true">
<title>商务合作</title> <title>商务合作</title>
<script src="/x_admin/js/jq.js"></script> <script src="/x_admin/js/jq.js"></script>
<script type="text/javascript" src="/x_admin/lib/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="/x_admin/js/xadmin.js"></script>
<style> <style>
*{ *{
padding: 0 0; padding: 0 0;
@ -154,6 +156,8 @@
#onload{ #onload{
width: 20vw; width: 20vw;
height: 5vw; height: 5vw;
min-width: 200px;
min-height: 45px;
background-color: #0A6CFF; background-color: #0A6CFF;
color: white; color: white;
border-radius: 10px; border-radius: 10px;
@ -278,6 +282,18 @@
textarea.style.height = textarea.scrollHeight + 'px'; // 设置为内容高度 textarea.style.height = textarea.scrollHeight + 'px'; // 设置为内容高度
} }
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// 获取 #onload 元素
const onloadElement = document.getElementById('onload');
// 计算 #onload 元素的高度
const height = onloadElement.offsetHeight;
// 设置 #onload 元素的行高与高度一致
onloadElement.style.lineHeight = height + 'px';
const checkboxes = document.querySelectorAll('.option-checkbox'); const checkboxes = document.querySelectorAll('.option-checkbox');
const selectedCountElement = document.getElementById('selectedCount'); const selectedCountElement = document.getElementById('selectedCount');
let selectedCount = 0; let selectedCount = 0;
@ -300,9 +316,7 @@
}); });
$('#onload').on('click', function() { $('#onload').on('click', function() {
var index = layer.load(1, {
shade: [0.1, '#fff'] //0.1透明度的白色背景
});
// 获取所有需要检查的输入字段 // 获取所有需要检查的输入字段
const nameInput = document.querySelector('.name-input'); const nameInput = document.querySelector('.name-input');
const phoneInput = document.querySelector('.phone-input'); const phoneInput = document.querySelector('.phone-input');
@ -339,9 +353,14 @@
} }
if (hasError) { if (hasError) {
alert('以下项目未填写或未选择:\n' + errorMessage);
layer.msg('以下项目未填写或未选择:\n' + errorMessage, {icon: 2});
// alert('以下项目未填写或未选择:\n' + errorMessage);
return; return;
} }
var index = layer.load(1, {
shade: [0.1, '#fff'] //0.1透明度的白色背景
});
// 如果所有字段都填写了,执行提交操作 // 如果所有字段都填写了,执行提交操作
$.ajax({ $.ajax({
@ -359,17 +378,19 @@
success: function(req) { success: function(req) {
layer.close(layer.index) layer.close(layer.index)
// 请求成功时处理 // 请求成功时处理
layer.msg(req.msg, {icon: 2});
if(req.code == 0){ if(req.code == 0){
layer.msg(req.msg, {icon: 1});
setTimeout(() => { setTimeout(() => {
window.location.reload(); window.location.reload();
}, 1000); }, 2000);
}else{
layer.msg(req.msg, {icon: 2});
} }
}, },
error: function() { error: function() {
layer.close(layer.index) layer.close(layer.index)
// 请求出错处理 // 请求出错处理
alert('提交失败,请重试。'); layer.msg('网络错误了,请直接联系商务合作电话/微信13590959084', {icon: 2});
} }
}); });
}); });

View File

@ -16,7 +16,7 @@
<title>下载页面</title> <title>下载页面</title>
<script src="/x_admin/js/jq.js"></script> <script src="/x_admin/js/jq.js"></script>
<style> <style>
*{ *{
padding: 0 0; padding: 0 0;
margin: 0 0; margin: 0 0;
} }

View File

@ -20,7 +20,8 @@
"topthink/framework": "5.0.*", "topthink/framework": "5.0.*",
"phpmailer/phpmailer": "^6.9", "phpmailer/phpmailer": "^6.9",
"phpoffice/phpspreadsheet": "^1.25", "phpoffice/phpspreadsheet": "^1.25",
"overtrue/wechat": "~4.0" "overtrue/wechat": "~4.0",
"zoujingli/ip2region": "^2.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@ -8,9 +8,11 @@ $baseDir = dirname($vendorDir);
return array( return array(
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'Ip2Region' => $vendorDir . '/zoujingli/ip2region/Ip2Region.php',
'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'Stringable' => $vendorDir . '/myclabs/php-enum/stubs/Stringable.php', 'Stringable' => $vendorDir . '/myclabs/php-enum/stubs/Stringable.php',
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'XdbSearcher' => $vendorDir . '/zoujingli/ip2region/XdbSearcher.php',
); );

View File

@ -245,11 +245,13 @@ class ComposerStaticInit2bc4f313dba415539e266f7ac2c87dcd
public static $classMap = array ( public static $classMap = array (
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'Ip2Region' => __DIR__ . '/..' . '/zoujingli/ip2region/Ip2Region.php',
'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php',
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
'Stringable' => __DIR__ . '/..' . '/myclabs/php-enum/stubs/Stringable.php', 'Stringable' => __DIR__ . '/..' . '/myclabs/php-enum/stubs/Stringable.php',
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
'XdbSearcher' => __DIR__ . '/..' . '/zoujingli/ip2region/XdbSearcher.php',
); );
public static function getInitializer(ClassLoader $loader) public static function getInitializer(ClassLoader $loader)

View File

@ -2735,6 +2735,55 @@
} }
], ],
"install-path": "../topthink/think-installer" "install-path": "../topthink/think-installer"
},
{
"name": "zoujingli/ip2region",
"version": "v2.0.6",
"version_normalized": "2.0.6.0",
"source": {
"type": "git",
"url": "https://github.com/zoujingli/ip2region.git",
"reference": "66895178be204521e9f5ae9df0ea502893ee53b2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zoujingli/ip2region/zipball/66895178be204521e9f5ae9df0ea502893ee53b2",
"reference": "66895178be204521e9f5ae9df0ea502893ee53b2",
"shasum": ""
},
"require": {
"php": ">=5.4"
},
"time": "2024-08-02T01:01:01+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"classmap": [
"Ip2Region.php",
"XdbSearcher.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Anyon",
"email": "zoujingli@qq.com",
"homepage": "https://thinkadmin.top"
}
],
"description": "Ip2Region for PHP",
"homepage": "https://github.com/zoujingli/Ip2Region",
"keywords": [
"Ip2Region"
],
"support": {
"issues": "https://github.com/zoujingli/ip2region/issues",
"source": "https://github.com/zoujingli/ip2region/tree/v2.0.6"
},
"install-path": "../zoujingli/ip2region"
} }
], ],
"dev": true, "dev": true,

View File

@ -3,7 +3,7 @@
'name' => 'topthink/think', 'name' => 'topthink/think',
'pretty_version' => 'dev-main', 'pretty_version' => 'dev-main',
'version' => 'dev-main', 'version' => 'dev-main',
'reference' => '96a7b429339e68a8dfd3eaa4457d6f8cfdf0e6d5', 'reference' => 'c9296ecb2ae6905df00593530a8784f2997e182a',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
@ -400,7 +400,7 @@
'topthink/think' => array( 'topthink/think' => array(
'pretty_version' => 'dev-main', 'pretty_version' => 'dev-main',
'version' => 'dev-main', 'version' => 'dev-main',
'reference' => '96a7b429339e68a8dfd3eaa4457d6f8cfdf0e6d5', 'reference' => 'c9296ecb2ae6905df00593530a8784f2997e182a',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
@ -415,5 +415,14 @@
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'zoujingli/ip2region' => array(
'pretty_version' => 'v2.0.6',
'version' => '2.0.6.0',
'reference' => '66895178be204521e9f5ae9df0ea502893ee53b2',
'type' => 'library',
'install_path' => __DIR__ . '/../zoujingli/ip2region',
'aliases' => array(),
'dev_requirement' => false,
),
), ),
); );

View File

@ -0,0 +1,5 @@
.idea/
/vendor
composer.lock
extensions.php
.php_cs.cache

View File

@ -0,0 +1,29 @@
<?php
$header = <<<EOF
This file is part of the EasyWeChatComposer.
(c) 张铭阳 <mingyoungcheung@gmail.com>
This source file is subject to the MIT license that is bundled
with this source code in the file LICENSE.
EOF;
return PhpCsFixer\Config::create()
->setRiskyAllowed(true)
->setRules([
'@Symfony' => true,
'header_comment' => ['header' => $header],
'declare_strict_types' => true,
'ordered_imports' => true,
'strict_comparison' => true,
'no_empty_comment' => false,
'yoda_style' => false,
])
->setFinder(
PhpCsFixer\Finder::create()
->exclude('vendor')
->notPath('src/Laravel/config.php', 'src/Laravel/routes.php')
->in(__DIR__)
)
;

View File

@ -0,0 +1,12 @@
language: php
php:
- 7.0
- 7.1
- 7.2
- 7.3
install:
- travis_retry composer install --no-interaction --no-suggest
script: ./vendor/bin/phpunit

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 张铭阳
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,55 @@
<p align="center">
<h1 align="center">EasyWeChat Composer Plugin</h1>
</p>
<p align="center">
<a href="https://travis-ci.org/mingyoung/easywechat-composer"><img src="https://travis-ci.org/mingyoung/easywechat-composer.svg" alt="Build Status"></a>
<a href="https://scrutinizer-ci.com/g/mingyoung/easywechat-composer/?branch=master"><img src="https://scrutinizer-ci.com/g/mingyoung/easywechat-composer/badges/quality-score.png?b=master" alt="Scrutinizer Code Quality"></a>
<a href="https://packagist.org/packages/easywechat-composer/easywechat-composer"><img src="https://poser.pugx.org/easywechat-composer/easywechat-composer/v/stable.svg" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/easywechat-composer/easywechat-composer"><img src="https://poser.pugx.org/easywechat-composer/easywechat-composer/d/total.svg" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/easywechat-composer/easywechat-composer"><img src="https://poser.pugx.org/easywechat-composer/easywechat-composer/license.svg" alt="License"></a>
</p>
Usage
---
Set the `type` to be `easywechat-extension` in your package composer.json file:
```json
{
"name": "your/package",
"type": "easywechat-extension"
}
```
Specify server observer classes in the extra section:
```json
{
"name": "your/package",
"type": "easywechat-extension",
"extra": {
"observers": [
"Acme\\Observers\\Handler"
]
}
}
```
Examples
---
* [easywechat-composer/open-platform-testcase](https://github.com/mingyoung/open-platform-testcase)
Server Delegation
---
> 目前仅支持 Laravel
1. 在 `config/app.php` 中添加 `EasyWeChatComposer\Laravel\ServiceProvider::class`
2. 在**本地项目**的 `.env` 文件中添加如下配置:
```
EASYWECHAT_DELEGATION=true # false 则不启用
EASYWECHAT_DELEGATION_HOST=https://example.com # 线上域名
```

View File

@ -0,0 +1,35 @@
{
"name": "easywechat-composer/easywechat-composer",
"description": "The composer plugin for EasyWeChat",
"type": "composer-plugin",
"license": "MIT",
"authors": [
{
"name": "张铭阳",
"email": "mingyoungcheung@gmail.com"
}
],
"require": {
"php": ">=7.0",
"composer-plugin-api": "^1.0 || ^2.0"
},
"require-dev": {
"composer/composer": "^1.0 || ^2.0",
"phpunit/phpunit": "^6.5 || ^7.0"
},
"autoload": {
"psr-4": {
"EasyWeChatComposer\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"EasyWeChatComposer\\Tests\\": "tests/"
}
},
"extra": {
"class": "EasyWeChatComposer\\Plugin"
},
"minimum-stability": "dev",
"prefer-stable": true
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.0/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
forceCoversAnnotation="true"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
verbose="true">
<testsuite name="EasyWeChatComposer Test">
<directory suffix="Test.php">tests</directory>
</testsuite>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</phpunit>

View File

@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Commands;
use Composer\Command\BaseCommand;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ExtensionsCommand extends BaseCommand
{
/**
* Configures the current command.
*/
protected function configure()
{
$this->setName('easywechat:extensions')
->setDescription('Lists all installed extensions.');
}
/**
* Executes the current command.
*
* @param InputInterface $input
* @param OutputInterface $output
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$extensions = require __DIR__.'/../../extensions.php';
if (empty($extensions) || !is_array($extensions)) {
return $output->writeln('<info>No extension installed.</info>');
}
$table = new Table($output);
$table->setHeaders(['Name', 'Observers'])
->setRows(
array_map([$this, 'getRows'], array_keys($extensions), $extensions)
)->render();
}
/**
* @param string $name
* @param array $extension
*
* @return array
*/
protected function getRows($name, $extension)
{
return [$name, implode("\n", $extension['observers'] ?? [])];
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Commands;
use Composer\Plugin\Capability\CommandProvider;
class Provider implements CommandProvider
{
/**
* Retrieves an array of commands.
*
* @return \Composer\Command\BaseCommand[]
*/
public function getCommands()
{
return [
new ExtensionsCommand(),
];
}
}

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Contracts;
interface Encrypter
{
/**
* Encrypt the given value.
*
* @param string $value
*
* @return string
*/
public function encrypt($value);
/**
* Decrypt the given value.
*
* @param string $payload
*
* @return string
*/
public function decrypt($payload);
}

View File

@ -0,0 +1,80 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Delegation;
use EasyWeChatComposer\EasyWeChat;
class DelegationOptions
{
/**
* @var array
*/
protected $config = [
'enabled' => false,
];
/**
* @return $this
*/
public function enable()
{
$this->config['enabled'] = true;
return $this;
}
/**
* @return $this
*/
public function disable()
{
$this->config['enabled'] = false;
return $this;
}
/**
* @param bool $ability
*
* @return $this
*/
public function ability($ability)
{
$this->config['enabled'] = (bool) $ability;
return $this;
}
/**
* @param string $host
*
* @return $this
*/
public function toHost($host)
{
$this->config['host'] = $host;
return $this;
}
/**
* Destructor.
*/
public function __destruct()
{
EasyWeChat::mergeConfig([
'delegation' => $this->config,
]);
}
}

View File

@ -0,0 +1,83 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Delegation;
use EasyWeChatComposer\Traits\MakesHttpRequests;
class DelegationTo
{
use MakesHttpRequests;
/**
* @var \EasyWeChat\Kernel\ServiceContainer
*/
protected $app;
/**
* @var array
*/
protected $identifiers = [];
/**
* @param \EasyWeChat\Kernel\ServiceContainer $app
* @param string $identifier
*/
public function __construct($app, $identifier)
{
$this->app = $app;
$this->push($identifier);
}
/**
* @param string $identifier
*/
public function push($identifier)
{
$this->identifiers[] = $identifier;
}
/**
* @param string $identifier
*
* @return $this
*/
public function __get($identifier)
{
$this->push($identifier);
return $this;
}
/**
* @param string $method
* @param array $arguments
*
* @return mixed
*/
public function __call($method, $arguments)
{
$config = array_intersect_key($this->app->getConfig(), array_flip(['app_id', 'secret', 'token', 'aes_key', 'response_type', 'component_app_id', 'refresh_token']));
$data = [
'config' => $config,
'application' => get_class($this->app),
'identifiers' => $this->identifiers,
'method' => $method,
'arguments' => $arguments,
];
return $this->request('easywechat-composer/delegate', $data);
}
}

View File

@ -0,0 +1,83 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Delegation;
use EasyWeChat;
use EasyWeChatComposer\Http\DelegationResponse;
class Hydrate
{
/**
* @var array
*/
protected $attributes;
/**
* @param array $attributes
*/
public function __construct(array $attributes)
{
$this->attributes = $attributes;
}
/**
* @return array
*/
public function handle()
{
$app = $this->createsApplication()->shouldntDelegate();
foreach ($this->attributes['identifiers'] as $identifier) {
$app = $app->$identifier;
}
return call_user_func_array([$app, $this->attributes['method']], $this->attributes['arguments']);
}
/**
* @return \EasyWeChat\Kernel\ServiceContainer
*/
protected function createsApplication()
{
$application = $this->attributes['application'];
if ($application === EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\Application::class) {
return $this->createsOpenPlatformApplication('officialAccount');
}
if ($application === EasyWeChat\OpenPlatform\Authorizer\MiniProgram\Application::class) {
return $this->createsOpenPlatformApplication('miniProgram');
}
return new $application($this->buildConfig($this->attributes['config']));
}
protected function createsOpenPlatformApplication($type)
{
$config = $this->attributes['config'];
$authorizerAppId = $config['app_id'];
$config['app_id'] = $config['component_app_id'];
return EasyWeChat\Factory::openPlatform($this->buildConfig($config))->$type($authorizerAppId, $config['refresh_token']);
}
protected function buildConfig(array $config)
{
$config['response_type'] = DelegationResponse::class;
return $config;
}
}

View File

@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer;
use EasyWeChatComposer\Delegation\DelegationOptions;
class EasyWeChat
{
/**
* @var array
*/
protected static $config = [];
/**
* Encryption key.
*
* @var string
*/
protected static $encryptionKey;
/**
* @param array $config
*/
public static function mergeConfig(array $config)
{
static::$config = array_merge(static::$config, $config);
}
/**
* @return array
*/
public static function config()
{
return static::$config;
}
/**
* Set encryption key.
*
* @param string $key
*
* @return static
*/
public static function setEncryptionKey(string $key)
{
static::$encryptionKey = $key;
return new static();
}
/**
* Get encryption key.
*
* @return string
*/
public static function getEncryptionKey(): string
{
return static::$encryptionKey;
}
/**
* @return \EasyWeChatComposer\Delegation\DelegationOptions
*/
public static function withDelegation()
{
return new DelegationOptions();
}
}

View File

@ -0,0 +1,89 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Encryption;
use EasyWeChatComposer\Contracts\Encrypter;
use EasyWeChatComposer\Exceptions\DecryptException;
use EasyWeChatComposer\Exceptions\EncryptException;
class DefaultEncrypter implements Encrypter
{
/**
* @var string
*/
protected $key;
/**
* @var string
*/
protected $cipher;
/**
* @param string $key
* @param string $cipher
*/
public function __construct($key, $cipher = 'AES-256-CBC')
{
$this->key = $key;
$this->cipher = $cipher;
}
/**
* Encrypt the given value.
*
* @param string $value
*
* @return string
*
* @throws \EasyWeChatComposer\Exceptions\EncryptException
*/
public function encrypt($value)
{
$iv = random_bytes(openssl_cipher_iv_length($this->cipher));
$value = openssl_encrypt($value, $this->cipher, $this->key, 0, $iv);
if ($value === false) {
throw new EncryptException('Could not encrypt the data.');
}
$iv = base64_encode($iv);
return base64_encode(json_encode(compact('iv', 'value')));
}
/**
* Decrypt the given value.
*
* @param string $payload
*
* @return string
*
* @throws \EasyWeChatComposer\Exceptions\DecryptException
*/
public function decrypt($payload)
{
$payload = json_decode(base64_decode($payload), true);
$iv = base64_decode($payload['iv']);
$decrypted = openssl_decrypt($payload['value'], $this->cipher, $this->key, 0, $iv);
if ($decrypted === false) {
throw new DecryptException('Could not decrypt the data.');
}
return $decrypted;
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Exceptions;
use Exception;
class DecryptException extends Exception
{
//
}

View File

@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Exceptions;
use Exception;
class DelegationException extends Exception
{
/**
* @var string
*/
protected $exception;
/**
* @param string $exception
*/
public function setException($exception)
{
$this->exception = $exception;
return $this;
}
/**
* @return string
*/
public function getException()
{
return $this->exception;
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Exceptions;
use Exception;
class EncryptException extends Exception
{
//
}

View File

@ -0,0 +1,143 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer;
use EasyWeChat\Kernel\Contracts\EventHandlerInterface;
use Pimple\Container;
use ReflectionClass;
class Extension
{
/**
* @var \Pimple\Container
*/
protected $app;
/**
* @var string
*/
protected $manifestPath;
/**
* @var array|null
*/
protected $manifest;
/**
* @param \Pimple\Container $app
*/
public function __construct(Container $app)
{
$this->app = $app;
$this->manifestPath = __DIR__.'/../extensions.php';
}
/**
* Get observers.
*
* @return array
*/
public function observers(): array
{
if ($this->shouldIgnore()) {
return [];
}
$observers = [];
foreach ($this->getManifest() as $name => $extra) {
$observers = array_merge($observers, $extra['observers'] ?? []);
}
return array_map([$this, 'listObserver'], array_filter($observers, [$this, 'validateObserver']));
}
/**
* @param mixed $observer
*
* @return bool
*/
protected function isDisable($observer): bool
{
return in_array($observer, $this->app->config->get('disable_observers', []));
}
/**
* Get the observers should be ignore.
*
* @return bool
*/
protected function shouldIgnore(): bool
{
return !file_exists($this->manifestPath) || $this->isDisable('*');
}
/**
* Validate the given observer.
*
* @param mixed $observer
*
* @return bool
*
* @throws \ReflectionException
*/
protected function validateObserver($observer): bool
{
return !$this->isDisable($observer)
&& (new ReflectionClass($observer))->implementsInterface(EventHandlerInterface::class)
&& $this->accessible($observer);
}
/**
* Determine whether the given observer is accessible.
*
* @param string $observer
*
* @return bool
*/
protected function accessible($observer): bool
{
if (!method_exists($observer, 'getAccessor')) {
return true;
}
return in_array(get_class($this->app), (array) $observer::getAccessor());
}
/**
* @param mixed $observer
*
* @return array
*/
protected function listObserver($observer): array
{
$condition = method_exists($observer, 'onCondition') ? $observer::onCondition() : '*';
return [$observer, $condition];
}
/**
* Get the easywechat manifest.
*
* @return array
*/
protected function getManifest(): array
{
if (!is_null($this->manifest)) {
return $this->manifest;
}
return $this->manifest = file_exists($this->manifestPath) ? require $this->manifestPath : [];
}
}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Http;
class DelegationResponse extends Response
{
/**
* @return string
*/
public function getBodyContents()
{
return $this->response->getBodyContents();
}
}

View File

@ -0,0 +1,104 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Http;
use EasyWeChat\Kernel\Contracts\Arrayable;
use EasyWeChat\Kernel\Http\Response as HttpResponse;
use JsonSerializable;
class Response implements Arrayable, JsonSerializable
{
/**
* @var \EasyWeChat\Kernel\Http\Response
*/
protected $response;
/**
* @var array
*/
protected $array;
/**
* @param \EasyWeChat\Kernel\Http\Response $response
*/
public function __construct(HttpResponse $response)
{
$this->response = $response;
}
/**
* @see \ArrayAccess::offsetExists
*
* @param string $offset
*
* @return bool
*/
public function offsetExists($offset)
{
return isset($this->toArray()[$offset]);
}
/**
* @see \ArrayAccess::offsetGet
*
* @param string $offset
*
* @return mixed
*/
public function offsetGet($offset)
{
return $this->toArray()[$offset] ?? null;
}
/**
* @see \ArrayAccess::offsetSet
*
* @param string $offset
* @param mixed $value
*/
public function offsetSet($offset, $value)
{
//
}
/**
* @see \ArrayAccess::offsetUnset
*
* @param string $offset
*/
public function offsetUnset($offset)
{
//
}
/**
* Get the instance as an array.
*
* @return array
*/
public function toArray()
{
return $this->array ?: $this->array = $this->response->toArray();
}
/**
* Convert the object into something JSON serializable.
*
* @return array
*/
public function jsonSerialize()
{
return $this->toArray();
}
}

View File

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Laravel\Http\Controllers;
use EasyWeChatComposer\Delegation\Hydrate;
use EasyWeChatComposer\Encryption\DefaultEncrypter;
use Illuminate\Http\Request;
use Throwable;
class DelegatesController
{
/**
* @param \Illuminate\Http\Request $request
* @param \EasyWeChatComposer\Encryption\DefaultEncrypter $encrypter
*
* @return \Illuminate\Http\Response
*/
public function __invoke(Request $request, DefaultEncrypter $encrypter)
{
try {
$data = json_decode($encrypter->decrypt($request->get('encrypted')), true);
$hydrate = new Hydrate($data);
$response = $hydrate->handle();
return response()->json([
'response_type' => get_class($response),
'response' => $encrypter->encrypt($response->getBodyContents()),
]);
} catch (Throwable $t) {
return [
'exception' => get_class($t),
'message' => $t->getMessage(),
];
}
}
}

View File

@ -0,0 +1,116 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Laravel;
use EasyWeChatComposer\EasyWeChat;
use EasyWeChatComposer\Encryption\DefaultEncrypter;
use Illuminate\Foundation\Application;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider as LaravelServiceProvider;
use RuntimeException;
class ServiceProvider extends LaravelServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot()
{
$this->registerRoutes();
$this->publishes([
__DIR__.'/config.php' => config_path('easywechat-composer.php'),
]);
EasyWeChat::setEncryptionKey(
$defaultKey = $this->getKey()
);
EasyWeChat::withDelegation()
->toHost($this->config('delegation.host'))
->ability($this->config('delegation.enabled'));
$this->app->when(DefaultEncrypter::class)->needs('$key')->give($defaultKey);
}
/**
* Register routes.
*/
protected function registerRoutes()
{
Route::prefix('easywechat-composer')->namespace('EasyWeChatComposer\Laravel\Http\Controllers')->group(function () {
$this->loadRoutesFrom(__DIR__.'/routes.php');
});
}
/**
* Register any application services.
*/
public function register()
{
$this->configure();
}
/**
* Register config.
*/
protected function configure()
{
$this->mergeConfigFrom(
__DIR__.'/config.php', 'easywechat-composer'
);
}
/**
* Get the specified configuration value.
*
* @param string|null $key
* @param mixed $default
*
* @return mixed
*/
protected function config($key = null, $default = null)
{
$config = $this->app['config']->get('easywechat-composer');
if (is_null($key)) {
return $config;
}
return Arr::get($config, $key, $default);
}
/**
* @return string
*/
protected function getKey()
{
return $this->config('encryption.key') ?: $this->getMd5Key();
}
/**
* @return string
*/
protected function getMd5Key()
{
$ttl = (version_compare(Application::VERSION, '5.8') === -1) ? 30 : 1800;
return Cache::remember('easywechat-composer.encryption_key', $ttl, function () {
throw_unless(file_exists($path = base_path('composer.lock')), RuntimeException::class, 'No encryption key provided.');
return md5_file($path);
});
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) mingyoung <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
return [
'encryption' => [
'key' => env('EASYWECHAT_KEY'),
],
'delegation' => [
'enabled' => env('EASYWECHAT_DELEGATION', false),
'host' => env('EASYWECHAT_DELEGATION_HOST'),
],
];

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
use Illuminate\Support\Facades\Route;
Route::post('delegate', 'DelegatesController');

View File

@ -0,0 +1,127 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer;
use Composer\Plugin\PluginInterface;
class ManifestManager
{
const PACKAGE_TYPE = 'easywechat-extension';
const EXTRA_OBSERVER = 'observers';
/**
* The vendor path.
*
* @var string
*/
protected $vendorPath;
/**
* The manifest path.
*
* @var string
*/
protected $manifestPath;
/**
* @param string $vendorPath
* @param string|null $manifestPath
*/
public function __construct(string $vendorPath, string $manifestPath = null)
{
$this->vendorPath = $vendorPath;
$this->manifestPath = $manifestPath ?: $vendorPath.'/easywechat-composer/easywechat-composer/extensions.php';
}
/**
* Remove manifest file.
*
* @return $this
*/
public function unlink()
{
if (file_exists($this->manifestPath)) {
@unlink($this->manifestPath);
}
return $this;
}
/**
* Build the manifest file.
*/
public function build()
{
$packages = [];
if (file_exists($installed = $this->vendorPath.'/composer/installed.json')) {
$packages = json_decode(file_get_contents($installed), true);
if (version_compare(PluginInterface::PLUGIN_API_VERSION, '2.0.0', 'ge')) {
$packages = $packages['packages'];
}
}
$this->write($this->map($packages));
}
/**
* @param array $packages
*
* @return array
*/
protected function map(array $packages): array
{
$manifest = [];
$packages = array_filter($packages, function ($package) {
if(isset($package['type'])){
return $package['type'] === self::PACKAGE_TYPE;
}
});
foreach ($packages as $package) {
$manifest[$package['name']] = [self::EXTRA_OBSERVER => $package['extra'][self::EXTRA_OBSERVER] ?? []];
}
return $manifest;
}
/**
* Write the manifest array to a file.
*
* @param array $manifest
*/
protected function write(array $manifest)
{
file_put_contents(
$this->manifestPath,
'<?php return '.var_export($manifest, true).';'
);
$this->invalidate($this->manifestPath);
}
/**
* Invalidate the given file.
*
* @param string $file
*/
protected function invalidate($file)
{
if (function_exists('opcache_invalidate')) {
@opcache_invalidate($file, true);
}
}
}

View File

@ -0,0 +1,107 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Installer\PackageEvent;
use Composer\Installer\PackageEvents;
use Composer\IO\IOInterface;
use Composer\Plugin\Capable;
use Composer\Plugin\PluginInterface;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
class Plugin implements PluginInterface, EventSubscriberInterface, Capable
{
/**
* @var bool
*/
protected $activated = true;
/**
* Apply plugin modifications to Composer.
*/
public function activate(Composer $composer, IOInterface $io)
{
//
}
/**
* Remove any hooks from Composer.
*
* This will be called when a plugin is deactivated before being
* uninstalled, but also before it gets upgraded to a new version
* so the old one can be deactivated and the new one activated.
*/
public function deactivate(Composer $composer, IOInterface $io)
{
//
}
/**
* Prepare the plugin to be uninstalled.
*
* This will be called after deactivate.
*/
public function uninstall(Composer $composer, IOInterface $io)
{
}
/**
* @return array
*/
public function getCapabilities()
{
return [
'Composer\Plugin\Capability\CommandProvider' => 'EasyWeChatComposer\Commands\Provider',
];
}
/**
* Listen events.
*
* @return array
*/
public static function getSubscribedEvents()
{
return [
PackageEvents::PRE_PACKAGE_UNINSTALL => 'prePackageUninstall',
ScriptEvents::POST_AUTOLOAD_DUMP => 'postAutoloadDump',
];
}
/**
* @param \Composer\Installer\PackageEvent
*/
public function prePackageUninstall(PackageEvent $event)
{
if ($event->getOperation()->getPackage()->getName() === 'overtrue/wechat') {
$this->activated = false;
}
}
public function postAutoloadDump(Event $event)
{
if (!$this->activated) {
return;
}
$manifest = new ManifestManager(
rtrim($event->getComposer()->getConfig()->get('vendor-dir'), '/')
);
$manifest->unlink()->build();
}
}

View File

@ -0,0 +1,110 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Traits;
use EasyWeChat\Kernel\Http\StreamResponse;
use EasyWeChat\Kernel\Traits\ResponseCastable;
use EasyWeChatComposer\Contracts\Encrypter;
use EasyWeChatComposer\EasyWeChat;
use EasyWeChatComposer\Encryption\DefaultEncrypter;
use EasyWeChatComposer\Exceptions\DelegationException;
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
trait MakesHttpRequests
{
use ResponseCastable;
/**
* @var \GuzzleHttp\ClientInterface
*/
protected $httpClient;
/**
* @var \EasyWeChatComposer\Contracts\Encrypter
*/
protected $encrypter;
/**
* @param string $endpoint
* @param array $payload
*
* @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
*
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function request($endpoint, array $payload)
{
$response = $this->getHttpClient()->request('POST', $endpoint, [
'form_params' => $this->buildFormParams($payload),
]);
$parsed = $this->parseResponse($response);
return $this->detectAndCastResponseToType(
$this->getEncrypter()->decrypt($parsed['response']),
($parsed['response_type'] === StreamResponse::class) ? 'raw' : $this->app['config']['response_type']
);
}
/**
* @param array $payload
*
* @return array
*/
protected function buildFormParams($payload)
{
return [
'encrypted' => $this->getEncrypter()->encrypt(json_encode($payload)),
];
}
/**
* @param \Psr\Http\Message\ResponseInterface $response
*
* @return array
*/
protected function parseResponse($response)
{
$result = json_decode((string) $response->getBody(), true);
if (isset($result['exception'])) {
throw (new DelegationException($result['message']))->setException($result['exception']);
}
return $result;
}
/**
* @return \GuzzleHttp\ClientInterface
*/
protected function getHttpClient(): ClientInterface
{
return $this->httpClient ?: $this->httpClient = new Client([
'base_uri' => $this->app['config']['delegation']['host'],
]);
}
/**
* @return \EasyWeChatComposer\Contracts\Encrypter
*/
protected function getEncrypter(): Encrypter
{
return $this->encrypter ?: $this->encrypter = new DefaultEncrypter(
EasyWeChat::getEncryptionKey()
);
}
}

View File

@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Traits;
use EasyWeChat\Kernel\BaseClient;
use EasyWeChatComposer\Delegation\DelegationTo;
use EasyWeChatComposer\EasyWeChat;
trait WithAggregator
{
/**
* Aggregate.
*/
protected function aggregate()
{
foreach (EasyWeChat::config() as $key => $value) {
$this['config']->set($key, $value);
}
}
/**
* @return bool
*/
public function shouldDelegate($id)
{
return $this['config']->get('delegation.enabled')
&& $this->offsetGet($id) instanceof BaseClient;
}
/**
* @return $this
*/
public function shouldntDelegate()
{
$this['config']->set('delegation.enabled', false);
return $this;
}
/**
* @param string $id
*
* @return \EasyWeChatComposer\Delegation
*/
public function delegateTo($id)
{
return new DelegationTo($this, $id);
}
}

View File

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
/*
* This file is part of the EasyWeChatComposer.
*
* (c) 张铭阳 <mingyoungcheung@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace EasyWeChatComposer\Tests;
use EasyWeChatComposer\ManifestManager;
use PHPUnit\Framework\TestCase;
class ManifestManagerTest extends TestCase
{
private $vendorPath;
private $manifestPath;
protected function getManifestManager()
{
return new ManifestManager(
$this->vendorPath = __DIR__.'/__fixtures__/vendor/',
$this->manifestPath = __DIR__.'/__fixtures__/extensions.php'
);
}
public function testUnlink()
{
$this->assertInstanceOf(ManifestManager::class, $this->getManifestManager()->unlink());
$this->assertFalse(file_exists($this->manifestPath));
}
}

1664
vendor/guzzlehttp/guzzle/CHANGELOG.md vendored Normal file

File diff suppressed because it is too large Load Diff

27
vendor/guzzlehttp/guzzle/LICENSE vendored Normal file
View File

@ -0,0 +1,27 @@
The MIT License (MIT)
Copyright (c) 2011 Michael Dowling <mtdowling@gmail.com>
Copyright (c) 2012 Jeremy Lindblom <jeremeamia@gmail.com>
Copyright (c) 2014 Graham Campbell <hello@gjcampbell.co.uk>
Copyright (c) 2015 Márk Sági-Kazár <mark.sagikazar@gmail.com>
Copyright (c) 2015 Tobias Schultze <webmaster@tubo-world.de>
Copyright (c) 2016 Tobias Nyholm <tobias.nyholm@gmail.com>
Copyright (c) 2016 George Mponos <gmponos@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

94
vendor/guzzlehttp/guzzle/README.md vendored Normal file
View File

@ -0,0 +1,94 @@
![Guzzle](.github/logo.png?raw=true)
# Guzzle, PHP HTTP client
[![Latest Version](https://img.shields.io/github/release/guzzle/guzzle.svg?style=flat-square)](https://github.com/guzzle/guzzle/releases)
[![Build Status](https://img.shields.io/github/actions/workflow/status/guzzle/guzzle/ci.yml?label=ci%20build&style=flat-square)](https://github.com/guzzle/guzzle/actions?query=workflow%3ACI)
[![Total Downloads](https://img.shields.io/packagist/dt/guzzlehttp/guzzle.svg?style=flat-square)](https://packagist.org/packages/guzzlehttp/guzzle)
Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
trivial to integrate with web services.
- Simple interface for building query strings, POST requests, streaming large
uploads, streaming large downloads, using HTTP cookies, uploading JSON data,
etc...
- Can send both synchronous and asynchronous requests using the same interface.
- Uses PSR-7 interfaces for requests, responses, and streams. This allows you
to utilize other PSR-7 compatible libraries with Guzzle.
- Supports PSR-18 allowing interoperability between other PSR-18 HTTP Clients.
- Abstracts away the underlying HTTP transport, allowing you to write
environment and transport agnostic code; i.e., no hard dependency on cURL,
PHP streams, sockets, or non-blocking event loops.
- Middleware system allows you to augment and compose client behavior.
```php
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');
echo $response->getStatusCode(); // 200
echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8'
echo $response->getBody(); // '{"id": 1420053, "name": "guzzle", ...}'
// Send an asynchronous request.
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
$promise = $client->sendAsync($request)->then(function ($response) {
echo 'I completed! ' . $response->getBody();
});
$promise->wait();
```
## Help and docs
We use GitHub issues only to discuss bugs and new features. For support please refer to:
- [Documentation](https://docs.guzzlephp.org)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/guzzle)
- [#guzzle](https://app.slack.com/client/T0D2S9JCT/CE6UAAKL4) channel on [PHP-HTTP Slack](https://slack.httplug.io/)
- [Gitter](https://gitter.im/guzzle/guzzle)
## Installing Guzzle
The recommended way to install Guzzle is through
[Composer](https://getcomposer.org/).
```bash
composer require guzzlehttp/guzzle
```
## Version Guidance
| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version |
|---------|---------------------|---------------------|--------------|---------------------|---------------------|-------|--------------|
| 3.x | EOL (2016-10-31) | `guzzle/guzzle` | `Guzzle` | [v3][guzzle-3-repo] | [v3][guzzle-3-docs] | No | >=5.3.3,<7.0 |
| 4.x | EOL (2016-10-31) | `guzzlehttp/guzzle` | `GuzzleHttp` | [v4][guzzle-4-repo] | N/A | No | >=5.4,<7.0 |
| 5.x | EOL (2019-10-31) | `guzzlehttp/guzzle` | `GuzzleHttp` | [v5][guzzle-5-repo] | [v5][guzzle-5-docs] | No | >=5.4,<7.4 |
| 6.x | EOL (2023-10-31) | `guzzlehttp/guzzle` | `GuzzleHttp` | [v6][guzzle-6-repo] | [v6][guzzle-6-docs] | Yes | >=5.5,<8.0 |
| 7.x | Latest | `guzzlehttp/guzzle` | `GuzzleHttp` | [v7][guzzle-7-repo] | [v7][guzzle-7-docs] | Yes | >=7.2.5,<8.5 |
[guzzle-3-repo]: https://github.com/guzzle/guzzle3
[guzzle-4-repo]: https://github.com/guzzle/guzzle/tree/4.x
[guzzle-5-repo]: https://github.com/guzzle/guzzle/tree/5.3
[guzzle-6-repo]: https://github.com/guzzle/guzzle/tree/6.5
[guzzle-7-repo]: https://github.com/guzzle/guzzle
[guzzle-3-docs]: https://guzzle3.readthedocs.io/
[guzzle-5-docs]: https://docs.guzzlephp.org/en/5.3/
[guzzle-6-docs]: https://docs.guzzlephp.org/en/6.5/
[guzzle-7-docs]: https://docs.guzzlephp.org/en/latest/
## Security
If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/guzzle/security/policy) for more information.
## License
Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information.
## For Enterprise
Available as part of the Tidelift Subscription
The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-guzzle?utm_source=packagist-guzzlehttp-guzzle&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)

1253
vendor/guzzlehttp/guzzle/UPGRADING.md vendored Normal file

File diff suppressed because it is too large Load Diff

131
vendor/guzzlehttp/guzzle/composer.json vendored Normal file
View File

@ -0,0 +1,131 @@
{
"name": "guzzlehttp/guzzle",
"description": "Guzzle is a PHP HTTP client library",
"keywords": [
"framework",
"http",
"rest",
"web service",
"curl",
"client",
"HTTP client",
"PSR-7",
"PSR-18"
],
"license": "MIT",
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Jeremy Lindblom",
"email": "jeremeamia@gmail.com",
"homepage": "https://github.com/jeremeamia"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"repositories": [
{
"type": "package",
"package": {
"name": "guzzle/client-integration-tests",
"version": "v3.0.2",
"dist": {
"url": "https://codeload.github.com/guzzle/client-integration-tests/zip/2c025848417c1135031fdf9c728ee53d0a7ceaee",
"type": "zip"
},
"require": {
"php": "^7.2.5 || ^8.0",
"phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.11",
"php-http/message": "^1.0 || ^2.0",
"guzzlehttp/psr7": "^1.7 || ^2.0",
"th3n3rd/cartesian-product": "^0.3"
},
"autoload": {
"psr-4": {
"Http\\Client\\Tests\\": "src/"
}
},
"bin": [
"bin/http_test_server"
]
}
}
],
"require": {
"php": "^7.2.5 || ^8.0",
"ext-json": "*",
"guzzlehttp/promises": "^1.5.3 || ^2.0.3",
"guzzlehttp/psr7": "^2.7.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
},
"provide": {
"psr/http-client-implementation": "1.0"
},
"require-dev": {
"ext-curl": "*",
"bamarni/composer-bin-plugin": "^1.8.2",
"guzzle/client-integration-tests": "3.0.2",
"php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.39 || ^9.6.20",
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
"suggest": {
"ext-curl": "Required for CURL handler support",
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"config": {
"allow-plugins": {
"bamarni/composer-bin-plugin": true
},
"preferred-install": "dist",
"sort-packages": true
},
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"autoload-dev": {
"psr-4": {
"GuzzleHttp\\Tests\\": "tests/"
}
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace GuzzleHttp;
use Psr\Http\Message\MessageInterface;
final class BodySummarizer implements BodySummarizerInterface
{
/**
* @var int|null
*/
private $truncateAt;
public function __construct(?int $truncateAt = null)
{
$this->truncateAt = $truncateAt;
}
/**
* Returns a summarized message body.
*/
public function summarize(MessageInterface $message): ?string
{
return $this->truncateAt === null
? Psr7\Message::bodySummary($message)
: Psr7\Message::bodySummary($message, $this->truncateAt);
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace GuzzleHttp;
use Psr\Http\Message\MessageInterface;
interface BodySummarizerInterface
{
/**
* Returns a summarized message body.
*/
public function summarize(MessageInterface $message): ?string;
}

483
vendor/guzzlehttp/guzzle/src/Client.php vendored Normal file
View File

@ -0,0 +1,483 @@
<?php
namespace GuzzleHttp;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\InvalidArgumentException;
use GuzzleHttp\Promise as P;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;
/**
* @final
*/
class Client implements ClientInterface, \Psr\Http\Client\ClientInterface
{
use ClientTrait;
/**
* @var array Default request options
*/
private $config;
/**
* Clients accept an array of constructor parameters.
*
* Here's an example of creating a client using a base_uri and an array of
* default request options to apply to each request:
*
* $client = new Client([
* 'base_uri' => 'http://www.foo.com/1.0/',
* 'timeout' => 0,
* 'allow_redirects' => false,
* 'proxy' => '192.168.16.1:10'
* ]);
*
* Client configuration settings include the following options:
*
* - handler: (callable) Function that transfers HTTP requests over the
* wire. The function is called with a Psr7\Http\Message\RequestInterface
* and array of transfer options, and must return a
* GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
* Psr7\Http\Message\ResponseInterface on success.
* If no handler is provided, a default handler will be created
* that enables all of the request options below by attaching all of the
* default middleware to the handler.
* - base_uri: (string|UriInterface) Base URI of the client that is merged
* into relative URIs. Can be a string or instance of UriInterface.
* - **: any request option
*
* @param array $config Client configuration settings.
*
* @see RequestOptions for a list of available request options.
*/
public function __construct(array $config = [])
{
if (!isset($config['handler'])) {
$config['handler'] = HandlerStack::create();
} elseif (!\is_callable($config['handler'])) {
throw new InvalidArgumentException('handler must be a callable');
}
// Convert the base_uri to a UriInterface
if (isset($config['base_uri'])) {
$config['base_uri'] = Psr7\Utils::uriFor($config['base_uri']);
}
$this->configureDefaults($config);
}
/**
* @param string $method
* @param array $args
*
* @return PromiseInterface|ResponseInterface
*
* @deprecated Client::__call will be removed in guzzlehttp/guzzle:8.0.
*/
public function __call($method, $args)
{
if (\count($args) < 1) {
throw new InvalidArgumentException('Magic request methods require a URI and optional options array');
}
$uri = $args[0];
$opts = $args[1] ?? [];
return \substr($method, -5) === 'Async'
? $this->requestAsync(\substr($method, 0, -5), $uri, $opts)
: $this->request($method, $uri, $opts);
}
/**
* Asynchronously send an HTTP request.
*
* @param array $options Request options to apply to the given
* request and to the transfer. See \GuzzleHttp\RequestOptions.
*/
public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface
{
// Merge the base URI into the request URI if needed.
$options = $this->prepareDefaults($options);
return $this->transfer(
$request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),
$options
);
}
/**
* Send an HTTP request.
*
* @param array $options Request options to apply to the given
* request and to the transfer. See \GuzzleHttp\RequestOptions.
*
* @throws GuzzleException
*/
public function send(RequestInterface $request, array $options = []): ResponseInterface
{
$options[RequestOptions::SYNCHRONOUS] = true;
return $this->sendAsync($request, $options)->wait();
}
/**
* The HttpClient PSR (PSR-18) specify this method.
*
* {@inheritDoc}
*/
public function sendRequest(RequestInterface $request): ResponseInterface
{
$options[RequestOptions::SYNCHRONOUS] = true;
$options[RequestOptions::ALLOW_REDIRECTS] = false;
$options[RequestOptions::HTTP_ERRORS] = false;
return $this->sendAsync($request, $options)->wait();
}
/**
* Create and send an asynchronous HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string $method HTTP method
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
*/
public function requestAsync(string $method, $uri = '', array $options = []): PromiseInterface
{
$options = $this->prepareDefaults($options);
// Remove request modifying parameter because it can be done up-front.
$headers = $options['headers'] ?? [];
$body = $options['body'] ?? null;
$version = $options['version'] ?? '1.1';
// Merge the URI into the base URI.
$uri = $this->buildUri(Psr7\Utils::uriFor($uri), $options);
if (\is_array($body)) {
throw $this->invalidBody();
}
$request = new Psr7\Request($method, $uri, $headers, $body, $version);
// Remove the option so that they are not doubly-applied.
unset($options['headers'], $options['body'], $options['version']);
return $this->transfer($request, $options);
}
/**
* Create and send an HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string $method HTTP method.
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
*
* @throws GuzzleException
*/
public function request(string $method, $uri = '', array $options = []): ResponseInterface
{
$options[RequestOptions::SYNCHRONOUS] = true;
return $this->requestAsync($method, $uri, $options)->wait();
}
/**
* Get a client configuration option.
*
* These options include default request options of the client, a "handler"
* (if utilized by the concrete client), and a "base_uri" if utilized by
* the concrete client.
*
* @param string|null $option The config option to retrieve.
*
* @return mixed
*
* @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0.
*/
public function getConfig(?string $option = null)
{
return $option === null
? $this->config
: ($this->config[$option] ?? null);
}
private function buildUri(UriInterface $uri, array $config): UriInterface
{
if (isset($config['base_uri'])) {
$uri = Psr7\UriResolver::resolve(Psr7\Utils::uriFor($config['base_uri']), $uri);
}
if (isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) {
$idnOptions = ($config['idn_conversion'] === true) ? \IDNA_DEFAULT : $config['idn_conversion'];
$uri = Utils::idnUriConvert($uri, $idnOptions);
}
return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
}
/**
* Configures the default options for a client.
*/
private function configureDefaults(array $config): void
{
$defaults = [
'allow_redirects' => RedirectMiddleware::$defaultSettings,
'http_errors' => true,
'decode_content' => true,
'verify' => true,
'cookies' => false,
'idn_conversion' => false,
];
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
// We can only trust the HTTP_PROXY environment variable in a CLI
// process due to the fact that PHP has no reliable mechanism to
// get environment variables that start with "HTTP_".
if (\PHP_SAPI === 'cli' && ($proxy = Utils::getenv('HTTP_PROXY'))) {
$defaults['proxy']['http'] = $proxy;
}
if ($proxy = Utils::getenv('HTTPS_PROXY')) {
$defaults['proxy']['https'] = $proxy;
}
if ($noProxy = Utils::getenv('NO_PROXY')) {
$cleanedNoProxy = \str_replace(' ', '', $noProxy);
$defaults['proxy']['no'] = \explode(',', $cleanedNoProxy);
}
$this->config = $config + $defaults;
if (!empty($config['cookies']) && $config['cookies'] === true) {
$this->config['cookies'] = new CookieJar();
}
// Add the default user-agent header.
if (!isset($this->config['headers'])) {
$this->config['headers'] = ['User-Agent' => Utils::defaultUserAgent()];
} else {
// Add the User-Agent header if one was not already set.
foreach (\array_keys($this->config['headers']) as $name) {
if (\strtolower($name) === 'user-agent') {
return;
}
}
$this->config['headers']['User-Agent'] = Utils::defaultUserAgent();
}
}
/**
* Merges default options into the array.
*
* @param array $options Options to modify by reference
*/
private function prepareDefaults(array $options): array
{
$defaults = $this->config;
if (!empty($defaults['headers'])) {
// Default headers are only added if they are not present.
$defaults['_conditional'] = $defaults['headers'];
unset($defaults['headers']);
}
// Special handling for headers is required as they are added as
// conditional headers and as headers passed to a request ctor.
if (\array_key_exists('headers', $options)) {
// Allows default headers to be unset.
if ($options['headers'] === null) {
$defaults['_conditional'] = [];
unset($options['headers']);
} elseif (!\is_array($options['headers'])) {
throw new InvalidArgumentException('headers must be an array');
}
}
// Shallow merge defaults underneath options.
$result = $options + $defaults;
// Remove null values.
foreach ($result as $k => $v) {
if ($v === null) {
unset($result[$k]);
}
}
return $result;
}
/**
* Transfers the given request and applies request options.
*
* The URI of the request is not modified and the request options are used
* as-is without merging in default options.
*
* @param array $options See \GuzzleHttp\RequestOptions.
*/
private function transfer(RequestInterface $request, array $options): PromiseInterface
{
$request = $this->applyOptions($request, $options);
/** @var HandlerStack $handler */
$handler = $options['handler'];
try {
return P\Create::promiseFor($handler($request, $options));
} catch (\Exception $e) {
return P\Create::rejectionFor($e);
}
}
/**
* Applies the array of request options to a request.
*/
private function applyOptions(RequestInterface $request, array &$options): RequestInterface
{
$modify = [
'set_headers' => [],
];
if (isset($options['headers'])) {
if (array_keys($options['headers']) === range(0, count($options['headers']) - 1)) {
throw new InvalidArgumentException('The headers array must have header name as keys.');
}
$modify['set_headers'] = $options['headers'];
unset($options['headers']);
}
if (isset($options['form_params'])) {
if (isset($options['multipart'])) {
throw new InvalidArgumentException('You cannot use '
.'form_params and multipart at the same time. Use the '
.'form_params option if you want to send application/'
.'x-www-form-urlencoded requests, and the multipart '
.'option to send multipart/form-data requests.');
}
$options['body'] = \http_build_query($options['form_params'], '', '&');
unset($options['form_params']);
// Ensure that we don't have the header in different case and set the new value.
$options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
$options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
}
if (isset($options['multipart'])) {
$options['body'] = new Psr7\MultipartStream($options['multipart']);
unset($options['multipart']);
}
if (isset($options['json'])) {
$options['body'] = Utils::jsonEncode($options['json']);
unset($options['json']);
// Ensure that we don't have the header in different case and set the new value.
$options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
$options['_conditional']['Content-Type'] = 'application/json';
}
if (!empty($options['decode_content'])
&& $options['decode_content'] !== true
) {
// Ensure that we don't have the header in different case and set the new value.
$options['_conditional'] = Psr7\Utils::caselessRemove(['Accept-Encoding'], $options['_conditional']);
$modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
}
if (isset($options['body'])) {
if (\is_array($options['body'])) {
throw $this->invalidBody();
}
$modify['body'] = Psr7\Utils::streamFor($options['body']);
unset($options['body']);
}
if (!empty($options['auth']) && \is_array($options['auth'])) {
$value = $options['auth'];
$type = isset($value[2]) ? \strtolower($value[2]) : 'basic';
switch ($type) {
case 'basic':
// Ensure that we don't have the header in different case and set the new value.
$modify['set_headers'] = Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']);
$modify['set_headers']['Authorization'] = 'Basic '
.\base64_encode("$value[0]:$value[1]");
break;
case 'digest':
// @todo: Do not rely on curl
$options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_DIGEST;
$options['curl'][\CURLOPT_USERPWD] = "$value[0]:$value[1]";
break;
case 'ntlm':
$options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_NTLM;
$options['curl'][\CURLOPT_USERPWD] = "$value[0]:$value[1]";
break;
}
}
if (isset($options['query'])) {
$value = $options['query'];
if (\is_array($value)) {
$value = \http_build_query($value, '', '&', \PHP_QUERY_RFC3986);
}
if (!\is_string($value)) {
throw new InvalidArgumentException('query must be a string or array');
}
$modify['query'] = $value;
unset($options['query']);
}
// Ensure that sink is not an invalid value.
if (isset($options['sink'])) {
// TODO: Add more sink validation?
if (\is_bool($options['sink'])) {
throw new InvalidArgumentException('sink must not be a boolean');
}
}
if (isset($options['version'])) {
$modify['version'] = $options['version'];
}
$request = Psr7\Utils::modifyRequest($request, $modify);
if ($request->getBody() instanceof Psr7\MultipartStream) {
// Use a multipart/form-data POST if a Content-Type is not set.
// Ensure that we don't have the header in different case and set the new value.
$options['_conditional'] = Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']);
$options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
.$request->getBody()->getBoundary();
}
// Merge in conditional headers if they are not present.
if (isset($options['_conditional'])) {
// Build up the changes so it's in a single clone of the message.
$modify = [];
foreach ($options['_conditional'] as $k => $v) {
if (!$request->hasHeader($k)) {
$modify['set_headers'][$k] = $v;
}
}
$request = Psr7\Utils::modifyRequest($request, $modify);
// Don't pass this internal value along to middleware/handlers.
unset($options['_conditional']);
}
return $request;
}
/**
* Return an InvalidArgumentException with pre-set message.
*/
private function invalidBody(): InvalidArgumentException
{
return new InvalidArgumentException('Passing in the "body" request '
.'option as an array to send a request is not supported. '
.'Please use the "form_params" request option to send a '
.'application/x-www-form-urlencoded request, or the "multipart" '
.'request option to send a multipart/form-data request.');
}
}

View File

@ -0,0 +1,84 @@
<?php
namespace GuzzleHttp;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;
/**
* Client interface for sending HTTP requests.
*/
interface ClientInterface
{
/**
* The Guzzle major version.
*/
public const MAJOR_VERSION = 7;
/**
* Send an HTTP request.
*
* @param RequestInterface $request Request to send
* @param array $options Request options to apply to the given
* request and to the transfer.
*
* @throws GuzzleException
*/
public function send(RequestInterface $request, array $options = []): ResponseInterface;
/**
* Asynchronously send an HTTP request.
*
* @param RequestInterface $request Request to send
* @param array $options Request options to apply to the given
* request and to the transfer.
*/
public function sendAsync(RequestInterface $request, array $options = []): PromiseInterface;
/**
* Create and send an HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string $method HTTP method.
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function request(string $method, $uri, array $options = []): ResponseInterface;
/**
* Create and send an asynchronous HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string $method HTTP method
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function requestAsync(string $method, $uri, array $options = []): PromiseInterface;
/**
* Get a client configuration option.
*
* These options include default request options of the client, a "handler"
* (if utilized by the concrete client), and a "base_uri" if utilized by
* the concrete client.
*
* @param string|null $option The config option to retrieve.
*
* @return mixed
*
* @deprecated ClientInterface::getConfig will be removed in guzzlehttp/guzzle:8.0.
*/
public function getConfig(?string $option = null);
}

View File

@ -0,0 +1,241 @@
<?php
namespace GuzzleHttp;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;
/**
* Client interface for sending HTTP requests.
*/
trait ClientTrait
{
/**
* Create and send an HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string $method HTTP method.
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
abstract public function request(string $method, $uri, array $options = []): ResponseInterface;
/**
* Create and send an HTTP GET request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function get($uri, array $options = []): ResponseInterface
{
return $this->request('GET', $uri, $options);
}
/**
* Create and send an HTTP HEAD request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function head($uri, array $options = []): ResponseInterface
{
return $this->request('HEAD', $uri, $options);
}
/**
* Create and send an HTTP PUT request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function put($uri, array $options = []): ResponseInterface
{
return $this->request('PUT', $uri, $options);
}
/**
* Create and send an HTTP POST request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function post($uri, array $options = []): ResponseInterface
{
return $this->request('POST', $uri, $options);
}
/**
* Create and send an HTTP PATCH request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function patch($uri, array $options = []): ResponseInterface
{
return $this->request('PATCH', $uri, $options);
}
/**
* Create and send an HTTP DELETE request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*
* @throws GuzzleException
*/
public function delete($uri, array $options = []): ResponseInterface
{
return $this->request('DELETE', $uri, $options);
}
/**
* Create and send an asynchronous HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string $method HTTP method
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
abstract public function requestAsync(string $method, $uri, array $options = []): PromiseInterface;
/**
* Create and send an asynchronous HTTP GET request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function getAsync($uri, array $options = []): PromiseInterface
{
return $this->requestAsync('GET', $uri, $options);
}
/**
* Create and send an asynchronous HTTP HEAD request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function headAsync($uri, array $options = []): PromiseInterface
{
return $this->requestAsync('HEAD', $uri, $options);
}
/**
* Create and send an asynchronous HTTP PUT request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function putAsync($uri, array $options = []): PromiseInterface
{
return $this->requestAsync('PUT', $uri, $options);
}
/**
* Create and send an asynchronous HTTP POST request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function postAsync($uri, array $options = []): PromiseInterface
{
return $this->requestAsync('POST', $uri, $options);
}
/**
* Create and send an asynchronous HTTP PATCH request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function patchAsync($uri, array $options = []): PromiseInterface
{
return $this->requestAsync('PATCH', $uri, $options);
}
/**
* Create and send an asynchronous HTTP DELETE request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply.
*/
public function deleteAsync($uri, array $options = []): PromiseInterface
{
return $this->requestAsync('DELETE', $uri, $options);
}
}

View File

@ -0,0 +1,307 @@
<?php
namespace GuzzleHttp\Cookie;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Cookie jar that stores cookies as an array
*/
class CookieJar implements CookieJarInterface
{
/**
* @var SetCookie[] Loaded cookie data
*/
private $cookies = [];
/**
* @var bool
*/
private $strictMode;
/**
* @param bool $strictMode Set to true to throw exceptions when invalid
* cookies are added to the cookie jar.
* @param array $cookieArray Array of SetCookie objects or a hash of
* arrays that can be used with the SetCookie
* constructor
*/
public function __construct(bool $strictMode = false, array $cookieArray = [])
{
$this->strictMode = $strictMode;
foreach ($cookieArray as $cookie) {
if (!($cookie instanceof SetCookie)) {
$cookie = new SetCookie($cookie);
}
$this->setCookie($cookie);
}
}
/**
* Create a new Cookie jar from an associative array and domain.
*
* @param array $cookies Cookies to create the jar from
* @param string $domain Domain to set the cookies to
*/
public static function fromArray(array $cookies, string $domain): self
{
$cookieJar = new self();
foreach ($cookies as $name => $value) {
$cookieJar->setCookie(new SetCookie([
'Domain' => $domain,
'Name' => $name,
'Value' => $value,
'Discard' => true,
]));
}
return $cookieJar;
}
/**
* Evaluate if this cookie should be persisted to storage
* that survives between requests.
*
* @param SetCookie $cookie Being evaluated.
* @param bool $allowSessionCookies If we should persist session cookies
*/
public static function shouldPersist(SetCookie $cookie, bool $allowSessionCookies = false): bool
{
if ($cookie->getExpires() || $allowSessionCookies) {
if (!$cookie->getDiscard()) {
return true;
}
}
return false;
}
/**
* Finds and returns the cookie based on the name
*
* @param string $name cookie name to search for
*
* @return SetCookie|null cookie that was found or null if not found
*/
public function getCookieByName(string $name): ?SetCookie
{
foreach ($this->cookies as $cookie) {
if ($cookie->getName() !== null && \strcasecmp($cookie->getName(), $name) === 0) {
return $cookie;
}
}
return null;
}
public function toArray(): array
{
return \array_map(static function (SetCookie $cookie): array {
return $cookie->toArray();
}, $this->getIterator()->getArrayCopy());
}
public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void
{
if (!$domain) {
$this->cookies = [];
return;
} elseif (!$path) {
$this->cookies = \array_filter(
$this->cookies,
static function (SetCookie $cookie) use ($domain): bool {
return !$cookie->matchesDomain($domain);
}
);
} elseif (!$name) {
$this->cookies = \array_filter(
$this->cookies,
static function (SetCookie $cookie) use ($path, $domain): bool {
return !($cookie->matchesPath($path)
&& $cookie->matchesDomain($domain));
}
);
} else {
$this->cookies = \array_filter(
$this->cookies,
static function (SetCookie $cookie) use ($path, $domain, $name) {
return !($cookie->getName() == $name
&& $cookie->matchesPath($path)
&& $cookie->matchesDomain($domain));
}
);
}
}
public function clearSessionCookies(): void
{
$this->cookies = \array_filter(
$this->cookies,
static function (SetCookie $cookie): bool {
return !$cookie->getDiscard() && $cookie->getExpires();
}
);
}
public function setCookie(SetCookie $cookie): bool
{
// If the name string is empty (but not 0), ignore the set-cookie
// string entirely.
$name = $cookie->getName();
if (!$name && $name !== '0') {
return false;
}
// Only allow cookies with set and valid domain, name, value
$result = $cookie->validate();
if ($result !== true) {
if ($this->strictMode) {
throw new \RuntimeException('Invalid cookie: '.$result);
}
$this->removeCookieIfEmpty($cookie);
return false;
}
// Resolve conflicts with previously set cookies
foreach ($this->cookies as $i => $c) {
// Two cookies are identical, when their path, and domain are
// identical.
if ($c->getPath() != $cookie->getPath()
|| $c->getDomain() != $cookie->getDomain()
|| $c->getName() != $cookie->getName()
) {
continue;
}
// The previously set cookie is a discard cookie and this one is
// not so allow the new cookie to be set
if (!$cookie->getDiscard() && $c->getDiscard()) {
unset($this->cookies[$i]);
continue;
}
// If the new cookie's expiration is further into the future, then
// replace the old cookie
if ($cookie->getExpires() > $c->getExpires()) {
unset($this->cookies[$i]);
continue;
}
// If the value has changed, we better change it
if ($cookie->getValue() !== $c->getValue()) {
unset($this->cookies[$i]);
continue;
}
// The cookie exists, so no need to continue
return false;
}
$this->cookies[] = $cookie;
return true;
}
public function count(): int
{
return \count($this->cookies);
}
/**
* @return \ArrayIterator<int, SetCookie>
*/
public function getIterator(): \ArrayIterator
{
return new \ArrayIterator(\array_values($this->cookies));
}
public function extractCookies(RequestInterface $request, ResponseInterface $response): void
{
if ($cookieHeader = $response->getHeader('Set-Cookie')) {
foreach ($cookieHeader as $cookie) {
$sc = SetCookie::fromString($cookie);
if (!$sc->getDomain()) {
$sc->setDomain($request->getUri()->getHost());
}
if (0 !== \strpos($sc->getPath(), '/')) {
$sc->setPath($this->getCookiePathFromRequest($request));
}
if (!$sc->matchesDomain($request->getUri()->getHost())) {
continue;
}
// Note: At this point `$sc->getDomain()` being a public suffix should
// be rejected, but we don't want to pull in the full PSL dependency.
$this->setCookie($sc);
}
}
}
/**
* Computes cookie path following RFC 6265 section 5.1.4
*
* @see https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4
*/
private function getCookiePathFromRequest(RequestInterface $request): string
{
$uriPath = $request->getUri()->getPath();
if ('' === $uriPath) {
return '/';
}
if (0 !== \strpos($uriPath, '/')) {
return '/';
}
if ('/' === $uriPath) {
return '/';
}
$lastSlashPos = \strrpos($uriPath, '/');
if (0 === $lastSlashPos || false === $lastSlashPos) {
return '/';
}
return \substr($uriPath, 0, $lastSlashPos);
}
public function withCookieHeader(RequestInterface $request): RequestInterface
{
$values = [];
$uri = $request->getUri();
$scheme = $uri->getScheme();
$host = $uri->getHost();
$path = $uri->getPath() ?: '/';
foreach ($this->cookies as $cookie) {
if ($cookie->matchesPath($path)
&& $cookie->matchesDomain($host)
&& !$cookie->isExpired()
&& (!$cookie->getSecure() || $scheme === 'https')
) {
$values[] = $cookie->getName().'='
.$cookie->getValue();
}
}
return $values
? $request->withHeader('Cookie', \implode('; ', $values))
: $request;
}
/**
* If a cookie already exists and the server asks to set it again with a
* null value, the cookie must be deleted.
*/
private function removeCookieIfEmpty(SetCookie $cookie): void
{
$cookieValue = $cookie->getValue();
if ($cookieValue === null || $cookieValue === '') {
$this->clear(
$cookie->getDomain(),
$cookie->getPath(),
$cookie->getName()
);
}
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace GuzzleHttp\Cookie;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Stores HTTP cookies.
*
* It extracts cookies from HTTP requests, and returns them in HTTP responses.
* CookieJarInterface instances automatically expire contained cookies when
* necessary. Subclasses are also responsible for storing and retrieving
* cookies from a file, database, etc.
*
* @see https://docs.python.org/2/library/cookielib.html Inspiration
*
* @extends \IteratorAggregate<SetCookie>
*/
interface CookieJarInterface extends \Countable, \IteratorAggregate
{
/**
* Create a request with added cookie headers.
*
* If no matching cookies are found in the cookie jar, then no Cookie
* header is added to the request and the same request is returned.
*
* @param RequestInterface $request Request object to modify.
*
* @return RequestInterface returns the modified request.
*/
public function withCookieHeader(RequestInterface $request): RequestInterface;
/**
* Extract cookies from an HTTP response and store them in the CookieJar.
*
* @param RequestInterface $request Request that was sent
* @param ResponseInterface $response Response that was received
*/
public function extractCookies(RequestInterface $request, ResponseInterface $response): void;
/**
* Sets a cookie in the cookie jar.
*
* @param SetCookie $cookie Cookie to set.
*
* @return bool Returns true on success or false on failure
*/
public function setCookie(SetCookie $cookie): bool;
/**
* Remove cookies currently held in the cookie jar.
*
* Invoking this method without arguments will empty the whole cookie jar.
* If given a $domain argument only cookies belonging to that domain will
* be removed. If given a $domain and $path argument, cookies belonging to
* the specified path within that domain are removed. If given all three
* arguments, then the cookie with the specified name, path and domain is
* removed.
*
* @param string|null $domain Clears cookies matching a domain
* @param string|null $path Clears cookies matching a domain and path
* @param string|null $name Clears cookies matching a domain, path, and name
*/
public function clear(?string $domain = null, ?string $path = null, ?string $name = null): void;
/**
* Discard all sessions cookies.
*
* Removes cookies that don't have an expire field or a have a discard
* field set to true. To be called when the user agent shuts down according
* to RFC 2965.
*/
public function clearSessionCookies(): void;
/**
* Converts the cookie jar to an array.
*/
public function toArray(): array;
}

View File

@ -0,0 +1,101 @@
<?php
namespace GuzzleHttp\Cookie;
use GuzzleHttp\Utils;
/**
* Persists non-session cookies using a JSON formatted file
*/
class FileCookieJar extends CookieJar
{
/**
* @var string filename
*/
private $filename;
/**
* @var bool Control whether to persist session cookies or not.
*/
private $storeSessionCookies;
/**
* Create a new FileCookieJar object
*
* @param string $cookieFile File to store the cookie data
* @param bool $storeSessionCookies Set to true to store session cookies
* in the cookie jar.
*
* @throws \RuntimeException if the file cannot be found or created
*/
public function __construct(string $cookieFile, bool $storeSessionCookies = false)
{
parent::__construct();
$this->filename = $cookieFile;
$this->storeSessionCookies = $storeSessionCookies;
if (\file_exists($cookieFile)) {
$this->load($cookieFile);
}
}
/**
* Saves the file when shutting down
*/
public function __destruct()
{
$this->save($this->filename);
}
/**
* Saves the cookies to a file.
*
* @param string $filename File to save
*
* @throws \RuntimeException if the file cannot be found or created
*/
public function save(string $filename): void
{
$json = [];
/** @var SetCookie $cookie */
foreach ($this as $cookie) {
if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
$json[] = $cookie->toArray();
}
}
$jsonStr = Utils::jsonEncode($json);
if (false === \file_put_contents($filename, $jsonStr, \LOCK_EX)) {
throw new \RuntimeException("Unable to save file {$filename}");
}
}
/**
* Load cookies from a JSON formatted file.
*
* Old cookies are kept unless overwritten by newly loaded ones.
*
* @param string $filename Cookie file to load.
*
* @throws \RuntimeException if the file cannot be loaded.
*/
public function load(string $filename): void
{
$json = \file_get_contents($filename);
if (false === $json) {
throw new \RuntimeException("Unable to load file {$filename}");
}
if ($json === '') {
return;
}
$data = Utils::jsonDecode($json, true);
if (\is_array($data)) {
foreach ($data as $cookie) {
$this->setCookie(new SetCookie($cookie));
}
} elseif (\is_scalar($data) && !empty($data)) {
throw new \RuntimeException("Invalid cookie file: {$filename}");
}
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace GuzzleHttp\Cookie;
/**
* Persists cookies in the client session
*/
class SessionCookieJar extends CookieJar
{
/**
* @var string session key
*/
private $sessionKey;
/**
* @var bool Control whether to persist session cookies or not.
*/
private $storeSessionCookies;
/**
* Create a new SessionCookieJar object
*
* @param string $sessionKey Session key name to store the cookie
* data in session
* @param bool $storeSessionCookies Set to true to store session cookies
* in the cookie jar.
*/
public function __construct(string $sessionKey, bool $storeSessionCookies = false)
{
parent::__construct();
$this->sessionKey = $sessionKey;
$this->storeSessionCookies = $storeSessionCookies;
$this->load();
}
/**
* Saves cookies to session when shutting down
*/
public function __destruct()
{
$this->save();
}
/**
* Save cookies to the client session
*/
public function save(): void
{
$json = [];
/** @var SetCookie $cookie */
foreach ($this as $cookie) {
if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
$json[] = $cookie->toArray();
}
}
$_SESSION[$this->sessionKey] = \json_encode($json);
}
/**
* Load the contents of the client session into the data array
*/
protected function load(): void
{
if (!isset($_SESSION[$this->sessionKey])) {
return;
}
$data = \json_decode($_SESSION[$this->sessionKey], true);
if (\is_array($data)) {
foreach ($data as $cookie) {
$this->setCookie(new SetCookie($cookie));
}
} elseif (\strlen($data)) {
throw new \RuntimeException('Invalid cookie data');
}
}
}

View File

@ -0,0 +1,488 @@
<?php
namespace GuzzleHttp\Cookie;
/**
* Set-Cookie object
*/
class SetCookie
{
/**
* @var array
*/
private static $defaults = [
'Name' => null,
'Value' => null,
'Domain' => null,
'Path' => '/',
'Max-Age' => null,
'Expires' => null,
'Secure' => false,
'Discard' => false,
'HttpOnly' => false,
];
/**
* @var array Cookie data
*/
private $data;
/**
* Create a new SetCookie object from a string.
*
* @param string $cookie Set-Cookie header string
*/
public static function fromString(string $cookie): self
{
// Create the default return array
$data = self::$defaults;
// Explode the cookie string using a series of semicolons
$pieces = \array_filter(\array_map('trim', \explode(';', $cookie)));
// The name of the cookie (first kvp) must exist and include an equal sign.
if (!isset($pieces[0]) || \strpos($pieces[0], '=') === false) {
return new self($data);
}
// Add the cookie pieces into the parsed data array
foreach ($pieces as $part) {
$cookieParts = \explode('=', $part, 2);
$key = \trim($cookieParts[0]);
$value = isset($cookieParts[1])
? \trim($cookieParts[1], " \n\r\t\0\x0B")
: true;
// Only check for non-cookies when cookies have been found
if (!isset($data['Name'])) {
$data['Name'] = $key;
$data['Value'] = $value;
} else {
foreach (\array_keys(self::$defaults) as $search) {
if (!\strcasecmp($search, $key)) {
if ($search === 'Max-Age') {
if (is_numeric($value)) {
$data[$search] = (int) $value;
}
} else {
$data[$search] = $value;
}
continue 2;
}
}
$data[$key] = $value;
}
}
return new self($data);
}
/**
* @param array $data Array of cookie data provided by a Cookie parser
*/
public function __construct(array $data = [])
{
$this->data = self::$defaults;
if (isset($data['Name'])) {
$this->setName($data['Name']);
}
if (isset($data['Value'])) {
$this->setValue($data['Value']);
}
if (isset($data['Domain'])) {
$this->setDomain($data['Domain']);
}
if (isset($data['Path'])) {
$this->setPath($data['Path']);
}
if (isset($data['Max-Age'])) {
$this->setMaxAge($data['Max-Age']);
}
if (isset($data['Expires'])) {
$this->setExpires($data['Expires']);
}
if (isset($data['Secure'])) {
$this->setSecure($data['Secure']);
}
if (isset($data['Discard'])) {
$this->setDiscard($data['Discard']);
}
if (isset($data['HttpOnly'])) {
$this->setHttpOnly($data['HttpOnly']);
}
// Set the remaining values that don't have extra validation logic
foreach (array_diff(array_keys($data), array_keys(self::$defaults)) as $key) {
$this->data[$key] = $data[$key];
}
// Extract the Expires value and turn it into a UNIX timestamp if needed
if (!$this->getExpires() && $this->getMaxAge()) {
// Calculate the Expires date
$this->setExpires(\time() + $this->getMaxAge());
} elseif (null !== ($expires = $this->getExpires()) && !\is_numeric($expires)) {
$this->setExpires($expires);
}
}
public function __toString()
{
$str = $this->data['Name'].'='.($this->data['Value'] ?? '').'; ';
foreach ($this->data as $k => $v) {
if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) {
if ($k === 'Expires') {
$str .= 'Expires='.\gmdate('D, d M Y H:i:s \G\M\T', $v).'; ';
} else {
$str .= ($v === true ? $k : "{$k}={$v}").'; ';
}
}
}
return \rtrim($str, '; ');
}
public function toArray(): array
{
return $this->data;
}
/**
* Get the cookie name.
*
* @return string
*/
public function getName()
{
return $this->data['Name'];
}
/**
* Set the cookie name.
*
* @param string $name Cookie name
*/
public function setName($name): void
{
if (!is_string($name)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Name'] = (string) $name;
}
/**
* Get the cookie value.
*
* @return string|null
*/
public function getValue()
{
return $this->data['Value'];
}
/**
* Set the cookie value.
*
* @param string $value Cookie value
*/
public function setValue($value): void
{
if (!is_string($value)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Value'] = (string) $value;
}
/**
* Get the domain.
*
* @return string|null
*/
public function getDomain()
{
return $this->data['Domain'];
}
/**
* Set the domain of the cookie.
*
* @param string|null $domain
*/
public function setDomain($domain): void
{
if (!is_string($domain) && null !== $domain) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Domain'] = null === $domain ? null : (string) $domain;
}
/**
* Get the path.
*
* @return string
*/
public function getPath()
{
return $this->data['Path'];
}
/**
* Set the path of the cookie.
*
* @param string $path Path of the cookie
*/
public function setPath($path): void
{
if (!is_string($path)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Path'] = (string) $path;
}
/**
* Maximum lifetime of the cookie in seconds.
*
* @return int|null
*/
public function getMaxAge()
{
return null === $this->data['Max-Age'] ? null : (int) $this->data['Max-Age'];
}
/**
* Set the max-age of the cookie.
*
* @param int|null $maxAge Max age of the cookie in seconds
*/
public function setMaxAge($maxAge): void
{
if (!is_int($maxAge) && null !== $maxAge) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Max-Age'] = $maxAge === null ? null : (int) $maxAge;
}
/**
* The UNIX timestamp when the cookie Expires.
*
* @return string|int|null
*/
public function getExpires()
{
return $this->data['Expires'];
}
/**
* Set the unix timestamp for which the cookie will expire.
*
* @param int|string|null $timestamp Unix timestamp or any English textual datetime description.
*/
public function setExpires($timestamp): void
{
if (!is_int($timestamp) && !is_string($timestamp) && null !== $timestamp) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int, string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Expires'] = null === $timestamp ? null : (\is_numeric($timestamp) ? (int) $timestamp : \strtotime((string) $timestamp));
}
/**
* Get whether or not this is a secure cookie.
*
* @return bool
*/
public function getSecure()
{
return $this->data['Secure'];
}
/**
* Set whether or not the cookie is secure.
*
* @param bool $secure Set to true or false if secure
*/
public function setSecure($secure): void
{
if (!is_bool($secure)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Secure'] = (bool) $secure;
}
/**
* Get whether or not this is a session cookie.
*
* @return bool|null
*/
public function getDiscard()
{
return $this->data['Discard'];
}
/**
* Set whether or not this is a session cookie.
*
* @param bool $discard Set to true or false if this is a session cookie
*/
public function setDiscard($discard): void
{
if (!is_bool($discard)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['Discard'] = (bool) $discard;
}
/**
* Get whether or not this is an HTTP only cookie.
*
* @return bool
*/
public function getHttpOnly()
{
return $this->data['HttpOnly'];
}
/**
* Set whether or not this is an HTTP only cookie.
*
* @param bool $httpOnly Set to true or false if this is HTTP only
*/
public function setHttpOnly($httpOnly): void
{
if (!is_bool($httpOnly)) {
trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__);
}
$this->data['HttpOnly'] = (bool) $httpOnly;
}
/**
* Check if the cookie matches a path value.
*
* A request-path path-matches a given cookie-path if at least one of
* the following conditions holds:
*
* - The cookie-path and the request-path are identical.
* - The cookie-path is a prefix of the request-path, and the last
* character of the cookie-path is %x2F ("/").
* - The cookie-path is a prefix of the request-path, and the first
* character of the request-path that is not included in the cookie-
* path is a %x2F ("/") character.
*
* @param string $requestPath Path to check against
*/
public function matchesPath(string $requestPath): bool
{
$cookiePath = $this->getPath();
// Match on exact matches or when path is the default empty "/"
if ($cookiePath === '/' || $cookiePath == $requestPath) {
return true;
}
// Ensure that the cookie-path is a prefix of the request path.
if (0 !== \strpos($requestPath, $cookiePath)) {
return false;
}
// Match if the last character of the cookie-path is "/"
if (\substr($cookiePath, -1, 1) === '/') {
return true;
}
// Match if the first character not included in cookie path is "/"
return \substr($requestPath, \strlen($cookiePath), 1) === '/';
}
/**
* Check if the cookie matches a domain value.
*
* @param string $domain Domain to check against
*/
public function matchesDomain(string $domain): bool
{
$cookieDomain = $this->getDomain();
if (null === $cookieDomain) {
return true;
}
// Remove the leading '.' as per spec in RFC 6265.
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3
$cookieDomain = \ltrim(\strtolower($cookieDomain), '.');
$domain = \strtolower($domain);
// Domain not set or exact match.
if ('' === $cookieDomain || $domain === $cookieDomain) {
return true;
}
// Matching the subdomain according to RFC 6265.
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3
if (\filter_var($domain, \FILTER_VALIDATE_IP)) {
return false;
}
return (bool) \preg_match('/\.'.\preg_quote($cookieDomain, '/').'$/', $domain);
}
/**
* Check if the cookie is expired.
*/
public function isExpired(): bool
{
return $this->getExpires() !== null && \time() > $this->getExpires();
}
/**
* Check if the cookie is valid according to RFC 6265.
*
* @return bool|string Returns true if valid or an error message if invalid
*/
public function validate()
{
$name = $this->getName();
if ($name === '') {
return 'The cookie name must not be empty';
}
// Check if any of the invalid characters are present in the cookie name
if (\preg_match(
'/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
$name
)) {
return 'Cookie name must not contain invalid characters: ASCII '
.'Control characters (0-31;127), space, tab and the '
.'following characters: ()<>@,;:\"/?={}';
}
// Value must not be null. 0 and empty string are valid. Empty strings
// are technically against RFC 6265, but known to happen in the wild.
$value = $this->getValue();
if ($value === null) {
return 'The cookie value must not be empty';
}
// Domains must not be empty, but can be 0. "0" is not a valid internet
// domain, but may be used as server name in a private network.
$domain = $this->getDomain();
if ($domain === null || $domain === '') {
return 'The cookie domain must not be empty';
}
return true;
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace GuzzleHttp\Exception;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Exception when an HTTP error occurs (4xx or 5xx error)
*/
class BadResponseException extends RequestException
{
public function __construct(
string $message,
RequestInterface $request,
ResponseInterface $response,
?\Throwable $previous = null,
array $handlerContext = []
) {
parent::__construct($message, $request, $response, $previous, $handlerContext);
}
/**
* Current exception and the ones that extend it will always have a response.
*/
public function hasResponse(): bool
{
return true;
}
/**
* This function narrows the return type from the parent class and does not allow it to be nullable.
*/
public function getResponse(): ResponseInterface
{
/** @var ResponseInterface */
return parent::getResponse();
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace GuzzleHttp\Exception;
/**
* Exception when a client error is encountered (4xx codes)
*/
class ClientException extends BadResponseException
{
}

View File

@ -0,0 +1,56 @@
<?php
namespace GuzzleHttp\Exception;
use Psr\Http\Client\NetworkExceptionInterface;
use Psr\Http\Message\RequestInterface;
/**
* Exception thrown when a connection cannot be established.
*
* Note that no response is present for a ConnectException
*/
class ConnectException extends TransferException implements NetworkExceptionInterface
{
/**
* @var RequestInterface
*/
private $request;
/**
* @var array
*/
private $handlerContext;
public function __construct(
string $message,
RequestInterface $request,
?\Throwable $previous = null,
array $handlerContext = []
) {
parent::__construct($message, 0, $previous);
$this->request = $request;
$this->handlerContext = $handlerContext;
}
/**
* Get the request that caused the exception
*/
public function getRequest(): RequestInterface
{
return $this->request;
}
/**
* Get contextual information about the error from the underlying handler.
*
* The contents of this array will vary depending on which handler you are
* using. It may also be just an empty array. Relying on this data will
* couple you to a specific handler, but can give more debug information
* when needed.
*/
public function getHandlerContext(): array
{
return $this->handlerContext;
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace GuzzleHttp\Exception;
use Psr\Http\Client\ClientExceptionInterface;
interface GuzzleException extends ClientExceptionInterface
{
}

View File

@ -0,0 +1,7 @@
<?php
namespace GuzzleHttp\Exception;
final class InvalidArgumentException extends \InvalidArgumentException implements GuzzleException
{
}

Some files were not shown because too many files have changed in this diff Show More