394 lines
13 KiB
PHP
Executable File
394 lines
13 KiB
PHP
Executable File
<?php
|
||
|
||
/**
|
||
* @Author: fm453
|
||
* @Date: 2019-04-27 22:19:28
|
||
* @Last Modified by: fm453
|
||
* @Last Modified time: 2019-04-27 22:28:12
|
||
*/
|
||
|
||
/**
|
||
* 利用workerman制作的推送接口控制器(演示版,默认针对vcms的fm453_*系列应用)
|
||
*/
|
||
|
||
namespace frontend\controllers;
|
||
|
||
use Yii;
|
||
use yii\web\Controller;
|
||
|
||
use dataModel;
|
||
|
||
//必须添加这一句,以便引入dataModel外部类库
|
||
|
||
// 引用GateWay Client
|
||
require(__DIR__ . '/../../vendor/workerman/GatewayClient-3.0.0/Gateway.php');
|
||
|
||
// GatewayClient 3.0.0版本开始要使用命名空间
|
||
use GatewayClient\Gateway;
|
||
|
||
// 设置GatewayWorker服务的Register服务ip和端口
|
||
Gateway::$registerAddress = '127.0.0.1:4530';
|
||
|
||
class PushController extends Controller
|
||
{
|
||
public $enableCsrfValidation = FALSE;//取消对POST数据的csrf令牌验证
|
||
|
||
/**
|
||
* 绑定客户端与指定客户id\分组id
|
||
*/
|
||
public function actionBind()
|
||
{
|
||
global $_FM;
|
||
//数据取出方法
|
||
$dataGet = $_FM['get']; //GET进来的参数
|
||
$dataPost = $_FM['post']; //POST进来的参数
|
||
$data = array();
|
||
header('Access-Control-Allow-Origin:*'); //允许任何网站通过ajax发送请求
|
||
require dirname(__FILE__) . '/_public/plat.php';
|
||
|
||
$group_pre = 'VCMS-IMMS';
|
||
|
||
//前台已经建立起长链接,取得了客户端ID号;需要绑定到当前用户,并返回用户uid,供服务侧同步绑定校验
|
||
$viaDomain = fmFunc_server_via_domain(); //来路域名
|
||
$viaIP = fmFunc_server_via_ip(); //来路IP
|
||
$timestamp = isset($_FM['timestamp']) ? $_FM['timestamp'] : time();
|
||
|
||
//通过前端GET传入的
|
||
$client_id = isset($dataGet['client_id']) ? $dataGet['client_id'] : 0;
|
||
$accessToken = isset($dataGet['accesstoken']) ? $dataGet['accesstoken'] : 0;
|
||
|
||
//判断accesstoken有效性
|
||
/*
|
||
@有效性规则判断
|
||
*Yii::$app->user->identity->username,Yii::$app->user->identity->id 当前用户账号及id
|
||
*domain 域名匹配
|
||
*expiretime 有效期判断
|
||
*$_FM['apiCert'] 服务器证书
|
||
*/
|
||
$connection = yii::$app->db;
|
||
$sql = "SELECT `username` FROM c_access WHERE accesstoken = :accesstoken AND domain = :domain AND expiretime > :expiretime ORDER BY id ASC";
|
||
$params = array();
|
||
$params[':accesstoken'] = $accessToken;
|
||
$params[':domain'] = $viaDomain;
|
||
$params[':expiretime'] = $timestamp;
|
||
$result = fmFunc_pdo_yii_fetch($connection, $sql, $params);
|
||
if ($result) {
|
||
$username = $result['username'];
|
||
//加载证书文件,但无用户登陆状态
|
||
$cert = $username . '.php';
|
||
if (file_exists($_HI['apiCertPath'] . $cert)) {
|
||
$_FM['apiCert'] = array_merge(include($_HI['apiCertPath'] . $cert));
|
||
}
|
||
}
|
||
$_FM['apiCert']['token'] = $accessToken;
|
||
|
||
//处理POST数据
|
||
$client_type = isset($dataPost['client_type']) ? $dataPost['client_type'] : 'undefined';
|
||
$isWeb = ($client_type == 'web') ? TRUE : FALSE;
|
||
$isApp = ($client_type == 'app') ? TRUE : FALSE;
|
||
$isAppWeb = ($client_type == 'appweb') ? TRUE : FALSE;
|
||
|
||
$group_ids = array();
|
||
|
||
//根据当前用户身份生成可准确识别的用户ID
|
||
$uid = isset($dataPost['uid']) ? $dataPost['uid'] : 'undefined';
|
||
$uid = fmFunc_server_hash_id($uid);
|
||
|
||
$group_id = isset($dataPost['groupid']) ? $dataPost['groupid'] : 0;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
$group_ids[$group_id] = $group_id;
|
||
// client_id与uid绑定
|
||
Gateway::bindUid($client_id, $uid);
|
||
// 加入某个群组(可调用多次加入多个群组)
|
||
Gateway::joinGroup($client_id, $group_id); //当前用户所在的会员组
|
||
|
||
//继续根据创建更多分组
|
||
$do = isset($dataPost['do']) ? $dataPost['do'] : 'undefined';
|
||
$ac = isset($dataPost['ac']) ? $dataPost['ac'] : 'undefined';
|
||
$op = isset($dataPost['op']) ? $dataPost['op'] : 'undefined';
|
||
|
||
if ($isWeb) {
|
||
$type = 'web';
|
||
$group_id = $type . '_' . $do . '_' . $ac . '_' . $op;
|
||
$group_id = $group_pre . $group_pre . fmFunc_server_hash_id($group_id);
|
||
$group_ids[$group_id] = $group_id;
|
||
Gateway::joinGroup($client_id, $group_id);
|
||
|
||
$group_id = $type . '_' . $do . '_' . $ac;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
$group_ids[$group_id] = $group_id;
|
||
Gateway::joinGroup($client_id, $group_id);
|
||
|
||
$group_id = $type . '_' . $do;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
$group_ids[$group_id] = $group_id;
|
||
Gateway::joinGroup($client_id, $group_id);
|
||
|
||
} else {
|
||
$type = 'app';
|
||
$group_id = $type . '_' . $do . '_' . $ac . '_' . $op;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
$group_ids[$group_id] = $group_id;
|
||
Gateway::joinGroup($client_id, $group_id);
|
||
|
||
$group_id = $type . '_' . $do . '_' . $ac;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
$group_ids[$group_id] = $group_id;
|
||
Gateway::joinGroup($client_id, $group_id);
|
||
|
||
$group_id = $type . '_' . $do;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
$group_ids[$group_id] = $group_id;
|
||
Gateway::joinGroup($client_id, $group_id);
|
||
|
||
$group_id = $type;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
$group_ids[$group_id] = $group_id;
|
||
Gateway::joinGroup($client_id, $group_id); //当前用户并入前台用户组
|
||
|
||
if ($isAppWeb) {
|
||
$type = 'appweb';
|
||
$group_id = $type;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
$group_ids[$group_id] = $group_id;
|
||
Gateway::joinGroup($client_id, $group_id); //当前用户并入前台核销用户组
|
||
}
|
||
}
|
||
|
||
//发送反馈消息
|
||
$message = array();
|
||
$message = '棒,客户端绑定成功!';
|
||
|
||
$data = array();
|
||
$data['type'] = 'tips';
|
||
$data['msg'] = $message;
|
||
$data['groupids'] = $group_ids;
|
||
$data = json_encode($data);
|
||
Gateway::sendToClient($client_id, $data);
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* 接收客户端数据
|
||
*/
|
||
public function actionIn()
|
||
{
|
||
$group_pre = 'VCMS-IMMS';
|
||
header('Access-Control-Allow-Origin:*'); //允许任何网站通过ajax发送请求
|
||
// 建立socket连接到内部推送端口
|
||
$client = stream_socket_client('tcp://127.0.0.1:4530');
|
||
|
||
//如果用户已经登陆,uid和群组id存在
|
||
//TBD 构建uid、group_id的生成方式
|
||
$uid = isset($dataPost['uid']) ? $dataPost['uid'] : 0;
|
||
$group_id = isset($dataPost['group']) ? $dataPost['group'] : 0;
|
||
|
||
//$client_id 通过前端传入
|
||
$client_id = isset($dataGet['client_id']) ? $dataGet['client_id'] : 0;
|
||
|
||
// 推送的数据,包含uid字段,表示是给这个uid推送
|
||
$uid = isset(Yii::$app->user->identity->username) ? Yii::$app->user->identity->username : '0';
|
||
$data = array('uid' => $uid, 'msg' => urlencode('嗯,这个是测试用的'));
|
||
|
||
// 发送数据,注意该端口是Text协议的端口,Text协议需要在数据末尾加上换行符
|
||
fwrite($client, json_encode($data) . "\n");
|
||
|
||
// 读取推送结果
|
||
// echo '$client=='.$client;
|
||
//echo fread($client, 8192);
|
||
}
|
||
|
||
/**
|
||
* 向客户端推送消息
|
||
*/
|
||
public function actionOut()
|
||
{
|
||
global $_FM;
|
||
//数据取出方法
|
||
$dataGet = $_FM['get']; //GET进来的参数
|
||
$dataPost = $_FM['post']; //POST进来的参数
|
||
$params = Yii::$app->params;
|
||
header('Access-Control-Allow-Origin:*'); //允许任何网站通过ajax发送请求
|
||
require dirname(__FILE__) . '/_public/plat.php';
|
||
|
||
$group_pre = 'VCMS-IMMS';
|
||
|
||
/*设置REDIS缓存*/
|
||
//初始化$cache = new \Redis();
|
||
$cache = new \Redis();
|
||
$cache->connect($params['redis']['IP'], $params['redis']['PORT']);
|
||
// 先检查是否存在,然后写入并设置有效时间
|
||
$key = 'FmWebSorcketCount';
|
||
$CACHE_PREFIX = 'DACMS';
|
||
$count = 0;
|
||
if ($cache->exists($CACHE_PREFIX . $key)) {
|
||
// 读取
|
||
$count = $cache->get($CACHE_PREFIX . $key);
|
||
//清除
|
||
$cache->delete($CACHE_PREFIX . $key);
|
||
}
|
||
|
||
$cache->set($CACHE_PREFIX . $key, $count + 1);
|
||
$expire = time() + 604800; //一周时间再过期
|
||
$cache->expire($CACHE_PREFIX . $key, $expire);
|
||
|
||
//前台已经建立起长链接,取得了客户端ID号;需要绑定到当前用户,并返回用户uid,供服务侧同步绑定校验
|
||
$viaDomain = fmFunc_server_via_domain(); //来路域名
|
||
$viaIP = fmFunc_server_via_ip(); //来路IP
|
||
$timestamp = isset($_FM['timestamp']) ? $_FM['timestamp'] : time();
|
||
|
||
//通过前端GET传入的
|
||
$client_id = isset($dataGet['client_id']) ? $dataGet['client_id'] : '7f000001b0f400000010';
|
||
$accessToken = isset($dataGet['accesstoken']) ? $dataGet['accesstoken'] : 0;
|
||
|
||
//判断accesstoken有效性
|
||
/*
|
||
@有效性规则判断
|
||
*Yii::$app->user->identity->username,Yii::$app->user->identity->id 当前用户账号及id
|
||
*domain 域名匹配
|
||
*expiretime 有效期判断
|
||
*$_FM['apiCert'] 服务器证书
|
||
*/
|
||
$connection = yii::$app->db;
|
||
$sql = "SELECT `username` FROM c_access WHERE accesstoken = :accesstoken AND domain = :domain AND expiretime > :expiretime ORDER BY id ASC";
|
||
$params = array();
|
||
$params[':accesstoken'] = $accessToken;
|
||
$params[':domain'] = $viaDomain;
|
||
$params[':expiretime'] = $timestamp;
|
||
$result = fmFunc_pdo_yii_fetch($connection, $sql, $params);
|
||
$hasToken = FALSE;
|
||
$hasCert = FALSE;
|
||
if ($result) {
|
||
$username = $result['username'];
|
||
$hasToken = TRUE;
|
||
//加载证书文件,但无用户登陆状态
|
||
$cert = $username . '.php';
|
||
if (file_exists($_HI['apiCertPath'] . $cert)) {
|
||
$_FM['apiCert'] = array_merge(include($_HI['apiCertPath'] . $cert));
|
||
$hasCert = TRUE;
|
||
}
|
||
}
|
||
$_FM['apiCert']['token'] = $accessToken;
|
||
|
||
//处理POST数据
|
||
$client_type = isset($dataPost['client_type']) ? $dataPost['client_type'] : '';
|
||
$msg_type = isset($dataPost['msg_type']) ? $dataPost['msg_type'] : '';
|
||
if (!$msg_type) {
|
||
$msg_type = isset($dataGet['msg_type']) ? $dataGet['msg_type'] : '';
|
||
}
|
||
$isWeb = ($client_type == 'web') ? TRUE : FALSE;
|
||
$isApp = ($client_type == 'app') ? TRUE : FALSE;
|
||
$isAppWeb = ($client_type == 'appweb') ? TRUE : FALSE;
|
||
$msg = isset($dataPost['msg']) ? $dataPost['msg'] : '';
|
||
if (!$msg) {
|
||
$msg = isset($dataGet['msg']) ? $dataGet['msg'] : '';
|
||
}
|
||
|
||
//构造反馈消息
|
||
$data = array();
|
||
$data['type'] = $msg_type;
|
||
$data['msg'] = $msg;
|
||
|
||
if (isset($dataGet['debug'])) {
|
||
//向全体推送数据
|
||
$data['msg'] = empty($data['msg']) ? '第' . $count . '次测试群发' : $data['msg'];
|
||
$count++;
|
||
$data = json_encode($data);
|
||
Gateway::sendToAll($data);
|
||
return;
|
||
}
|
||
|
||
$data = json_encode($data);
|
||
|
||
//根据情况发送消息
|
||
switch ($hasToken) {
|
||
case TRUE:
|
||
//根据当前用户身份生成可准确识别的用户ID
|
||
$uid = isset($dataPost['uid']) ? $dataPost['uid'] : '';
|
||
if ($uid) {
|
||
$uid = fmFunc_server_hash_id($uid);
|
||
Gateway::sendToUid($uid, $data);
|
||
}
|
||
|
||
//有证书时,可继续下一步的推送
|
||
if (!$hasCert) {
|
||
break; //无证书,不再继续
|
||
}
|
||
|
||
//已指派分组时
|
||
$group_id = isset($dataPost['group']) ? $dataPost['group'] : 0;
|
||
if ($groud_id) {
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
Gateway::sendToGroup($group_id, $data);
|
||
break; //执行后结束此次推送
|
||
}
|
||
|
||
//根据创建更多分组
|
||
$do = isset($dataPost['do']) ? $dataPost['do'] : '';
|
||
$ac = isset($dataPost['ac']) ? $dataPost['ac'] : '';
|
||
$op = isset($dataPost['op']) ? $dataPost['op'] : '';
|
||
|
||
if ($client_type) {
|
||
if ($isWeb) {
|
||
$type = 'web';
|
||
} else if ($isAppWeb) {
|
||
$type = 'appweb';
|
||
} else {
|
||
$type = 'app';
|
||
}
|
||
if ($do) {
|
||
if ($ac) {
|
||
if ($op) {
|
||
$group_id = $type . '_' . $do . '_' . $ac . '_' . $op;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
Gateway::sendToGroup($group_id, $data);
|
||
} else {
|
||
$group_id = $type . '_' . $do . '_' . $ac;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
Gateway::sendToGroup($group_id, $data);
|
||
}
|
||
} else {
|
||
$group_id = $type . '_' . $do;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
Gateway::sendToGroup($group_id, $data);
|
||
}
|
||
} else {
|
||
$group_id = $type;
|
||
$group_id = $group_pre . fmFunc_server_hash_id($group_id);
|
||
Gateway::sendToGroup($group_id, $data);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case FALSE;
|
||
//只发送给指定客户端
|
||
Gateway::sendToClient($client_id, $data);
|
||
break;
|
||
}
|
||
|
||
// 以下是调用示例,接口与GatewayWorker环境的接口一致
|
||
// 接口具体使用方法见《Lib\Gateway类提供的接口》一章
|
||
// 注意除了不支持sendToCurrentClient和closeCurrentClient方法
|
||
// 其它方法都支持
|
||
//Gateway::sendToAll($data);
|
||
//Gateway::sendToClient($client_id, $data);
|
||
//Gateway::closeClient($client_id);
|
||
//Gateway::isOnline($client_id);
|
||
//Gateway::bindUid($client_id, $uid);
|
||
//Gateway::isUidOnline($uid);
|
||
//Gateway::getClientIdByUid($uid);
|
||
//Gateway::unbindUid($client_id, $uid);
|
||
//Gateway::sendToUid($uid, $data);
|
||
//Gateway::joinGroup($client_id, $group);
|
||
//Gateway::sendToGroup($group, $data);
|
||
//Gateway::leaveGroup($client_id, $group);
|
||
//Gateway::getClientCountByGroup($group);
|
||
//Gateway::getClientSessionsByGroup($group);
|
||
//Gateway::getAllClientCount();
|
||
//Gateway::getAllClientSessions();
|
||
//Gateway::setSession($client_id, $session);
|
||
//Gateway::updateSession($client_id, $session);
|
||
//Gateway::getSession($client_id);
|
||
|
||
}
|
||
} |