Commit 9920c316 authored by cuiweifeng's avatar cuiweifeng

update : composer update

parent 440ba706

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

composer.lock
/vendor/
.idea
.DS_Store
.project
\ No newline at end of file
生活圈通用业务
负责人:崔伟峰
\ No newline at end of file
{
"name": "api/php_services",
"description": "bp api php_services",
"type": "library",
"require": {
"php": "7.2.*",
"api/php_utils":"dev-master",
"perftools/php-profiler": "^0.18.0",
"endroid/qr-code": "^3.9"
},
"autoload": {
"psr-4": {
"Api\\PhpServices\\": "src/"
}
},
"repositories": {
"api/php_utils":{
"type":"vcs",
"url":"https://gitlab.yidian-inc.com/bp/php_utils.git"
}
}
}
<?php
namespace Api\PhpServices\Certification;
class DesEncryptor
{
protected $_key;
protected $_iv;
protected $_blocksize = 8;
protected $_encrypt;
protected $_cipher;
/**
* Creates a symmetric Data Encryption Standard (DES) encryptor object
* with the specified key and initialization vector.
*
* @param $key
* @param $iv
* @param bool $encrypt
*/
public function __construct($key, $iv, $encrypt = true)
{
$this->_key = $key;
$this->_iv = $iv;
$this->_encrypt = $encrypt;
$this->_cipher = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, '');
mcrypt_generic_init($this->_cipher, $this->_key, $this->_iv);
}
public function __destruct()
{
mcrypt_generic_deinit($this->_cipher);
mcrypt_module_close($this->_cipher);
}
/**
* Transforms the specified region of the specified byte array using PCKS7 padding.
* @param $text
* @return string
*/
public function transformFinalBlock($text)
{
if ($this->_encrypt)
{
$padding = $this->_blocksize - strlen($text) % $this->_blocksize;
$text .= str_repeat(pack('C', $padding), $padding);
}
$text = $this->transformBlock($text);
if (!$this->_encrypt)
{
$aPadding = array_values(unpack('C', substr($text, -1)));
$padding = $aPadding[0];
$text = substr($text, 0, strlen($text) - $padding);
}
return $text;
}
/**
* Transforms the specified region of the specified byte array.
* @param $text
* @return string
*/
public function transformBlock($text)
{
if ($this->_encrypt)
{
return mcrypt_generic($this->_cipher, $text);
}
return mdecrypt_generic($this->_cipher, $text);
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\Certification;
use Api\PhpUtils\Http\Request;
class IdCertification
{
private const key = '_v7QkFPgzb887YD6BuBqzHPJMJalJ6Zt';
private const secret = 'mDenoicZs2U_wd2jVmQQpCOPeM8jaFRu';
private const kuangshi_ocr_url = 'https://api.megvii.com/faceid/v3/ocridcard';
private const kuangshi_get_token = 'https://api.megvii.com/faceid/v3/sdk/get_biz_token';
private const kuangshi_face_compare = 'https://api.megvii.com/faceid/v3/sdk/verify';
/**
* 身份证合法校验
* @param $id_number
* @return bool
*/
public static function checkIdcard (string $id_number) :bool
{
$weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
$codes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
if (strlen($id_number) !== 18) {
return false;
}
$validate = substr($id_number, 0, 17);
$sum = 0;
for ($i = 0; $i < 17; $i++) {
$sum += $validate[$i] * $weight[$i];
}
return $codes[$sum % 11] === $id_number[17];
}
/**
* 获取sign
* @param $api_key
* @param $api_secret
* @param $expired
* @file https://faceid.com/pages/documents/37662604
* @return string
*/
private static function genSign($api_key, $api_secret, $expired) :string
{
$rdm = rand();
$current_time = time();
$expired_time = $current_time + $expired;
$srcStr = "a=%s&b=%d&c=%d&d=%d";
$srcStr = sprintf($srcStr, $api_key, $expired_time, $current_time, $rdm);
return base64_encode(hash_hmac('SHA1', $srcStr, $api_secret, true).$srcStr);
}
/**
* 身份证ocr
* @param $posit_image_url string 身份证人头像图片地址
* @param $back_image_url string 身份证国徽像图片地址
* @file https://faceid.com/pages/documents/10881005
* @return array
*/
public function idCardOcr($posit_image_url,$back_image_url) :array
{
if (!empty($posit_image_url)) {
$result_posit = $this->getIdCardOcr($posit_image_url);
}
if (!empty($back_image_url)) {
$result_back = $this->getIdCardOcr($back_image_url);
}
$final['posit'] = self::analysisPositData($result_posit ?? []);
$final['back'] = self::analysisBackData($result_back ?? []);
return $final;
}
/**
* 单次获取 ocr
* @param $image_url
* @param $return_portrait int 设定是否返回身份证上的人像 “0”:不返回 | “1”:返回人像
* @file https://faceid.com/pages/documents/10881005
* @return array
*/
public function getIdCardOcr($image_url,$return_portrait=1)
{
$get = ['api_key' => self::key,'api_secret'=> self::secret, 'return_portrait' => $return_portrait];
$url = self::kuangshi_ocr_url. '?' . http_build_query($get);
$form_data = [
['name' => 'image' , 'contents' => $this->getFile($image_url)]
];
return (new Request())->post($url, $form_data, 3000, 'multipart',[],1);
}
/**
* 并发请求 身份证ocr
* @param $posit_image_url
* @param $back_image_url
* @return mixed
*/
public function mgetIdCardOcr($posit_image_url,$back_image_url)
{
$posit_image_url = $this->getFile($posit_image_url);
$form_data1 = [
['name' => 'api_key', 'contents' => self::key],
['name' => 'api_secret', 'contents' => self::secret],
['name' => 'image' , 'contents' => fopen($posit_image_url,'r')]
];
$form_data2 = [
['name' => 'api_key', 'contents' => self::key],
['name' => 'api_secret', 'contents' => self::secret],
['name' => 'image' , 'contents' => fopen($back_image_url,'r')]
];
$urls = [
0 => self::kuangshi_ocr_url,
1 => self::kuangshi_ocr_url,
];
$params = [
0 => $form_data1,
1 => $form_data2,
];
$timeouts = [
0 => 5000,
1 => 5000
];
$content_types = [
0 => 'multipart',
1 => 'multipart'
];
$result = (new Request())->concurrencyPost($urls,$params , $timeouts, $content_types);
$final['posit'] = self::analysisPositData($result[0]);
$final['back'] = self::analysisBackData($result[1]);
return $final;
}
/**
* 获取 活体检测token
* @param $id_number string 身份证号
* @param $id_card_name string 姓名
* @param $liveness_type string 检测方式 ("still"(静默) / ”meglive”(动作活体)/ ”flash”(炫彩活体))
* @param $biz_no string 业务号
* @param $expired int 签名生效时长 ,单位秒
* @file https://faceid.com/pages/documents/37661898
* @return string | array
*/
public function getBizToken($id_number,$id_card_name,$liveness_type='meglive',$biz_no='merchat',$expired=10)
{
$form_data = [
['name' => 'sign', 'contents' => self::genSign(self::key,self::secret,$expired)],
['name' => 'sign_version', 'contents' => 'hmac_sha1'],
['name' => 'liveness_type', 'contents' => $liveness_type],
['name' => 'comparison_type', 'contents' => '1'],
['name' => 'idcard_name', 'contents' => $id_card_name],
['name' => 'idcard_number', 'contents' => $id_number],
['name' => 'biz_no', 'contents' => $biz_no],
['name' => 'verbose','contents' => '1'],
['name' => 'get_liveness_video', 'contents' => '1']
];
$result = (new Request())->post(self::kuangshi_get_token, $form_data, 1500, 'multipart');
if (isset($result['code'],$result['response']['biz_token']) && $result['code'] === 0) {
return $result['response']['biz_token'];
}
if(isset($result['http_code']) && $result['http_code'] === 400)
{
if(strpos($result['msg'],'BAD_ARGUMENTS: idcard_name')) {
return ['msg' => '姓名不符合规范'];
}
}
return '';
}
/**
* 人脸比对接口
* @param $biz_token
* @param $meglive_data_url
* @param int $expired
* @file https://faceid.com/pages/documents/37662519
* @return array|mixed
*/
public function verify($biz_token,$meglive_data_url,$expired=10)
{
$form_data = [
['name' => 'sign' , 'contents' => self::genSign(self::key,self::secret,$expired)],
['name' => 'sign_version', 'contents' => 'hmac_sha1'],
['name' => 'biz_token', 'contents' => $biz_token],
['name' => 'meglive_data', 'contents' => $this->getFile($meglive_data_url)]
];
$result = (new Request())->post(self::kuangshi_face_compare, $form_data, 3000, 'multipart',[],1);
if (isset($result['code'], $result['response']) && $result['code'] === 0) {
return $result['response'];
}
return $result['msg']?? '活体检测失败';
}
/**
* 返回文件句柄
* @param $file
* @return bool|false|string
*/
private function getFile($file)
{
if (strpos($file, 'http') === false && !file_exists($file)) {
return false;
}
//获取文件内容
$file_content = fopen($file,'r');
if ($file_content === false) {
return false;
}
return $file_content;
}
/**
* 解析人头像 数据
* @param $ocr_data
* @return array
*/
private static function analysisPositData($ocr_data)
{
$final_data['name'] = $ocr_data['response']['name']['result'] ?? '';
$final_data['gender'] = $ocr_data['response']['gender']['result'] ?? '';
$final_data['address'] = $ocr_data['response']['address']['result'] ?? '';
$final_data['idcard_number'] = $ocr_data['response']['idcard_number']['result'] ?? '';
$final_data['birth_month'] = $ocr_data['response']['birth_month']['result'] ?? '';
$final_data['birth_day'] = $ocr_data['response']['birth_day']['result'] ?? '';
$final_data['nationality'] = $ocr_data['response']['nationality']['result'] ?? '';
$final_data['birth_year'] = $ocr_data['response']['birth_year']['result'] ?? '';
$final_data['completeness'] = $ocr_data['response']['completeness'] ?? -1;
$final_data['legality'] = $ocr_data['response']['legality'] ?? (object)[];
return $final_data;
}
/**
* 解析国徽面数据
* @param $ocr_data
* @return array
*/
private static function analysisBackData($ocr_data)
{
$final_data['valid_date_start'] = $ocr_data['response']['valid_date_start']['result'] ?? '';
$final_data['issued_by'] = $ocr_data['response']['issued_by']['result'] ?? '';
$final_data['valid_date_end'] = $ocr_data['response']['valid_date_end']['result'] ?? '';
$final_data['completeness'] = $ocr_data['response']['completeness'] ?? -1;
$final_data['legality'] = $ocr_data['response']['legality'] ?? (object)[];
return $final_data;
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\Certification;
class PbeWithMd5AndDes
{
/**
* "Magic" keyword used by OpenSSL to put at the beginning of the encrypted
* bytes.
*/
private static $MAGIC_SALTED_BYTES = "Salted__";
private static function _getCharRandonSalt($length = 16): string
{
$salt = '';
for ($n = 0; $n < $length; $n++) {
$salt .= dechex(mt_rand(0, 0xF));
}
return $salt;
}
public static function encrypt($data, $keystring, $salt = null, $iterationsMd5 = 1, $segments = 1)
{
$useRandomSalt = false;
if ($salt === null) {
$salt = self::_getCharRandonSalt();
$useRandomSalt = true;
/**
* Number of iterations -
* needs to be set to 1 for our roundtrip to work.
*/
$iterationsMd5 = 1;
}
$pkcsKeyGenerator = new PkcsKeyGenerator(
$keystring, $salt, $iterationsMd5, $segments);
$encryptor = new DesEncryptor(
$pkcsKeyGenerator->getKey(), $pkcsKeyGenerator->getIv());
$crypt = $encryptor->transformFinalBlock($data);
if ($useRandomSalt) {
// add the magic keyword, salt informazionr and encrypted byte
$crypt = self::$MAGIC_SALTED_BYTES .
pack("H*", $salt) .
$crypt;
}
// base64 encode so we can send it around as a string
return base64_encode($crypt);
}
public static function decrypt($data, $keystring, $salt = null, $iterationsMd5 = 1, $segments = 1)
{
if ($salt === null) {
// get the salt information from the input
$salt = bin2hex(substr(base64_decode($data), 8, 8));
$data = base64_encode(substr(base64_decode($data), 16));
/**
* Number of iterations -
* needs to be set to 1 for our roundtrip to work.
*/
$iterationsMd5 = 1;
}
$pkcsKeyGenerator = new PkcsKeyGenerator(
$keystring, $salt, $iterationsMd5, $segments);
$encryptor = new DesEncryptor(
$pkcsKeyGenerator->getKey(), $pkcsKeyGenerator->getIv(), false);
return $encryptor->transformFinalBlock(base64_decode($data));
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\Certification;
class PkcsKeyGenerator
{
protected $_key;
protected $_iv;
/**
* @return string
*/
public function getKey()
{
return $this->_key;
}
/**
* Gets the initialization vector.
* @return string
*/
public function getIv()
{
return $this->_iv;
}
public function __construct($keystring, $salt, $iterationsMd5, $segments)
{
$salt = pack('H*', $salt);
$keyMaterial = '';
$data = $keystring . $salt;
$result = '';
for ($j = 0; $j < $segments; $j++)
{
if ($j === 0)
{
$result = $data;
}
else
{
$result .= $data;
}
for ($i = 0; $i < $iterationsMd5; $i++)
{
$result = md5($result, true);
}
$keyMaterial .= $result;
}
$this->_key = substr($keyMaterial, 0, 8);
$this->_iv = substr($keyMaterial, 8, 8);
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\Certification;
use Api\PhpUtils\Http\Request;
class SocialCreditCertification
{
private const account = 'BJyimingzhineng';
private const app_key = 'deee9c9877e5452f8838cfc5130ac5ad';
private const ocr_bussiness_url = 'http://apistore.xmturui.com/apistore/ocr-new';
private const engine_type = 'blic-new';
/**
* 校验社会统一信用代码格式是否合法
* @param $social_creadit_code
* @return bool
*/
public static function checkSocialCredit(string $social_creadit_code) :bool
{
$one = '159Y';//第一位可以出现的字符
$two = '12391';//第二位可以出现的字符
$str = strtoupper($social_creadit_code);
if (strpos($one, $str[1]) === false && strpos($two, $str[2]) === false && !empty($array[substr($str, 2, 6)])) {
return false; //有误
}
$wi = array(1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28);//加权因子数值
$str_organization = substr($str, 0, 17);
$num = 0;
for ($i = 0; $i < 17; $i++) {
$num += self::transformation($str_organization[$i]) * $wi[$i];
}
switch ($num % 31) {
case '0':
$result = 0;
break;
default:
$result = 31 - $num % 31;
break;
}
if ($str[strlen($str) - 1] === self::transformation($result, true)) {
return true;
}
return false;
}
private static function transformation($num, $status = false)
{
$list = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'J' => 18, 'K' => 19, 'L' => 20, 'M' => 21, 'N' => 22, 'P' => 23, 'Q' => 24, 'R' => 25, 'T' => 26, 'U' => 27, 'W' => 28, 'X' => 29, 'Y' => 30);//值转换
if ($status === true) {
$list = array_flip($list);
}
return $list[$num];
}
/**
* 营业执照ocr 识别
* @param $business_image string image_url
* @return array
*/
public function businessLicenseOcr($business_image)
{
$base64_image = self::imgBase64Encode($business_image);
if ($base64_image === false) {
return ['code'=>-1];
}
$post_data = [
'account' => self::account,
'key' => self::app_key,
'enginetype' => self::engine_type,
'databaseImageContent' => $base64_image
];
$result = (new Request())->post(self::ocr_bussiness_url, $post_data, 5000, 'json',[],0);
if (isset($result['code'],$result['response']) && $result['code'] === 0 ) {
return $result['response'];
}
return ['code'=>-1];
}
/**
* base64_encode_image
* @param string $img
* @return bool|string
*/
public static function imgBase64Encode($img = '')
{
if (strpos($img, 'http') === false && !file_exists($img)) {
return false;
}
//获取文件内容
$file_content = file_get_contents($img);
if ($file_content === false) {
return false;
}
return chunk_split(base64_encode($file_content));
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\Certification;
use Api\PhpUtils\Http\Request;
class ThreeElementsCertification
{
private const app_key = '392df35aa98721c597cf20b85d21eebc';
//运营商三要素检测接口
private const test_mobile3_ele_Sim_url = 'https://api.goodsdatas.com:8443/credit/Mobile3EleSim';
//加密需要的相关参数
private const salt = 'A99BC8325635E303';
private const iterations = 2;
private const segments = 1;
/**
* 运营商三要素检测
* @param $mobile_num
* @param $id_num
* @param $name
* @return array
*/
public function mobile3EleSimCheck($mobile_num,$id_num,$name)
{
$encry_data = sprintf('idCard=%s&name=%s&mobile=%s',$id_num,$name,$mobile_num);
$crypt = PbeWithMd5AndDes::encrypt(
$encry_data, self::app_key,
self::salt, self::iterations, self::segments
);
$query = [
'rettype' => 'json',
'encryptParam' => $crypt
];
$result = (new Request())->get(self::test_mobile3_ele_Sim_url.'/'.self::app_key,$query,4000,[],1);
if (isset($result['code']) && $result['code'] === 0) {
return $result['response'];
}
return ['code'=>-1];
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\Daemon;
use Api\PhpUtils\Cache\ApcuUtil;
use Api\PhpUtils\Log\DaemonLog;
use Api\PhpUtils\Message\Email;
use Yaf\Application;
class Daemon
{
/**
* 任务名
* @var string
*/
protected $task_name;
protected $task_class;
const MAX_WORKER_PROCESS_NUMBER = 16;
const MAX_WORKER_EXECUTE_TIMES = 1000;
protected $process_list = false;
protected $max_process_num = 0;
protected $current_process_num = 0;
protected $matser_process_id = false;
protected $output = false;
protected $terminate = false;
protected $log_signature = "daemon";
protected $env = "dev";
protected $exception_time_cycle = 120; // 脚本异常记录时间周期
protected $exception_save_time = 10; // 异常时间周期内,记录前 n 条到错误日志
protected $exception_alert_time = 100; // 异常时间周期内,超过 n 次异常则邮件报警
public function __construct(string $task_name, $task_class, int $worker_num = 1, array $params =[])
{
$this->checkEnv();
if( $worker_num > self::MAX_WORKER_PROCESS_NUMBER )
{
die("worker进程最大限制为".self::MAX_WORKER_PROCESS_NUMBER."\n");
}
if( !class_exists($task_class) ){
die("任务不存在"."\n");
}
$this->task_name = $task_name;
$this->params = $params;
$this->task_class = $task_class;
$this->max_process_num = $worker_num;
$this->env = Application::app()->environ() ?? "dev";
$this->set_base_config();
if(function_exists('gc_enable')) gc_enable();
}
public static function run(){
throw new \Exception("bbb");
}
/**
* 启动守护进程,并在master进行中监听子进程状态,当子进程退出后重新启动新的子进程( 保持worker进程数为max_process_num )
* 若要结束守护进程可向主进程发送kill -SIGUSR1的信号,子进程完成当前工作后会逐个退出
*/
public function start(){
DaemonLog::info($this->log_signature,'process start now');
$this->daemon();
for($i=0; $i<$this->max_process_num; $i++) {
$this->worker();
}
while(1)
{
//注册信号处理,master进程中捕获SIGUSR1后通知worker进程退出
if( !pcntl_signal(SIGUSR1, array(__CLASS__, "signal_handler"),false) ) {
DaemonLog::error($this->log_signature,'master pcntl SIGUSR1 failed');
}
pcntl_signal_dispatch();
$pid = pcntl_wait($status, WUNTRACED); //阻塞取得子进程结束状态
if( ($key = array_search($pid, $this->process_list)) !==false )
{
$this->current_process_num--;
unset($this->process_list[$key]);
$this->process_list = array_values($this->process_list);
// DaemonLog::info($this->log_signature,"worker process: {".$pid."} exited with {$status}");
if( $this->terminate == false )
{
if( $this->current_process_num < $this->max_process_num )
{
$this->worker();
}
}else
{
if( $this->current_process_num == 0 )
{
break;
}
}
}
}
DaemonLog::info($this->log_signature,"shut down success");
exit(0);
}
protected function daemon()
{
set_time_limit(0);
$pid = pcntl_fork();
if($pid == -1)
{
die('Could not fork 1');
}
if ($pid != 0){ //父进程
exit(0);
}
posix_setsid(); //设置新会话组长,脱离终端
$pid = pcntl_fork();
if($pid == -1)
{
die('Could not fork 2');
}
if ($pid != 0) //第一子进程
{
DaemonLog::info($this->log_signature,'master process pid:'.$pid);
exit(0);
}
chdir(ROOT_PATH);
umask(0);
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
$this->matser_process_id = posix_getgid();
// mac 系统不支持此函数,调试时关闭
cli_set_process_title($this->task_name.' '.$this->env.' master process');
}
/**
* 启动worker进程
* @Author wangdanfeng
* @return void
*/
protected function worker()
{
$pid = pcntl_fork();
if( $pid == -1 ) {
DaemonLog::error($this->log_signature,'worker Process fork failed');
}elseif ($pid == 0) {
//子进程
cli_set_process_title($this->task_name . ' ' . $this->env . ' worker process');
DaemonLog::info($this->log_signature,"worker Process {".posix_getpid()."} was created".' master process id:'.posix_getppid());
//注册子进程信号
if( !pcntl_signal(SIGUSR2, array(__CLASS__, "signal_handler"),false) )
{
DaemonLog::error( $this->log_signature ,"worker Process {".posix_getpid()."} pcntl SIGUSR2 failed".' master process id:'.posix_getppid() );
}
// 执行指定次数后自动退出
for ($i=0; $i <self::MAX_WORKER_EXECUTE_TIMES ; $i++)
{
pcntl_signal_dispatch();
try {
$task = new $this->task_class(...$this->params);
$task->run();
}catch (\Exception $e){
// 默认2分钟内最多记录10条异常日志,超过100次则报警
$exception_num = ApcuUtil::apcu_inc($this->log_signature, posix_getppid(),1,$success, $this->exception_time_cycle);
if($success && $exception_num){
if($exception_num < $this->exception_save_time+1){
DaemonLog::error( $this->log_signature ,"worker Process {".posix_getpid()."} throw exception! msg: ".$e->getMessage().' master process id:'.posix_getppid() );
}elseif ($exception_num == $this->exception_alert_time){
$subject= "Daemon 任务异常";
$mail_body = '任务在'.$this->exception_time_cycle.'秒内异常次数达到'.$this->exception_alert_time.'次,请及时处理。'."\r\n" .
'time: ' . date('Y-m-d H:i:s') . "\r\n" .
'task_name: ' . $this->task_name . "\r\n" .
'task_class: ' . $this->task_class . "\r\n" .
'host name: ' . gethostname() . "\r\n";
// $to = 'api@yidian-inc.com';
$to = 'zhangyu1@yidian-inc.com';
Email::sendMail('noreply@yidian-inc.com', $to, $subject, $mail_body);
}
}
}
if($this->terminate==true)
{
exit(0);
}
}
exit(0);
}else
{
$this->process_list[] = $pid;
$this->current_process_num++;
return;
}
}
protected function quit()
{
DaemonLog::info( $this->log_signature ,"process shut down" );
$this->terminate = true;
foreach ($this->process_list as $pid)
{
if( !posix_kill($pid, SIGUSR2) ) {
DaemonLog::error( $this->log_signature ,'master process send SIGUSR2 to '.$pid.' failed' );
}
}
}
/**
* 目前仅支持退出所有进程,后续待完善
* @Author wangdanfeng
* @param [type] $signal [description]
* @return [type] [description]
*/
protected function signal_handler($signal)
{
switch ($signal)
{
case SIGUSR1: //父进程监听信号
$this->quit();
break;
case SIGUSR2: //子进程监听信号
$this->terminate = true;
break;
default:
# code...
break;
}
}
/**
* 运行环境检查
* @Author wangdanfeng
* @return void
*/
protected function checkEnv()
{
php_sapi_name() == "cli" or die("只允许在cli下面运行"."\n");
PHP_VERSION_ID >= 50330 or die("php版本需大于5.3.3"."\n");
function_exists('pcntl_signal') or die("请安装pcntl扩展"."\n");
function_exists('posix_getpid') or die("请安装posix扩展"."\n");
}
/**
* 基本配置
*/
protected function set_base_config(){
ini_set("display_errors", 1);
error_reporting('E_ALL');
ini_set('date.timezone','Asia/Shanghai');
ini_set("memory_limit", '2048M');
error_reporting(E_ALL);
//创建任务日志文件
$log_dir = ROOT_PATH.'/logs/daemon/'.$this->task_name;
$log_path = $log_dir.'/'.$this->task_name.'.log';
ini_set('error_log',$log_path );
if( !file_exists($log_path) )
{
mkdir($log_dir, 0777, true);
if( !touch( $log_path ) )
{
die($log_path."文件无法创建"."\n");
}
}
$this->log_signature = "daemon:".$this->task_name;
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\Daemon;
interface DaemonServiceInterface
{
public function run();
}
\ No newline at end of file
This diff is collapsed.
<?php
namespace Api\PhpServices\Idgen;
use Api\PhpUtils\Http\Request;
class Idgen
{
public static function get($partner, $key, $id_snow=[], $id_datetime=[]){
$url = config('interface','service.idgen');
$params = [];
$params['partner'] = $partner;
$params['key'] = $key;
if(!empty($id_snow)){
$params['id_snow'] = $id_snow;
}
if(!empty($id_datetime)){
$params['id_datetime'] = $id_datetime;
}
$res = (new Request())->post($url, $params,5000, 'json');
if(isset($res['code']) && $res['code']==0 && isset($res['response']['result'])){
return $res['response']['result'] ?? [];
}
return [];
}
}
\ No newline at end of file
This diff is collapsed.
<?php
/**
* Description of JwUser.php
*
* @author haiming
* Date: 2021/5/21
* Time: 10:32 PM
*/
namespace Api\PhpServices\JwUser;
use Api\PhpUtils\Common\TimeOut;
use Api\PhpUtils\Http\Request;
use App\Exception\custom\CodeSpecialException;
class JwUser
{
/**
* 获取简网用户信息
*
*@param $params['mobile'] 手机号
*
*/
public function getUserInfo($params)
{
$url = config('interface', 'service.jw_user.get_user_info');
if (!$url) {
throw new CodeSpecialException("failed");
}
if (empty($params['mobile'])) {
throw new CodeSpecialException("failed");
}
$params = ["mobilePhone" => $params['mobile']];
$user_info = (new TimeOut())->runGet($url, $params);
if (!$user_info) {
throw new CodeSpecialException("timeout");
}
return $user_info;
}
/**
* 获取单条信息
*
*/
public function getUserByUserId($params)
{
$url = config('interface', 'service.jw_user.get_user_info_by_user_id');
if (!$url) {
throw new CodeSpecialException("failed");
}
if (empty($params['user_id'])) {
throw new CodeSpecialException("failed");
}
$params = ["userId" => $params['user_id']];
$user_info = (new TimeOut())->runPost($url, $params);
if (!$user_info) {
throw new CodeSpecialException("timeout");
}
return $user_info;
}
public function getUserList($params)
{
$url = config('interface', 'service.jw_user.get_user_list');
if (!$url) {
throw new CodeSpecialException("failed");
}
if (empty($params['user_id'])) {
throw new CodeSpecialException("failed");
}
$params = ["userIds" => $params['user_id']];
$user_info = (new TimeOut())->runPost($url, $params);
if (!$user_info) {
throw new CodeSpecialException("timeout");
}
return $user_info;
}
/**
* 获取城市树接口
*
*
*/
public function getAllCityTree()
{
$url = config('interface', 'service.jw_user.get_all_city_tree');
if (!$url) {
throw new CodeSpecialException("failed");
}
$params = [];
$city_list = (new TimeOut())->runGet($url, $params);
if (!$city_list) {
throw new CodeSpecialException("timeout");
}
return $city_list;
}
/**
* 保存用户与token的对应关系接口
* 支持的token prefix:MMPP 小米推送,UMPP 友盟推送,GTPP 个推
*
*/
public function savePushToken($params)
{
$url = config('interface', 'service.jw_user.save_push_token');
if (!$url) {
throw new CodeSpecialException("failed");
}
if (empty($params)) {
throw new CodeSpecialException("failed");
}
$pushToken = (new TimeOut())->runPost($url, $params);
if (!$pushToken) {
throw new CodeSpecialException("timeout");
}
return $pushToken;
}
/**
* 获取简网用户动态
*/
public static function getUserListWithDynamic($params)
{
$url = config('interface', 'service.jw_user.get_user_dynamic');
if (!$url) {
throw new CodeSpecialException("failed");
}
if (empty($params['user_id'])) {
throw new CodeSpecialException("failed");
}
$params = ["userIds" => $params['user_id']];
$list = (new TimeOut())->runPost($url, $params);
if (!$list) {
throw new CodeSpecialException("timeout");
}
return $list;
}
/**
* 获取简网用户历史赞
*/
public static function getUserDigg($params)
{
$url = config('interface', 'service.jw_user.get_user_digg');
if (!$url) {
throw new CodeSpecialException("failed");
}
if (empty($params['user_id'])) {
throw new CodeSpecialException("failed");
}
$params = ["userId" => $params['user_id']];
$list = (new TimeOut())->runPost($url, $params);
if (!$list) {
throw new CodeSpecialException("timeout");
}
return $list;
}
/**
* 给简网同步生活号
*/
public static function saveUpdateLife($params)
{
$url = config('interface', 'service.jw_user.save_update_life');
if (!$url) {
throw new CodeSpecialException("failed");
}
$ret = (new TimeOut())->runPost($url, $params);
if (!$ret) {
throw new CodeSpecialException("timeout");
}
return $ret;
}
}
use Api\PhpServices\JwUser\JwUser;
//获取简网用户信息
$jwUser = new JwUser();
$params = [
'mobile' => 13800000000
];
$user_info = $jwUser->getUserInfo($params);
//单个获取
$params = [
'user_id' => 100000000
];
$user_info = $jwUser->getUserByUserId($params);
//批量获取
$params = [
'user_id' => 100000,20000,30000
];
$user_info = $jwUser->getUserList($params);
<?php
namespace Api\PhpServices\Ksy;
use Api\PhpUtils\Http\Request;
class Ksyun
{
private const jinshan_ak = 'AKLTnATdoXUnR72IDSGgN2WSOQ'; //AccessKey
private const jinshan_sk = 'OMw7UAOkrLVsRevuP44ctAlfzriDzUm9+JvOFoYuiSoLgaLJWi+kjUa+4G3EWXFakQ=='; //SecretKey
private const bp_bucket = 'bp-yidian';
private const bp_image_yidian = 'bp-image_yidian';
private const get_down_from_ksyun = 'http://video-stream-service.int.yidian-inc.com/auth/url-get';
private const get_down_from_pic_service = 'https://ibp.go2yd.com/imagebp.php'; //来自图片服务
/**
* 支持批量
* 根据 object_id 从金山云 获取下载地址
* @param $object_ids array ["90.mp4", "17.mp4"]
* @param $appid string 区分不同业务方
* @param $bucket string
* @param $expire_time
* @return array
*/
public static function getDownUrl(array $object_ids,$appid,$bucket,$expire_time=60)
{
$post_data = [
'keys' => $object_ids,
'from' => $appid,
'bucket' => $bucket,
'expire' => $expire_time,
];
$res = (new Request())->post(self::get_down_from_ksyun, $post_data,50, 'json',[],1,true);
if (isset($res['code'],$res['response']['status']) && $res['response']['status'] === 'success') {
return $res['response']['data'];
}
return [];
}
/**
*
* @param $url
* @param $appid
* @param int $expire_time
* @return mixed|string
*/
public static function getUrlFromKsyn($url,$appid,$expire_time=60)
{
$del_str = explode('/',$url);
$bucket = $del_str[0] ?? '';
$objectid = $del_str[1] ?? '';
$image_url = Ksyun::getDownUrl([$objectid],$appid,$bucket,$expire_time);
if (empty($image_url) || (!isset($image_url[$objectid]) )
) {
return '';
}
return $image_url[$objectid];
}
/**
* 返回 金山云token
* @param $http_method
* @param $date
* @param $resource
* @param string $headers
* @param string $content_md5
* @param string $content_type
* @file https://docs.ksyun.com/documents/6890
* @return string
*/
public function getToken($http_method,$date,$resource,$headers='',$content_md5='',$content_type='') :string
{
if (!empty($headers))
{
$headers .= "\n";
}
$StringToSign = $http_method . "\n"
. $content_md5 . "\n"
. $content_type . "\n"
. $date . "\n"
. $headers
. $resource;
$signature = base64_encode(hash_hmac('sha1', $StringToSign, self::jinshan_sk, true));
$signature = 'KSS ' . self::jinshan_ak . ':' . $signature;
return $signature;
}
/**
* @param string $appid 应用
* @param $scenario
* @param $http_method
* @param $date
* @param $resource
* @param string $headers
* @param string $content_md5
* @param string $content_type
* @return string
*/
public function getTokenV2($appid,$scenario,$http_method,$date,$resource,$headers='',$content_md5='',$content_type='') : string
{
return $this->getToken($http_method,$date,$resource,$headers,$content_md5,$content_type);
}
/**
* 返回bucket
* @param $appid
* @param $scenario string 区分业务场景
* @return string
*/
public static function getBucket($appid,$scenario) :string
{
if ($appid === 'merchant-b' || $appid === 'merchant-c') {
if ($scenario === 'goods') {
return self::bp_image_yidian;
}
return self::bp_bucket;
}
return '';
}
/**
* 生成objectid 和 bucket
* @param $appid
* @param $scenario string 区分业务场景
* @return array
*/
public static function getObjectAndBucket($appid,$scenario):array
{
return ['bucket' => self::getBucket($appid,$scenario),'objectId' => md5(uniqid(mt_rand(), true))];
}
/**
* 获取可支持裁剪的图片url
* @param $bucket
* @param $objectid
* @param $wideSize
* @param $highSize
* @param string $type 目前只支持 png webp jpeg
* @wiki http://ydwiki.yidian-inc.com/pages/viewpage.action?pageId=41584585
* @return string
*/
public static function getCutPicUtl($bucket,$objectid,$wideSize,$highSize,$type='jepg')
{
if ($bucket !== self::bp_image_yidian || !in_array($type,['png','webp','jpeg'])) {
//目前只有当bucket == bp-image_yidian 才支持可裁剪
return '';
}
return sprintf(self::get_down_from_pic_service.'?'.'url=%s&%s_%sx%s',$objectid,$type,$wideSize,$highSize);
}
}
\ No newline at end of file
<?php
/**
* Description of
*
* @author zhiyuan
* Date: 2021/6/12
* Time: 10:32 PM
*/
namespace Api\PhpServices\LifeAccount;
use Api\PhpUtils\Common\TimeOut;
use Api\PhpUtils\Http\Request;
use App\Exception\custom\CodeSpecialException;
class Account
{
/**
* 批量获取生活号角色表数据
*
*@param $params['role_id'] 主键id
*
*/
public static function getRoleList($params)
{
$url = config('interface', 'merchant.account.get_role_list');
if (!$url) {
throw new CodeSpecialException("failed");
}
if (!array_key_exists('role_id', $params) || !array_key_exists('page', $params) || !array_key_exists('page_size', $params)) {
throw new CodeSpecialException("failed");
}
$list = (new TimeOut())->runGet($url, $params);
if (!$list) {
throw new CodeSpecialException("timeout");
}
return $list;
}
/**
* 批量获取生活号表数据
*
*@param $params['user_id'] 主键id
*
*/
public static function getLifeList($params)
{
$url = config('interface', 'merchant.account.get_life_list');
if (!$url) {
throw new CodeSpecialException("failed");
}
$list = (new TimeOut())->runGet($url, $params);
if (!$list) {
throw new CodeSpecialException("timeout");
}
return $list;
}
/**
* 批量获取用户表数据
*
*@param $params['user_id'] 主键id
*
*/
public static function getUserList($params)
{
$url = config('interface', 'merchant.account.get_user_list');
if (!$url) {
throw new CodeSpecialException("failed");
}
$list = (new TimeOut())->runGet($url, $params);
if (!$list) {
throw new CodeSpecialException("timeout");
}
return $list;
}
}
<?php
namespace Api\PhpServices\Login;
use Api\PhpUtils\Common\TimeOut;
use Api\PhpUtils\Http\Request;
use App\Exception\custom\CodeSpecialException;
class Login
{
/**
* 访客内网登录
*
* @doc http://ydwiki.yidian-inc.com/pages/viewpage.action?pageId=59676495
* @param array $user
* @param string $partner 调用方(包括一点资讯yidian,VPN项目hubble,地铁metro)
* @return array
*/
public static function guest(array $user, string $key, string $partner){
$url = config("interface","service.login.guest");
if(!$url){
throw new CodeSpecialException("failed");
}
$user["partner"] = $partner;
$user["key"] = $key;
$res = (new TimeOut())->runGet($url, $user);
if(!$res){
throw new CodeSpecialException("timeout");
}
if(!isset($res["code"])){
throw new CodeSpecialException("user_login");
}
if($res["code"] == 0){
unset($res["code"]);
unset($res["status"]);
return $res;
}
switch ($res["code"]/1){
case 10:
throw new CodeSpecialException("param");
case 14:
throw new CodeSpecialException("permission_denied");
case 15:
throw new CodeSpecialException("sign");
case 21:
throw new CodeSpecialException("mysql");
default:
throw new CodeSpecialException("user_login");
}
}
/**
* 手机号内网登录
*
* @doc http://ydwiki.yidian-inc.com/pages/viewpage.action?pageId=57606923
*/
public static function mobile(array $user, string $key, string $partner){
$url = config("interface","service.login.mobile");
if(!$url){
throw new CodeSpecialException("failed");
}
$user["partner"] = $partner;
$user["key"] = $key;
$res = (new TimeOut())->runGet($url, $user);
if(!$res){
throw new CodeSpecialException("timeout");
}
if(!isset($res["code"])){
throw new CodeSpecialException("user_login");
}
if($res["code"] == 0){
unset($res["code"]);
unset($res["status"]);
return $res;
}
switch ($res["code"]/1){
case 10:
throw new CodeSpecialException("param");
case 14:
throw new CodeSpecialException("permission_denied");
case 21:
throw new CodeSpecialException("user_mobile_error");
case 32:
throw new CodeSpecialException("user_mobile_registed");
default:
throw new CodeSpecialException("user_login");
}
}
/**
* 发送短信验证码服务
* http://ydwiki.yidian-inc.com/pages/viewpage.action?pageId=58693127
* @param array $data
* @param string $template 模板
* @param string $partner 调用方(包括一点资讯yidian,VPN项目hubble,地铁metro等)
* @param int $code_lenght 验证码长度,默认4位
* @param int $code_expire 验证码有效期,默认300秒(5分钟)
* @param int $resend_times 验证周期内验证码最大发送次数,默认10次
* @param int $retry_times 验证周期内每个验证码最大可校验次数,默认10次
* @param int $ticket_expire 验证码验证周期,默认86400秒(1天)
* @throws CodeSpecialException
* @return true
*/
public static function sendSmsCode(array $data, int $template, string $key, string $partner, $code_lenght =4, $code_expire=300, $resend_times=10, $retry_times=10, $ticket_expire=86400){
$url = config("interface","service.login.send_sms_code");
if(!$url){
throw new CodeSpecialException("failed");
}
$data = array_merge($data,[
"key" => $key,
"partner" => $partner,
"template" => $template,
"code_lenght" => $code_lenght,
"ticket_expire" => $ticket_expire,
"code_expire" => $code_expire,
"resend_times" => $resend_times,
"retry_times" => $retry_times,
]);
$res = (new Request())->get($url, $data, 60000);
if(!$res){
throw new CodeSpecialException("timeout");
}
if(!isset($res["code"])){
throw new CodeSpecialException("failed");
}
if($res["code"] == 0){
return true;
}
switch ($res["code"]/1){
case 10:
throw new CodeSpecialException("param");
case 14:
throw new CodeSpecialException("permission_denied");
case 221:
throw new CodeSpecialException("captcha_sent");
case 30:
throw new CodeSpecialException("mobile_error");
case 23:
throw new CodeSpecialException("memcache");
case 224:
throw new CodeSpecialException("captcha_delay_retry");
default:
throw new CodeSpecialException("failed");
}
}
/**
* 校验短信验证码
* @param array $data
* @param string $partner
* @return true
* @throws CodeSpecialException
*/
public static function checkSmsCode(array $data, string $key, string $partner){
$url = config("interface","service.login.check_sms_code");
if(!$url){
throw new CodeSpecialException("failed");
}
$data = array_merge($data,[
"partner" => $partner,
"key" => $key,
]);
$res = (new TimeOut())->runGet($url, $data);
if(!$res){
throw new CodeSpecialException("timeout");
}
if(!isset($res["code"])){
throw new CodeSpecialException("failed");
}
if($res["code"] == 0){
return true;
}
switch ($res["code"]/1){
case 10:
throw new CodeSpecialException("param");
case 14:
throw new CodeSpecialException("permission_denied");
case 220:
$reasion = $res["reason"] ?? "";
throw new CodeSpecialException("captcha", $reasion);
case 222:
throw new CodeSpecialException("captcha_timeout");
case 223:
throw new CodeSpecialException("captcha_forbidden");
default:
throw new CodeSpecialException("failed");
}
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\PushToken;
use Api\PhpUtils\Http\Request;
class Android extends Base
{
/**
* @param bool $err 引用类型,是否存在错误
* @param $appid
* @param $userid
* @param $data
*/
public static function save(&$err = false, $appid, $data, $userid=''){
$new_token = $data['new_token'] ?? "";
$old_token = $data['old_token'] ?? "";
$token = $data['new_token'] ?? $data['old_token'] ?? "";
$version = self::version($data['version'] ?? "");
$personal_rec = $data['personalRec'] ?? 1;
$enable = self::enable($data['enable'] ?? 1, $personal_rec);
$push_key = $data['push_key'] ?? "";
$device_id = $data["device_id"] ?? "";
if($device_id && !self::valid_device_id($device_id)){
$device_id = "";
}
$android_id = $data["androidId"] ?? "";
if($android_id && !self::valid_device_id($android_id)){
$android_id = "";
}
if (!self::valid_appid($appid)){
return ["code"=> self::ERROR_CODE_PARAM, "msg" => "appid有误"];
}
if( empty($token) || !self::valid_android_token($token) ){
$err = true;
return ["code"=> self::ERROR_CODE_PARAM, "msg" => "token有误"];
}
if( !$version ){
$err = true;
return ["code"=> self::ERROR_CODE_PARAM, "msg" => "version有误"];
}
if($new_token && substr($new_token, 0, 4) === 'OPPO' && (empty($push_key)) ){
$err = true;
return ["code"=> self::ERROR_CODE_PARAM, "msg" => "该类型token的push_key必传"];
}
// $action = explode('?', $_SERVER['REQUEST_URI'])[0]; // 与运营中台沟通,暂时写死成 website 路径,之后重构再调整
$action = "/Website/push/BindingTokenForAndroidAction.php";
$send = [
'action' => $action,
'appid' => $appid,
'request_time' => intval($_SERVER['REQUEST_TIME']),
'version' => $version,
'userid' => $userid,
'time_zone' => $data["time_zone"] ?? "",
'personal_rec' => $personal_rec,
'enable' => $enable,
'sound' => $data["sound"] ?? "",
'push_level' => self::set_device_type_from_brand($data["push_level"] ?? "1048576", $data["brand"] ??""),
'old_token' => $old_token,
'new_token' => $new_token,
'push_key' => $push_key,
'cv' => $data["cv"] ?? "",
'device_id' => $device_id,
'android_id' => $android_id,
'os' => $data["os"] ?? "",
'distribution' => $data["distribution"] ?? "",
'platform' => "Android"
];
$send = array_filter ($send,function($v){if($v===''){return false;}else{return true;}});
if(!self::sendKafka($send)){
$err = true;
return ["code"=> self::ERROR_CODE_KAFKA, "msg" => "send failed"];
};
$err = false;
return true;
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\PushToken;
use Api\PhpUtils\Http\Request;
class Base
{
const ERROR_CODE_PARAM = 1;
const ERROR_CODE_KAFKA = 2;
// appid 最大长度
const MAX_APPID_LENGTH = 20;
// android token 的最大长度
const MAX_ANDROID_TOKEN_LENGTH = 40;
// ios token 的最大长度
const MAX_IOS_TOKEN_LENGTH = 80;
// 特殊的appid(普通appid只包含数字字母)
static $SPECIAL_APPIDS = array('web_mixapp' => '');
// android token 合法前缀
static $ANDROID_VALID_TOKEN_PREFIX = array('MMPP', 'UMPP', 'GTPP', 'JGPP', 'OPPP', 'HMSP', 'FCMP', 'OPPO', 'VIVO');
const DEVICE_MASK = 0xF0;
const DEVICE_NONE = 0x00;
const DEVICE_XIAOMI = 0x10;
const DEVICE_HUAWEI = 0x20;
const DEVICE_MEIZU = 0x30;
const DEVICE_UNKNOWN = 0x40;
const DEVICE_NUBIA = 0x50;
const DEVICE_ZTE = 0x60;
const DEVICE_OPPO = 0x70;
const DEVICE_VIVO = 0x80;
const DEVICE_SAMSUNG = 0x90;
const DEVICE_ID_LENGTH = 80;
/**
* 校验appid
* @param $appid
* @return bool
*/
protected static function valid_appid($appid){
return strlen($appid) <= self::MAX_APPID_LENGTH
&& ctype_alnum($appid)
|| isset(self::$SPECIAL_APPIDS[$appid]);
}
/**
* 校验安卓token
* @param $token
* @return bool
*/
protected static function valid_android_token($token)
{
return strlen($token) <= self::MAX_ANDROID_TOKEN_LENGTH
&& in_array(substr($token, 0, 4), self::$ANDROID_VALID_TOKEN_PREFIX)
&& ctype_alnum(substr($token, 4));
}
protected static function valid_ios_token($token)
{
return strlen($token) <= self::MAX_IOS_TOKEN_LENGTH && ctype_alnum($token);
}
protected static function valid_device_id($device_id)
{
return strlen($device_id) < self::DEVICE_ID_LENGTH && ctype_alnum($device_id);
}
protected static function version($version = '', $default = '000000')
{
if ($version)
{
if (preg_match('/\d{6}/', trim($version)))
{
return trim($version);
}
return false;
}
return $default;
}
protected static function enable($enable, $personal_rec){
return $enable == 0 ? '0' : (!$personal_rec ? '3' : '1');
}
protected static function set_device_type_from_brand($push_level, $brand)
{
if(!$brand){
return $push_level;
}
switch ($brand)
{
case 'Xiaomi':
case 'xiaomi':
case 'Redmi':
$push_level =
strval(($push_level & (~self::DEVICE_MASK)) | self::DEVICE_XIAOMI);
break;
case 'HUAWEI':
case 'HONOR':
case 'Huawei':
case 'Honor':
case 'honor':
$push_level =
strval(($push_level & (~self::DEVICE_MASK)) | self::DEVICE_HUAWEI);
break;
case 'Meizu':
$push_level =
strval(($push_level & (~self::DEVICE_MASK)) | self::DEVICE_MEIZU);
break;
case 'nubia':
$push_level =
strval(($push_level & (~self::DEVICE_MASK)) | self::DEVICE_NUBIA);
break;
case 'ZTE':
$push_level =
strval(($push_level & (~self::DEVICE_MASK)) | self::DEVICE_ZTE);
break;
case 'OPPO':
case 'oppo':
case 'realme':
case 'Realme':
$push_level =
strval(($push_level & (~self::DEVICE_MASK)) | self::DEVICE_OPPO);
break;
case 'vivo':
$push_level =
strval(($push_level & (~self::DEVICE_MASK)) | self::DEVICE_VIVO);
break;
case 'samsung':
case 'SAMSUNG':
$push_level =
strval(($push_level & (~self::DEVICE_MASK)) | self::DEVICE_SAMSUNG);
break;
default:
$push_level =
strval(($push_level & (~self::DEVICE_MASK)) | self::DEVICE_UNKNOWN);
break;
}
return $push_level;
}
protected static function sendKafka($data){
// echo json_encode($data);exit();
$url = config("interface","service.push_token") . '?' . config("interface","service.push_token_topic");
$res = (new Request())->post($url, $data, 200000, 'json');
if($res['code']==0){
return true;
}
return false;
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\PushToken;
use Api\PhpUtils\Http\Request;
class Ios extends Base
{
/**
* @param bool $err 引用类型,是否存在错误
* @param $appid
* @param $userid
* @param $data
*/
public static function save(&$err = false, $appid, $data, $userid=''){
$new_token = $data['new_token'] ?? "";
$old_token = $data['old_token'] ?? "";
$token = $data['new_token'] ?? $data['old_token'] ?? "";
$version = self::version($data['version'] ?? "");
$personal_rec = $data['personalRec'] ?? 1;
$enable = self::enable($data['enable'] ?? 1, $personal_rec);
if (!self::valid_appid($appid)){
return ["code"=> self::ERROR_CODE_PARAM, "msg" => "appid有误"];
}
if( empty($token) || !self::valid_ios_token($token) ){
$err = true;
return ["code"=> self::ERROR_CODE_PARAM, "msg" => "token有误"];
}
if( !$version ){
$err = true;
return ["code"=> self::ERROR_CODE_PARAM, "msg" => "version有误"];
}
// $action = explode('?', $_SERVER['REQUEST_URI'])[0]; // 与运营中台沟通,暂时写死成 website 路径,之后重构再调整
$action = "/Website/push/BindingTokenAction.php";
$send = [
'action' => $action,
'userid' => $userid,
'appid' => $appid,
'request_time' => intval($_SERVER['REQUEST_TIME']),
'version' => $version,
'time_zone' => $data["time_zone"] ?? "",
'personal_rec' => intval($personal_rec),
'enable' => $enable,
'sound' => $data["sound"] ?? "",
'push_level' => $data["push_level"] ?? "",
'old_token' => $old_token,
'new_token' => $new_token,
'push_key' => $data["push_key"] ?? "",
'cv' => $data["cv"] ?? "",
'os' => $data["os"] ?? "",
'distribution' => $data["distribution"] ?? "",
'platform' => "IOS"
];
$send = array_filter ($send,function($v){if($v===''){return false;}else{return true;}});
if(!self::sendKafka($send)){
$err = true;
return ["code"=> self::ERROR_CODE_KAFKA, "msg" => "send failed"];
};
$err = false;
return true;
}
}
\ No newline at end of file
use Api\PhpServices\Sensitive\Sensitive;
//参数描述
businessId = 业务ID 1.一点 2.身边 9.VPN
text 送查内容
scene 场景ID 1.标题 2.简介 3.正文 4.评论 6.昵称 7.搜索
//单个词敏感词
$params = [
'businessId' => !empty($param['businessId']) ? $param['businessId'] : 1,
'text' => !empty($param['text']) ? $param['text'] : '习近平',
'scene' => !empty($param['scene']) ? $param['scene'] : 3,
];
(new Sensitive)->detect($params)
//批量敏感词
$params = [
[
'businessId' => 1,
'text' => '习近平',
'scene' => 3,
]
];
(new Sensitive)->detectBatch($params)
\ No newline at end of file
<?php
/**
*
* @author haiming
* Date: 2021/5/21
* Time: 10:32 PM
*/
namespace Api\PhpServices\Sensitive;
use Api\PhpUtils\Common\TimeOut;
use Api\PhpUtils\Http\Request;
use App\Exception\custom\CodeSpecialException;
class Sensitive
{
/**
* 敏感词
*
*
*/
public function detect($param)
{
$url = config('interface','service.sensitive.detect');
if(!$url){
throw new CodeSpecialException("failed");
}
if (empty($param)) {
throw new CodeSpecialException("failed");
}
$params = [
'businessId' => !empty($param['businessId']) ? $param['businessId'] : 1,
'text' => !empty($param['text']) ? $param['text'] : '',
'scene' => !empty($param['scene']) ? $param['scene'] : 3,
];
$headers = [
'Content-Type' => 'application/json;charset=UTF-8',
];
$detect_info = (new TimeOut())->runPost($url, $params,'json',$headers);
if(!$detect_info){
throw new CodeSpecialException("timeout");
}
return $detect_info;
}
/**
* 敏感词批量
*
*
*/
public function detectBatch($params)
{
$url = config('interface','service.sensitive.detect_batch');
if(!$url){
throw new CodeSpecialException("failed");
}
if (empty($params)) {
throw new CodeSpecialException("failed");
}
$headers = [
'Content-Type' => 'application/json;charset=UTF-8',
];
$detect_info = (new TimeOut())->runPost($url, $params,'json',$headers);
if(!$detect_info){
throw new CodeSpecialException("timeout");
}
return $detect_info;
}
}
## Session服务
#### Usage:
```
use Api\PhpServices\Session\SessionManager;
// write session
SessionManager::set($appid, $userid, $isLogin, $sessionData, $maxLogin=10);
// start session
SessionManager::start();
// destroy session
SessionManager::destroy();
```
\ No newline at end of file
<?php
namespace Api\PhpServices\Session;
use Api\PhpServices\Session\Session;
use Api\PhpServices\Session\RedisSessionHandler;
use Api\PhpUtils\Http\Request;
class RedisSession extends Session
{
protected $redis = null;
protected $key = 'c071f6e5923a648a5ef88f32b6f738e1';
/**
* 从cookie开启session
* @param boolean $readOnly 是否只读会话,如果是,则在读取session之后直接关闭session
* 只读会话,需要在session更改后,手动调用write()写入,不然更改后的会话不会保存
* @param string $app
* @return boolean
*/
public function start($readOnly = true)
{
if ($this->started) {
return true;
}
$sessionId = $_COOKIE[$this->getSessionName()] ?? '';
if (empty($sessionId) || !$this->checkSessionId($sessionId)) {
return false;
}
$this->sessionId = $sessionId;
$options = [];
if ($readOnly) {
$options['read_and_close'] = true;
}
return $this->doStart($options);
}
/**
* 创建session,多用于用户登录后创建session,用户会话包括:访客会话和登录会话
* @param integer $userid
* @param string $appid session所属app,默认为一点资讯
* @param boolean $isLogin 是否登录
* @return boolean
*/
public function create($appid, $userid, $isLogin = false)
{
// 如果session已开启,需要关闭当前会话
if ($this->started) {
$this->close();
}
$this->setAppid($appid);
if ($userid === null || $appid === null) {
throw new \Exception("userid[{$userid}], or appid[{$appid}] is null");
}
$sessionId = $this->generateSessionId($appid, $userid, $isLogin);
if (empty($sessionId)) {
return false;
}
$this->sessionId = $sessionId;
$options = [];
return $this->doStart($options, [
'userid' => $userid,
]);
}
/**
* start session
* @param array $options session_start()支持的选项
* @param array $params 该方法使用的附加参数
* @return boolean
*/
protected function doStart(array $options = [], array $params = [])
{
// 注册session处理器
$sessionHandler = new RedisSessionHandler();
$sessionHandler->setExpire($this->getExpire($params['userid'] ?? null));
$this->setHandler($sessionHandler, true);
if (empty($options['serialize_handler'])) {
$options['serialize_handler'] = 'php_serialize';
}
// 禁用session_start()默认cookie header发送
$options['use_cookies'] = 0;
//$options['cache_limiter'] = '';
$this->setSessionId();
$this->setSessionName();
return parent::start($options);
}
/**
* 生成用户sessionId
* @param integer $userid
* @param string $username
* @param boolean $isLogin 是否登录
* @return string
*/
public function generateSessionId($appid, $userid, $isLogin = false)
{
$validSessionIds = $this->validSessionIds($appid, $userid, $isLogin);
// 提取其中在用的session
$liveSession = $this->extractLiveSessionIds($validSessionIds);
if (empty($liveSession)) {
return $validSessionIds[rand(0, count($validSessionIds) - 1)];
}
$usableSesssionIds = array_values(array_diff($validSessionIds, array_keys($liveSession)));
if ($usableSesssionIds) {
$sessionId = $usableSesssionIds[array_rand($usableSesssionIds, 1)];
} else {
//10个可用全部用完,随机选一个
$sessionId = $validSessionIds[rand(0, count($validSessionIds) - 1)];
}
return $sessionId;
}
/**
* 删除当前会话
* @return boolean
*/
public function deleteSelf()
{
return $this->delete($this->sessionId);
}
/**
* 删除指定session的redis
* @param array|string $sessionIds
* @return boolean
*/
public function delete($sessionIds)
{
if (empty($sessionIds)) {
return true;
}
if (!is_array($sessionIds)) {
$sessionIds = [$sessionIds];
}
// 如果当前session也被删除,需要先关闭当前session
if (in_array($this->sessionId, $sessionIds)) {
$this->close();
}
$url = $this->getUrl('delete');
$params = ['sessionid' => array_unique($sessionIds), 'key' => $this->key];
$result = (new Request())->post($url, $params, 0, 'json');
if (isset($result['response']['code']) && $result['response']['code'] == 0 ) {
return true;
}
return false;
}
/**
* 删除用户所有会话
* @param integer $userid
* @param string $username
* @param int $type 0 所有session,1 访客session,2 非访客session
* @return boolean
*/
public function deleteByUser($appid, $userid, $type = 0)
{
$sessionIds = [];
if ($type === 1 || $type === 0) {
$sessionIds = array_merge($sessionIds, $this->validSessionIds($appid, $userid, false));
}
if ($type === 2 || $type === 0) {
$sessionIds = array_merge($sessionIds, $this->validSessionIds($appid, $userid, true));
}
return $this->delete($sessionIds);
}
/**
* 提取在用的session id
* @param array $sessionIds
* @return array
*/
public function extractLiveSessionIds(array $sessionIds)
{
$data = [];
$url = $this->getUrl('mget');
$params = ['sessionid' => $sessionIds, 'key' => $this->key];
$result = (new Request())->post($url, $params, 0, 'json');
if (isset($result['response']['code']) && $result['response']['code'] == 0
&& isset($result['response']['result']) && !empty($result['response']['result'])
) {
$liveSession = $result['response']['result'];
foreach ($liveSession as $key => $value) {
if (empty($value)) {
continue;
}
$data[$sessionIds[$key]] = is_string($value) ? unserialize($value) : $value;
}
}
return $data;
}
/**
* get yaconf interface.url
* @return string
*/
public function getUrl($param = '')
{
if (empty($param)){
return "";
}
$env = \Yaf\Application::app()->environ() ?? "test";
$key = 'interface.' . $env . '.service.session.' . $param;
return \Yaconf::get($key);
}
}
<?php
namespace Api\PhpServices\Session;
use Api\PhpUtils\Http\Request;
/**
* Customer Redis Session Handler
*/
class RedisSessionHandler implements \SessionHandlerInterface
{
protected $key = 'c071f6e5923a648a5ef88f32b6f738e1';
protected $expire = 0;
/**
* open session
* @param string $savePath
* @param string $sessionName
* @return boolean
*/
public function open($savePath, $sessionName)
{
return true;
}
/**
* read session
* @param string $sessionId
* @return string
*/
public function read($sessionId)
{
$url = $this->getUrl('get');
$query = ['sessionid' => $sessionId];
$result = (new Request())->get($url, $query);
$data = [];
if (isset($result['response']['code']) && $result['response']['code'] == 0 && isset($result['response']['result'])) {
$data = $result['response']['result'];
}
return empty($data) ? '' : (is_array($data) ? serialize($data) : $data);
}
/**
* write session
* @param string $sessionId
* @param string $sessionData
* @return boolean
*/
public function write($sessionId, $sessionData)
{
if (!$_SESSION) {
return true;
}
$url = $this->getUrl('set');
$params = ['sessionid' => $sessionId, 'data' => $_SESSION, 'expire' => $this->expire, 'key' => $this->key];
$result = (new Request())->post($url, $params, 3000, 'json');
if (isset($result['response']['code']) && $result['response']['code'] == 0 ) {
return true;
}
return false;
}
/**
* close session
* @return boolean
*/
public function close()
{
return true;
}
/**
* destroy session
* @param string $sessionId
* @return boolean
*/
public function destroy($sessionId)
{
$url = $this->getUrl('delete');
$params = ['sessionid' => $sessionId, 'key' => $this->key];
$result = (new Request())->post($url, $params, 3000, 'json');
if (isset($result['response']['code']) && $result['response']['code'] == 0 ) {
return true;
}
return false;
}
/**
* garbage clean session
* session in redis would be auto cleaned when expired
* @param integer $maxlifetime
* @return integer
*/
public function gc($maxlifetime)
{
return 0;
}
/**
* set session expire
* @param integer $expire second
* @return RedisSessionHandler
*/
public function setExpire($expire)
{
$this->expire = $expire;
return $this;
}
/**
* get session expire
* @return integer
*/
public function getExpire()
{
return $this->expire;
}
/**
* get yaconf interface.url
* @return string
*/
public function getUrl($param = '')
{
if (empty($param)){
return "";
}
$env = \Yaf\Application::app()->environ() ?? "test";
$key = 'interface.' . $env . '.service.session.' . $param;
return \Yaconf::get($key);
}
}
<?php
namespace Api\PhpServices\Session;
/**
* Session base class
*/
abstract class Session
{
protected $sessionId = '';
protected $sessionName = 'JSESSIONID';
protected $started = false;
protected $handler = null;
protected $appid = '';
protected static $instance = null;
protected function __construct()
{
}
public static function getInstance()
{
if (is_null(self::$instance)) {
self::$instance = new static();
}
return self::$instance;
}
/**
* session started, or not
* @return boolean
*/
public function started()
{
$this->started = false;
if (session_status() === PHP_SESSION_ACTIVE) {
$this->started = true;
}
return $this->started;
}
public function getAppid()
{
return $this->appid;
}
public function setAppid($appid)
{
$this->appid = $appid;
return $this;
}
/**
* get session id
* @return string
*/
public function getSessionId()
{
return $this->sessionId;
}
/**
* set session id
* @param string $sessionId
* @return boolean
*/
public function setSessionId($sessionId = null)
{
if ($sessionId) {
if (!$this->checkSessionId($sessionId)) {
throw new \Exception("session id [{$sessionId}] invalid");
}
$this->sessionId = $sessionId;
}
if (!empty($this->sessionId)) {
return session_id($this->sessionId);
}
return false;
}
/**
* get session name
* @return string
*/
public function getSessionName()
{
return $this->sessionName;
}
/**
* set session name
* @param string $sessionName
* @return boolean
*/
public function setSessionName($sessionName = null)
{
if ($sessionName) {
$this->sessionName = $sessionName;
} else {
$sessionName = $this->sessionName;
}
return session_name($sessionName);
}
/**
* get session handler
* @return SessionHandlerInterface
*/
public function getHandler()
{
return $this->handler;
}
/**
* set session handler
* @param object $handler
* @param boolean $registerShutdown
* @return boolean
*/
public function setHandler($handler, $registerShutdown = true)
{
$this->handler = $handler;
return session_set_save_handler($handler, $registerShutdown);
}
/**
* session start
* @param array $options
* @return boolean
*/
public function start($options = [])
{
if (session_start($options) === false) {
return false;
}
$this->started();
return true;
}
/**
* get session expire (second)
* @param string $userid
* @return integer
*/
public function getExpire($userid = null)
{
if (empty($userid) || !in_array($userid, [
1211920133,
1215304799,
])) {
return 2592000;
}
return 3600;
}
/**
* flush session to database
* @return boolean
*/
public function write()
{
return $this->handler ? $this->handler->write(
$this->sessionId,
serialize($_SESSION)
) : false;
}
/**
* destroy session
* @return boolean
*/
public function destroy()
{
$this->started = false;
return session_destroy();
}
/**
* close session
* @return boolean
*/
public function close()
{
if (!$this->started()) {
$this->write();
$this->closeHandler();
$this->started = false;
return true;
}
session_write_close();
$this->started = false;
return true;
}
/**
* close session handler
* @return boolean
*/
protected function closeHandler()
{
return $this->handler ? $this->handler->close() : false;
}
/**
* set cookie
* @param integer $expire expire time (s)
* @param boolean $replace replace previous similar cookie
* @return boolean
*/
public function setCookie($expire = 0, $replace = true)
{
if ($replace) {
$cookieKeyword = $this->getSessionName()
. '=' . $this->getSessionId() . ';';
$this->removeCookie($cookieKeyword);
}
if ($expire != 0) {
$expire += time();
}
setcookie(
$this->getSessionName(),
$this->getSessionId(),
$expire, '/', '', false, true);
$_COOKIE[$this->getSessionName()] = $this->getSessionId();
return true;
}
/**
* generate valid session id
* @param string $appid
* @param integer $userid
* @param boolean $isLogin 是否登录
* @return array
*/
public function validSessionIds($appid, $userid, $isLogin = false)
{
$guest = $isLogin ? 'nonguest' : 'guest';
// 使用codis hash tag保证同一个文章的正文及信息流缓存落入同一台codis server
$tag = '{'.strtolower(str_replace(array('+','/','='), array(''), base64_encode($userid))).'}';
$sessionIds = [];
for ($i = 0; $i < 10; $i++) {
$sessionId = $tag . md5($i . $appid . $userid . $guest);
$sessionIds[] = $sessionId . substr(sha1($sessionId), -2);
}
return $sessionIds;
}
/**
* check session id
* @return boolean
*/
public function checkSessionId($sessionId = null)
{
if(!$sessionId) {
return false;
}
$verifyCode = substr($sessionId, -2);
$encodeStr = substr($sessionId, 0, -2);
if (substr(sha1($encodeStr), -2) !== $verifyCode) {
return false;
}
return true;
}
/**
* remove cookie
* @param string $keyword
* @return boolean
*/
protected function removeCookie($keyword = null)
{
if (is_null($keyword)) {
header_remove('Set-Cookie');
return true;
}
$keyword = " {$keyword}";
$otherCookies = [];
foreach (headers_list() as $header) {
if (stripos($header, 'Set-Cookie:') !== 0) {
continue;
}
if (strpos($header, $keyword, 11) !== 11) {
$otherCookies[] = $header;
}
}
header_remove('Set-Cookie');
$otherCookies = array_unique($otherCookies);
foreach ($otherCookies as $cookie) {
header($cookie, false);
}
return true;
}
}
<?php
namespace Api\PhpServices\Session;
use Api\PhpServices\Session\RedisSession;
class SessionManager
{
/**
* get session instance
* @return RedisSession
*/
public static function getSession()
{
return RedisSession::getInstance();
}
/**
* set session app
* @param string $app
* @return boolean
*/
public static function setAppid($app)
{
self::getSession()->setAppid($app);
return true;
}
/**
* get session app
* @return string
*/
public static function getAppid()
{
return self::getSession()->getAppid();
}
/**
* get session name
* @return string
*/
public static function name()
{
return self::getSession()->getSessionName();
}
/**
* get session id
* @return string
*/
public static function sid()
{
return self::getSession()->getSessionId();
}
/**
* whether session started
* @return boolean
*/
public static function started()
{
return self::getSession()->started();
}
/**
* 删除非访客session
*
* @param int $userid
* @param string $username
* @param string $app
* @return bool
*/
public static function delete_nonguest($appid, $userid)
{
$session = self::getSession();
return $session->deleteByUser($appid, $userid, 2);
}
/**
* delete all sessions of the user
* @param integer $userid
* @param string $username
* @param string $app
* @return boolean
*/
public static function delete_all($appid, $userid)
{
$session = self::getSession();
return $session->deleteByUser($appid, $userid);
}
/**
* delete sessions
* @param array|string $sessionIds
* @return boolean
*/
public static function delete($sessionIds)
{
return self::getSession()->delete($sessionIds);
}
/**
* destroy session
* @return boolean
*/
public static function destroy()
{
$session = self::getSession();
if (!self::started()) {
$sessionId = $_COOKIE[$session->getSessionName()] ?? '';
if (empty($sessionId) || !$session->checkSessionId($sessionId)) {
return false;
}
return $session->delete($sessionId);
}
if ($session->destroy()) {
$_SESSION = [];
return true;
}
return false;
}
/**
* start session from cookie
* @param boolean $readOnly 是否只读会话
* 以只读形式打开的会话,如果session发生了更改,需要手动调用write()写入会话
* @param string $app
* @return RedisSession
*/
public static function start($readOnly = true)
{
$session = self::getSession();
if ($session->start($readOnly)) {
if (!empty($_SESSION)
&& (!isset($_SESSION['utime']) || (time() - $_SESSION['utime']) > 86400)) {
$_SESSION['utime'] = time();
self::write();
}
return $session;
}
return false;
}
/**
* set session
* @param array $session
* @param boolean $readonly
* @param integer $cookieExpire
* @return boolean
*/
public static function set($appid, $userid, $isLogin, array $session, $maxLogin = 10, $cookieExpire = 0)
{
// 只允许单台设备登录,先清除所有已登录用户的sessionid
if ($isLogin && $maxLogin === 1) {
self::delete_nonguest($appid, $userid);
}
// @todo 大于1小于10, 让用户选择需要下线的设备信息,暂无此需求
$sessionInstance = self::getSession();
if (!$sessionInstance->create($appid, $userid, $isLogin)) {
return false;
// throw new \Exception('session was not started');
}
self::fillup($session);
self::write();
$sessionInstance->setCookie($cookieExpire);
return $sessionInstance->getSessionName() . '=' . $sessionInstance->getSessionId();
}
/**
* fillup $_SESSION
* @param array $session
* @param boolean $readonly
* @return array
*/
public static function fillup(array $session)
{
$_SESSION['utime'] = time();
foreach ($session as $key => $value) {
$_SESSION[$key] = $value;
}
return $_SESSION;
}
/**
* read session data
* @return array
*/
public static function read()
{
self::pickup();
if (!empty($_SESSION)
&& (!isset($_SESSION['utime']) || (time() - $_SESSION['utime']) > 86400)) {
$_SESSION['utime'] = time();
if (self::started()) {
self::write();
} else {
self::close();
}
}
return $_SESSION;
}
/**
* pickup data from session
*/
public static function pickup()
{
if (!empty($_SESSION['userid'])) {
$_GET['userid'] = $_SESSION['userid'];
$_POST['userid'] = $_SESSION['userid'];
$_REQUEST['userid'] = $_SESSION['userid'];
}
if (!isset($_GET['version']) && isset($_SESSION['version'])) {
$_GET['version'] = $_SESSION['version'];
}
if (isset($_SESSION['usertype'])) {
$_GET['usertype'] = $_SESSION['usertype'];
}
if (isset($_SESSION['readonly'])) {
$_GET['readonly'] = $_SESSION['readonly'];
}
}
/**
* get session data
* @return array
*/
public static function get()
{
return $_SESSION;
}
/**
* write session data
* @return boolean
*/
public static function write()
{
return self::getSession()->write();
}
/**
* close session
* @return boolean
*/
public static function close()
{
return self::getSession()->close();
}
}
This diff is collapsed.
<?php
namespace Api\PhpServices\ShopImage;
use Endroid\QrCode\ErrorCorrectionLevel;
use Endroid\QrCode\QrCode;
class QR
{
private $_content;
private $_size = 300;
private $_logo_url = '';
private $_logo_size = 80;
private $_writeFile = false;
private $_blockSize = QrCode::ROUND_BLOCK_SIZE_MODE_MARGIN;
// private $_errorCorrectionLevel;
public function setRoundBlockSize($_blockSize)
{
$this->_blockSize = $_blockSize;
}
public function setWriteFile(bool $writeFile): void
{
$this->_writeFile = $writeFile;
}
public function setContent($content): void
{
$this->_content = $content;
}
public function setSize(int $size): void
{
$this->_size = $size;
}
public function setLogoUrl(string $logo_url): void
{
$this->_logo_url = $logo_url;
}
public function setLogoSize(int $logo_size): void
{
$this->_logo_size = $logo_size;
}
public function __construct($content)
{
$this->_content = $content;
}
public function get(){
$qr = new QrCode($this->_content);
$qr->setSize($this->_size);
$qr->setRoundBlockSize(true, $this->_blockSize);
if(!empty($this->_logo_url)){
$qr->setLogoPath($this->_logo_url);
$qr->setLogoSize($this->_logo_size);
}
if (!$this->_writeFile) {
header('Content-Type: ' . $qr->getContentType());
}
return $qr->writeString();
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\Sms;
use Api\PhpUtils\Common\TimeOut;
use Api\PhpUtils\Http\Request;
use App\Exception\custom\CodeSpecialException;
class Sms
{
/**
* 验证短信是否正确
*
* @param $params['mobile'] 手机号
* @param $params['code'] 验证码
* @param $params['appid'] appid
*/
public function checkSmsCode($params)
{
$url = config('interface','service.user.check_sms_code');
if(!$url){
throw new CodeSpecialException("failed");
}
if (empty($params)) {
throw new CodeSpecialException("failed");
}
$params = [
'mobile' => !empty($params['mobile']) ? $params['mobile'] : '',
'appid' => !empty($params['appid']) ? $params['appid'] : '',
'code' => !empty($params['code']) ? $params['code'] : '',
'key' => 'f16bdd46292480b4b82c841d90a6ba02',
'partner' => 'merchant-b'
];
$sms = (new TimeOut())->runGet($url, $params);
if(!$sms){
throw new CodeSpecialException("timeout");
}
if (!empty($sms) && $sms['code'] == 0) {
return true;
}else{
return false;
}
}
/**
* 发送验证码
*
* @param $params['mobile'] 手机号
* @param $params['appid'] appid
* @param $params['scene'] 使用场景 例如: 登陆传login
* @param $params['template'] 模版id,发送短信模版
* @param $params['code_lenght'] 短信验证码长度 4位和6位
* @param $params['ticket_expire'] 验证码验证周期,默认86400秒(1天),最小值为60秒,少于最小值使用默认值
* @param $params['resend_times'] 验证周期内验证码最大发送次数,默认重发最多10次,最小值为1次,少于最小值使用默认值
* @param $params['retry_times']验证周期内每个验证码最大可校验次数,默认每个验证码最大可校验10次,最小值为1次,少于最小值使用默认值
*
*/
public function sendSmsCode($params = [])
{
$url = config('interface','service.user.send_sms_code');
if(!$url){
throw new CodeSpecialException("failed");
}
if (empty($params)) {
throw new CodeSpecialException("failed");
}
$params = [
'mobile' => !empty($params['mobile']) ? $params['mobile'] : '',
'appid' => !empty($params['appid']) ? $params['appid'] : 'hubble',
'scene' => !empty($params['scene']) ? $params['scene'] : '',
'key' => 'f16bdd46292480b4b82c841d90a6ba02',
'partner' => 'merchant-b',
'template' => !empty($params['template']) ? $params['template'] : 7,
'code_lenght' => !empty($params['code_lenght']) ? $params['code_lenght'] : 6,
'ticket_expire' => !empty($params['ticket_expire']) ? $params['ticket_expire'] : 86400,
'resend_times' => !empty($params['resend_times']) ? $params['resend_times'] : 5,
'retry_times' => !empty($params['retry_times']) ? $params['retry_times'] : 10,
];
$sms = (new TimeOut())->runGet($url, $params);
if(!$sms){
throw new CodeSpecialException("timeout");
}
if (!empty($sms) && $sms['code'] == 0) {
return $sms;
}else{
return $sms;
}
}
/**
* 发送短信,不需要验证,场景是,只发,例如:审核通过,发个通知短信,审核驳回,发一个通知短信
*
* @param $mobile 手机号
* @param $template 短信模版
* @param $param = [] 数组,多个参数传值
*/
public function messageSendSms($mobile,$template,$param = [])
{
$url = config('interface', 'service.message.send_sms');
if (!$url) {
throw new CodeSpecialException("failed");
}
$params = [
'mobile' => $mobile,
'key' => 'b2acfb0d53c8557c9b0a0346d2a4fab4',
'template' => $template,
'param' => $param,
];
$sms = (new TimeOut())->runGet($url, $params);
if (!$sms) {
throw new CodeSpecialException("timeout");
}
if (!empty($sms) && $sms['code'] == 0) {
return true;
} else {
return false;
}
}
}
### bp暂未接入
```
/**
* 申请 towerpro key
*/
public function keyAction(){
$appid = "test9_appid";
$env = 0;
$version = "124441";
$os = 1;
$creator = "subway";
$keyTag = "test";
$res = Towerpro::create($appid, $env, $version, $os, $creator, $keyTag, $note=null);
$data = [
"keyInfo" => null,
'data' => null
];
if($res && isset($res["result"]) && $res["result"]){
if (isset($res["result"]["data"])){
$data["data"] = $res["result"]["data"];
unset($res["result"]["data"]);
}
$data["keyInfo"] = $res["result"];
}
echo json_encode($res);
return;
}
/**
* 用 key 配置信息
*/
public function setAction(){
$res = Towerpro::set("df436947f7e0d4ad7cc4a9cefdc0a708",[
]);
if($res["code"] == 0){
$this->success();
return;
}
echo json_encode($res);
return;
}
/**
* 用 key 获取信息
*/
public function getAction(){
$res = Towerpro::get("df436947f7e0d4ad7cc4a9cefdc0a708", 1);
echo json_encode($res);
return;
}
```
\ No newline at end of file
<?php
namespace Api\PhpServices\Towerpro;
use Api\PhpUtils\Http\Request;
class Towerpro
{
/**
* 申请一个key,可以通过本接口申请,也可以在平台网页中申请
* 一般本接口只需本地调用一次,不会在业务接口中使用
* http://ydwiki.yidian-inc.com/pages/viewpage.action?pageId=53663475
*
* @param $appid string 应用id
* @param $env int 0:测试环境,1:线上环境
* @param $version string 版本号
* @param $os int 操作系统,0:ios,1:安卓,2 所有
* @param $creator string 创建者
* @param $keyTag string key 的关键词标志
* @param null $note string 备注说明
*/
public static function create($appid, int $env, $version, int $os, $creator, $keyTag, $note=null){
$url = config("interface","towerpro.create_key");
$data = [
"appid" => $appid,
"env" => $env,
"version" => $version,
"os" => $os,
"creator" => $creator,
"keyTag" => $keyTag,
"note" => $note,
];
$res = (new Request())->post($url, $data,5000, 'json');
return $res;
}
/**
* 使用key配置数据
* @param $key
* @param array $data
*/
public static function set($key, array $data){
$url = config("interface","towerpro.set");
$data = [
"uniqueKey" => $key,
"data" => $data
];
$res = (new Request())->post($url, $data,5000, 'json');
return $res;
}
/**
* 使用key获取配置数据
* @param $key
* @param int $type 0 所有信息(key信息+data); 1 仅 data ; 2 仅 key 信息
* @return array|bool|mixed
*/
public static function get($key, int $type = 0){
$url = config("interface","towerpro.get");
$data = [
"uniqueKey" => $key
];
$res = (new Request())->get($url, $data,5,["Content-Type"=>"application/json"]);
if($res["code"] != 0){
return $res;
}
$all = [
"keyInfo" => null,
'data' => null
];
if($res && isset($res["result"]) && $res["result"]){
if (isset($res["result"]["data"])){
$all["data"] = $res["result"]["data"];
unset($res["result"]["data"]);
}
$all["keyInfo"] = $res["result"];
}
switch ($type){
case 1:
$data = $all['data'];
break;
case 3:
$data = $all['keyInfo'];
break;
default:
$data = $all;
break;
}
return ["code"=>0, "data"=>$data];
}
}
\ No newline at end of file
## 接入tuffy统一实验平台,bp暂未接入
#### 数据组wiki地址
<url>http://ydwiki.yidian-inc.com/pages/viewpage.action?pageId=34241933</url>
#### Usage:
```
try{
$tuffyService = new TuffyService();
$full = $tuffyService->getFullTuffyBucket('745679237', 'yidian');
$basic = $tuffyService->getBasicTuffyBucket('745679237', 'yidian');
$user = $tuffyService->getUserBucket('745679237', 'yidian');
...
}catch (\Exception $e){
...
}
```
\ No newline at end of file
<?php
/**
* 接入API_GATEWAY实现平台,wiki地址:http://ydwiki.yidian-inc.com/pages/viewpage.action?pageId=34241933
* Description of TuffyService.php
*
* @author caoyunmeng
* Date: 2021/2/18
* Time: 2:20 PM
*/
namespace Api\PhpServices\Tuffy;
use Api\PhpUtils\Http\Request;
class TuffyService{
private $request = false;
public function __construct() {
$this->request = new Request();
}
/**
* 计算前端全量Bucket(基于画像数据,用于APP等有画像场景)
*
* @param $userid
* @param $appid
* @return bool|mixed
* @throws
*/
function getFullTuffyBucket($userid, $appid)
{
if (empty($userid)) {
throw new \Exception('userid params is empty');
}
if (empty($appid)) {
throw new \Exception('appid params is empty');
}
$options = array(
'userId' => $userid,
'appId' => $appid
);
return $this->request->post(\Yaconf::get('interface.common.service.tuffy.full_buckets'),
$options,
1,
'json',
array('Content-type' => 'application/json')
);
}
/**
* 计算前端基础Bucket(不取画像,用于Web页面等无画像场景)
*
* @param $userid
* @param $appid
* @param $extraInfo array 补充信息:举例:net、extraInfo、brand、androidId、net、type 等,所有客户端请求的信息统一传递到extraInfo里
* $extraInfo = array(
'deviceid' => $_GET['deviceid'],
'type' => $_GET['type'],
'cv' => $cv,
'ip' => ip(),
'version' => '999999',
'userid' => $wuid,
'net' => isset($_GET['net'])? $_GET['net']: '',
'createTime' => $_GET['createTime']??'',
'appid' => $_GET['appid'],
'env' => $_GET['env']??'',
'distribution' => isset($_GET['distribution'])? $_GET['distribution']:''
'net' => isset($_GET['net]) ? $_GET['net]:''
);
* @return bool|mixed
* @throws
*/
function getBasicTuffyBucket($userid, $appid, $extraInfo = array())
{
if (empty($userid)) {
throw new \Exception('userid params is empty');
}
if (empty($appid)) {
throw new \Exception('appid params is empty');
}
$options = array(
'userId' => $userid,
'appId' => $appid
);
if(!empty($extraInfo)){
$options['extraInfo'] = $extraInfo;
}
return $this->request->post(
\Yaconf::get('interface.common.service.tuffy.basic_buckets'),
$options,
0.1,
'json',
array('Content-type' => 'application/json')
);
}
/**
* 获取用户bucket
*
* @param $userid
* @param $appid
* @return bool|mixed
* @throws
*/
function getUserBucket($userid, $appid){
if (empty($userid)) {
throw new \Exception('userid params is empty');
}
if (empty($appid)) {
throw new \Exception('appid params is empty');
}
$options = array(
'service_name' => 'app_api',
'userid' => $userid,
'appId' => $appid,
);
return $this->request->get(
\Yaconf::get('interface.common.service.tuffy.user_buckets'),
$options,
0.1,
array('Content-type' => 'application/json')
);
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\XhProfiler;
use Api\PhpUtils\Mongo\MongoBase;
class XhMongo extends MongoBase
{
protected function getConfigIndex()
{
return 'xhprof';
}
protected function getDatabaseName()
{
return 'xhprof';
}
protected function getCollectionName()
{
$sever = str_replace('.','_',$_SERVER['SERVER_NAME']);
$collection = \Yaconf::get('xhprof.common.collection');
if (isset($collection[$sever])) {
return $sever;
}
// 默认使用results
return 'results';
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\XhProfiler;
use Xhgui\Profiler\Profiler;
class XhProfilerService
{
private $profiler;
public function __construct()
{
$this->profiler = new Profiler([]);
}
/**
* 开启 xhprofiler 分析
*/
public function start(): void
{
//开启 分析器,并且初始化 mongodb 实例
$this->profiler->start();
}
/**
* 结束分析
* @param $domain
*/
public function end($domain): void
{
// 结束分析器,生产性能检测数据
$profiler_data = $this->profiler->disable();
$profiler_data = $this->dealProfile($profiler_data,$domain);
$mongo = XhMongo::getInstance();
$mongo->insertOne($profiler_data);
}
private function dealProfile(array $profile,$domain)
{
$profile['profile'] = $this->encodeProfile($profile['profile']);
$profile['domain'] = str_replace('.', '_',$domain);
return $profile;
}
private function encodeProfile(array $profile)
{
$results = array();
foreach ($profile as $k => $v) {
if (strpos($k, '.') !== false) {
$k = str_replace('.', '_', $k);
}
$results[$k] = $v;
}
return $results;
}
}
\ No newline at end of file
<?php
namespace Api\PhpServices\XhProfiler;
class Xhprof
{
public static $xhprof_service;
private static $flag = false;
protected function __construct()
{
}
/**
* 开启 xhprof 性能检测分析
*/
public static function getInstance()
{
if (empty(self::$xhprof_service))
{
return new XhProfilerService();
}
return false;
}
public static function startXhprof()
{
//从 yaconf 获取配置 ,判断当前域名是否要开启
$config = \Yaconf::get('xhprof') ?? [];
if (!self::judgeSwitch($config)) {
return false;
}
self::$flag = true;
self::$xhprof_service = self::getInstance();
if ( !empty(self::$xhprof_service))
{
self::$xhprof_service->start();
}
return true;
}
/**
* 开关决策器
* @return bool
*/
private static function judgeSwitch($config=[])
{
$domain = str_replace('.', '_',$_SERVER['SERVER_NAME']);
$switch = $config['common']['switch'] ?? [];
if (!isset($switch[$domain]) || random_int(0,100) >= $switch[$domain]) {
return false;
}
return true;
}
/**
* 关闭分析器,并且将数据写入mongo
*/
public static function endXhprof()
{
if (!self::$flag) {
return false;
}
self::$xhprof_service->end($_SERVER['SERVER_NAME']);
}
}
\ No newline at end of file
composer.lock
/vendor/
.idea
.DS_Store
.project
\ No newline at end of file
生活圈商户系统工具类库,配合yaf框架使用的基础库
负责人:崔伟峰
\ No newline at end of file
{
"name": "api/php_utils",
"description": "bp api php_utils",
"type": "library",
"require": {
"php": "7.2.*",
"guzzlehttp/guzzle": "6.3",
"mongodb/mongodb": "1.4.3",
"ext-mbstring": "*",
"ext-exif": "*",
"ext-fileinfo": "*",
"ext-ctype": "*",
"elasticsearch/elasticsearch": "~7.0"
},
"autoload": {
"psr-4": {
"Api\\PhpUtils\\": "src/"
}
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Common工具库
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Http工具库
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Lock工具库
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
Log工具库
\ No newline at end of file
This diff is collapsed.
Email工具库
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment