<?php
/**
* APP消息推送类
* 默认为极光推送
* @update 支持同时向多个app推送 sugang 2014-7-19
* @update 增加个推www.getui.com sugang 2015-1-5
* 增加多平台推送,同时推送jpush和getui 2014-1-6
* @update 增加通知和消息的转化和开关,如把个推通知转到消息去,即用消息推送。如关闭个推通知。 sugang 2014-1-7
* @update 优化一些函数和调用方式 sugang 2015-3-28
* @update 增加appId,个推推送时需要指定 sugang 2015-7-25
**/
class AppPush {
private $appId; // App Id
private $appKey; // App Key
private $secretKey; // Secret Key
private $initParams; // 其它参数
private $pushType = ''; // 推送类型,通知或消息
private $pushPlatUse = 'jpush'; // 当前使用的api平台
private $productCode = 'yl1001'; // 当前使用的产品
private $pushPlatArr = array('jpush','baidu','yl1001','getui'); // 使用的平台
private $pushAppNum = 0; // 推送多个app时的当前推送
private $pushAppNumTotal = 0; // 推送多个app时的推送总次数
private $pushPlatNum = 0; // 当前推送的平台编号
private $pushPlatNumTotal = 0; // 当前推送的平台总数
private $pushPlatUses = ''; // pushPlateUse记录当前使用的平台,pushPlatUsers记录需要推送的平台
private $debug = false; // 是否开启调试信息
// 个推平台的参数
private $gt_host = 'http://sdk.open.api.igexin.com/apiex.htm';
private $gt_appId = ''; // 已使用appId替换,应为个推推送多个app时,每个appId不同
// 不同平台,使用不同的字符集
private $pushCharset = array(
'jpush' => 'utf-8',
'baidu' => 'utf-8',
'yl1001' => 'gbk',
'getui' => 'utf-8',
);
// 不同平台,不同产品的key
private $keyArr = array(
'jpush' => array(
'yl1001' => array(
array(
'app_key' => '',
'secret_key'=> '',
),
array( // 只推送给ios
'app_key' => '',
'secret_key'=> '',
),
),
'moyuan' => array(
'app_key' => '',
'secret_key'=> '',
),
),
'baidu' => array(
'yl1001' => array(
'app_key' => '',
'secret_key'=> '',
),
),
'getui' => array(
'yl1001' => array(
array(
'app_id' => '', // AppID
'app_key' => '', // AppKey
'secret_key'=> '', // MasterSecret
),
// array( // 用于测试app,不用上传到线上
// 'app_id' => '',
// 'app_key' => '',
// 'secret_key'=> '', // MasterSecret
// )
)
),
);
/**
* 构造函数,初始化传入的参数、推送的key、推送类
* @param String $pushPlatUse
* @param String $appKey
* @param String $secretKey
* @param Array $initParams
*/
public function __construct($initParams = array()) {
// 参数设置
if ( $initParams['pushPlatUse'] ) {
$this->pushPlatUse = $initParams['pushPlatUse'];
}
if ( $initParams['productCode'] ) {
$this->productCode = $initParams['productCode'];
}
if ( $initParams['appId'] ) {
$this->appId = $initParams['appId'];
}
if ( $initParams['appKey'] ) {
$this->appKey = $initParams['appKey'];
}
if ( $initParams['secretKey'] ) {
$this->secretKey = $initParams['secretKey'];
}
// 调试
if( $_SESSION['dugabcd'] == 1 ){
$this->debug = true;
}
if ( isset($initParams['debug']) ) {
$this->debug = $initParams['debug'];
}
unset($initParams['pushPlatUse']);
unset($initParams['productCode']);
unset($initParams['appKey']);
unset($initParams['secretKey']);
// 其他参数
if ( $initParams ) {
$this->initParams = $initParams;
}
// 处理多平台推送
if ( $this->pushPlatUse ) {
$this->pushPlatUses = explode(',', $this->pushPlatUse);
$this->pushPlatUses = array_unique($this->pushPlatUses);
// 设置当前使用的平台,因为传进来的时候可能是多个平台
$this->pushPlatUse = $this->pushPlatUses[0];
$this->pushPlatNumTotal = count($this->pushPlatUses);
}
// 初始化key
$this->initPushKey();
// 初始化推送类
$this->initPushClass();
}
/**
* 检查当前使用的平台是否合法
**/
public function checkPushPlat() {
if ( !array_key_exists($this->pushPlatUse, $this->pushPlatArr) ) {
return false;
}
return true;
}
/**
* 初始化key,key的定义见变量$keyArr
**/
public function initPushKey() {
if ( $this->pushPlatUse && $this->productCode ) {
// 是否存在定义的平台
if ( array_key_exists($this->pushPlatUse, $this->keyArr) ) {
// 是否存在定义的产品
if ( array_key_exists($this->productCode, $this->keyArr[$this->pushPlatUse]) ) {
$keyArr = $this->keyArr[$this->pushPlatUse][$this->productCode];
// key可能是二维数组,表示需要推送给多个app
if ( !$keyArr['app_key'] && is_array($keyArr[$this->pushAppNum]) ) {
$this->pushAppNumTotal = count($keyArr);
// 初始化当前需要推送的app的key
$this->appId = $keyArr[$this->pushAppNum]['app_id'];
$this->appKey = $keyArr[$this->pushAppNum]['app_key'];
$this->secretKey= $keyArr[$this->pushAppNum]['secret_key'];
} else {
$this->appId = $keyArr['app_id'];
$this->appKey = $keyArr['app_key'];
$this->secretKey= $keyArr['secret_key'];
}
}
}
}
}
/**
* 加载不同平台需要的类
* @notice 切换不同的平台推送时需要调用
**/
public function initPushClass() {
switch( $this->pushPlatUse ) {
case 'jpush':
// 极光推送
include_once dirname(__FILE__) . '/lib/jpush/JPushClient.php';
break;
case 'baidu':
// 百度云推送
include_once dirname(__FILE__) . '/lib/baidu/Channel.class.php';
break;
case 'yl1001':
// 一览推送
include_once dirname(__FILE__) . '/lib/yl1001/Yl1001Push.php';
break;
case 'getui':
// 个推
include_once dirname(__FILE__) . '/lib/getui/IGt.Push.php';
break;
}
}
/**
* 初始化推送对象
* 处理initParams的其他参数,如离线时长、设备类型
* @notice 切换不同的平台推送时需要调用
**/
public function initPushObject() {
switch( $this->pushPlatUse ) {
case 'jpush':
if ( !isset($this->initParams['time_to_live']) ) {
$this->initParams['time_to_live'] = 86400; // 离线时长:1天
}
if ( !isset($this->initParams['platform']) ) {
$this->initParams['platform'] = ''; // android,ios
}
if ( !isset($this->initParams['apns_production']) ) {
$this->initParams['apns_production']= false; // APNS 通知发送环境 false开发环境 true生产环境
}
$pushObj = new JPushClient($this->appKey,$this->secretKey, $this->initParams['time_to_live'], $this->initParams['platform'], $this->initParams['apns_production']);
break;
case 'baidu':
if ( !isset($this->initParams['arr_curlOpts']) ) {
$this->initParams['arr_curlOpts'] = array();
}
$pushObj = new Channel($this->appKey, $this->secretKey, $this->initParams['arr_curlOpts']);
break;
case 'yl1001':
if ( !isset($this->initParams['platform']) ) {
$this->initParams['platform'] = ''; // android,ios
}
$pushObj = new Yl1001Push($this->initParams);
break;
case 'getui':
if ( !isset($this->initParams['time_to_live']) ) {
$this->initParams['time_to_live'] = 86400 * 1000; // 离线时长:1天,个推使用的毫秒
}
if ( !isset($this->initParams['platform']) ) {
$this->initParams['platform'] = ''; // android,ios
}
$pushObj = new IGeTui($this->gt_host,$this->appKey,$this->secretKey);
break;
}
return $pushObj;
}
/**
* 初始化默认参数
* 默认为广播
* @params array 用户参数参数
* @extras array 扩展参数列表
**/
public function initPushParam(&$params, &$extras) {
$default_params = array();
$default_extras = array();
$params = is_array($params) ? $params : array();
$extras = is_array($extras) ? $extras : array();
switch( $this->pushPlatUse ) {
case 'jpush':
// 极光推送
$default_params['receiver_type'] = 4; // 接收者类型:4广播
$default_params['receiver_value'] = ' '; // 广播不用填写
$default_params['sendno'] = time(); // 发送编号(最大支持32位正整数(即 4294967295 ))
$default_params['send_description'] = ''; // 描述此次发送调用
$default_params['override_msg_id'] = ''; // 覆盖的上一条消息的 ID
if( $this->initParams['platform']=='' || strpos($this->initParams['platform'], 'ios')!==false ){
// ios处理
$default_extras['ios']['badge'] = 1;
$default_extras['ios']['sound'] = 'default';
}
break;
case 'baidu':
// 百度云推送
break;
case 'getui':
// 个推
if( $this->initParams['platform']=='' || strpos($this->initParams['platform'], 'ios')!==false ){
// ios处理
$default_extras['ios']['badge'] = 1;
$default_extras['ios']['sound'] = 'default';
}
break;
}
$params = $params + $default_params;
$extras = $extras + $default_extras;
}
/**
* 通过此方法判断是否需要多平台推送
* @notice 该方法判断时必须保证当前平台下面的多个app推送完成后,才能进行下一个平台的推送
* @author sugang
* @date 2015-1-6
**/
public function multiPlatPush() {
// 当前平台下的多个App推送是否完成,如果没完成不能进入下一个平台的推送
if ( $this->pushAppNum != ($this->pushAppNumTotal - 1) ) {
return false;
}
if ( $this->pushPlatNum < ($this->pushPlatNumTotal - 1) ) {
// 初始化不同平台需要的东西(key,pushObj等)
$this->pushPlatNum++; // 切换下一个平台
$this->pushAppNum = 0; // 切换平台后,app推送从头开始
// 定义当前使用的平台
$this->pushPlatUse = $this->pushPlatUses[$this->pushPlatNum];
// class
$this->initPushClass();
// Key
$this->initPushKey();
// Object
$this->initPushObject();
return true;
}
return false;
}
/**
* 通过此方法判断是否需要推送给多个app(重构之前的功能、之前没有进行封装)
* @author sugang
* @date 2015-1-7
**/
public function multiAppPush() {
if ( $this->pushAppNum < ($this->pushAppNumTotal - 1) ) {
$this->pushAppNum++; // 切换下一个app
// Key
$this->initPushKey(); // 同一平台的不同app推送,只需重新初始化Key
return true;
}
return false;
}
/**
* 推送通知或消息时需要重置推送平台,推送app
* @notice 当同时推送通知和消息时,通知推送完毕后,需要重置推送平台和app(从头开始再依次推送)
* @author sugang
* @date 2015-7-29
**/
public function multiTypePush() {
// 多平台,多app推送完了,表示此事通知或者消息通知完毕了,要消息或通知了
if ( $this->pushAppNum == ($this->pushAppNumTotal - 1) && $this->pushPlatNum == ($this->pushPlatNumTotal - 1) ) {
$this->pushAppNum = 0;
$this->pushPlatNum = 0;
// 定义当前使用的平台
$this->pushPlatUse = $this->pushPlatUses[$this->pushPlatNum];
// class
$this->initPushClass();
// Key
$this->initPushKey();
// Object
$this->initPushObject();
}
}
/**
* 输出调试信息,方便调试
* @author sugang
* @date 2015-1-7
**/
public function debugInfo() {
if ( $this->debug ) {
echo '<br/>当前推送的信息---';
echo '<br/>推送类型:' . $this->pushType;
echo '<br/>推送平台:' . $this->pushPlatUse;
echo '<br/>推送产品:' . $this->productCode;
echo '<br/>推送app序号(从0开始):' . $this->pushAppNum;
echo '<br/>当前使用的Key:' . $this->appId . ' / ' . $this->appKey . ' / ' . $this->secretKey;
echo '<br/><br/>';
}
}
/**
* 编码转换,默认输入编码为gbk
**/
private function changeCode($param1,$param2) {
$argList = func_get_args();
$paramArr = array();
switch($this->pushCharset[$this->pushPlatUse]) {
case 'utf-8':
foreach($argList as $arg) {
$paramArr[] = iconv('gbk', 'utf-8', $arg);
}
break;
case 'gbk':
default:
foreach($argList as $arg) {
$paramArr[] = $arg;
}
break;
}
return $paramArr;
}
/**
* 某个时间段不进行推送
* @notice 注意,实际的推送方法中返回值需要做处理。直接在该方法中返回是可以避免推送,但是有些情况是:推送完后需要记录在yl_app_push表中,该记录的状态是根据推送返回结果来判断的,如果没有返回结果,默认的推送记录状态为“未推送”,在定时推送程序中还会进行推送。
* @author sugang
* @date 2015-4-25
**/
public function filterTimePush() {
$hour = date('H');
// 23点开始,早上8点结束
if ( $hour<8 || $hour>=23 ) {
return false;
}
return true;
}
/**
* 推送通知
* @param $title 推送通知的标题(客户端接收的内容)
* @param $content 推送通知的内容(客户端接收的内容)
* @param $params 推送的配置参数
* @param $extras 推送的扩展内容(客户端接收的内容)
**/
public function sendNotice($title, $content, $params, $extras = array()) {
if ( !$this->filterTimePush() ) {
return array('status'=>'FORBID');
}
$this->pushType = 'notice';
/// 用于多次推送
$_title = $title;
$_content = $content;
$_params = $params;
$_extras = $extras;
/
// 编码转换
list($title, $content) = $this->changeCode($title, $content);
$pushObj = $this->initPushObject();
$this->initPushParam($params, $extras);
switch( $this->pushPlatUse ) {
case 'jpush':
// 过滤特殊字符
$title = $this->filterSpecialChar($title);
$content= $this->filterSpecialChar($content);
$extras = $this->filterSpecialChar($extras);
// 获取合适长度的内容
$content= $this->getAppropriateLen($title, $content, $params, $extras, '1');
if( $params['receiver_type'] == '4' ) {
// 广播
$result_tmp = $pushObj->sendNotification($title, $content, $params, $extras);
$result = $this->formatResult($result_tmp);
} else {
if( $params['receiver_type']=='2' ) {
// 标签tag,一次支持10个标签
$len = 10;
} else if( $params['receiver_type']=='3' || $params['receiver_type']=='5' ){
// 别名alias和RegistrationID,一次支持1000个
$len = 1000;
}
$receiverStr = $params['receiver_value'];
$receiverArr = $this->getAliasStringByStr($receiverStr, $len);
$result = array(
'status' => 'FAIL',
'code' => 0,
'status_desc' => '',
'info' => '',
);
foreach( $receiverArr as $receiver ){
$params['receiver_value'] = $receiver;
$result_tmp = $pushObj->sendNotification($title, $content, $params, $extras);
$result_tmp = $this->formatResult($result_tmp);
if( $result_tmp['status']=='OK' && $result['status']=='FAIL' ){
$result['status'] = 'OK';
$result['code'] = 200;
}
$result['info'][] = $result_tmp;
}
}
break;
case 'baidu':
// 推送类型,取值范围为:1~3 1:单个人 2:一群人 3:所有人
$push_type = 3;
// 设备类型,取值范围为:1~5 1:浏览器设备;2:PC设备;3:Andriod设备;4:iOS设备;5:Windows Phone设备;
$optional[Channel::DEVICE_TYPE] = 3;
// 消息类型0:消息 1:通知
$optional[Channel::MESSAGE_TYPE]= 1;
//通知类型的内容必须按指定内容发送,示例如下:
$message = '{
"title": "test_push",
"description": "open url",
"notification_basic_style":7,
"open_type":1,
"url":"http://www.baidu.com"
}';
// 消息标识
$message_key= time();
$result = $pushObj->pushMessage( $push_type, $message, $message_key, $optional );
$result = $this->formatResult($result);
break;
case 'yl1001':
$title = $this->filterSpecialChar($title); // 过滤特殊字符
$content = $this->filterSpecialChar($content);// 过滤特殊字符
$result_tmp = $pushObj->send_note_by_user_id($title, $content, $params, $extras);
$result_tmp = $pushObj->send_note_by_device_token($title, $content, $params, $extras);
$result = array(
'status' => 'FAIL',
'code' => 0,
'status_desc' => '',
'info' => '',
);
foreach($result_tmp as $result_device){
foreach($result_device as $val){
$re_tmp = $this->formatResult($val);
$result['info'][] = $re_tmp;
if( $re_tmp['status']=='OK' ){
$result['status'] = 'OK';
$result['code'] = 200;
}
}
}
break;
case 'getui':
// 从极光推送中获取个推的参数(之前的程序使用极光)
$this->gtParamFromJpush($params, $extras);
$templateType = $this->gtPushStatus('notice');
if ( $templateType ) {
$result_tmp = $this->gtPushMessage($params['gt_target'], $templateType, array(
'title' => $title,
'content' => $content,
'extras' => $extras,
),$pushObj);
$result = $this->formatResult($result_tmp);
}
break;
}
// 输出本次推送的调试信息
$this->debugInfo();
// 是否进入下一个app推送
if ( $this->multiAppPush() ) {
$this->sendNotice($_title, $_content, $_params, $_extras);
}
// 是否进入下一个平台推送
if ( $this->multiPlatPush() ) {
$this->sendNotice($_title, $_content, $_params, $_extras);
}
// 所有平台,所有app的通知是否推送完毕
$this->multiTypePush();
return $result;
}
/**
* 推送消息(仅Android设备支持)
* @param $title 推送通知的标题(客户端接收的内容)
* @param $content 推送通知的内容(客户端接收的内容)
* @param $params 推送的配置参数
* @param $extras 推送的扩展内容(客户端接收的内容)
* @update sugang 2015-7-20 之前推送完后,没有调用下次推送
**/
public function sendMessage($title, $content, $params, $extras = array()) {
if ( !$this->filterTimePush() ) {
return array('status'=>'FORBID');
}
$this->pushType = 'message';
// 多次推送通知后,消息只推送一个
// $this->pushAppNum = 0;
// $this->initPushKey();
//
/// 用于多次推送
$_title = $title;
$_content = $content;
$_params = $params;
$_extras = $extras;
// 编码转换
list($title, $content) = $this->changeCode($title, $content);
$pushObj = $this->initPushObject();
$this->initPushParam($params, $extras);
switch( $this->pushPlatUse ) {
case 'jpush':
// 过滤特殊字符
$title = $this->filterSpecialChar($title);
$content= $this->filterSpecialChar($content);
$extras = $this->filterSpecialChar($extras);
if( $params['receiver_type'] == '4' ){
// 广播
$result_tmp = $pushObj->sendCustomMessage($title, $content, $params, $extras);
$result = $this->formatResult($result_tmp);
} else {
if( $params['receiver_type']=='2' ){
// 标签tag,一次支持10个标签
$len = 10;
} else if( $params['receiver_type']=='3' || $params['receiver_type']=='5' ){
// 别名alias和RegistrationID,一次支持1000个
$len = 1000;
}
$receiverStr = $params['receiver_value'];
$receiverArr = $this->getAliasStringByStr($receiverStr, $len);
$result = array(
'status' => 'FAIL',
'code' => 0,
'status_desc' => '',
'info' => '',
);
foreach( $receiverArr as $receiver ){
$params['receiver_value'] = $receiver;
$result_tmp = $pushObj->sendCustomMessage($title, $content, $params, $extras);
$result_tmp = $this->formatResult($result_tmp);
if( $result_tmp['status']=='OK' && $result['status']=='FAIL' ){
$result['status'] = 'OK';
$result['code'] = 200;
}
$result['info'][] = $result_tmp;
}
}
break;
case 'baidu':
break;
case 'getui':
// 从极光推送中获取个推的参数(之前的程序使用极光)
$this->gtParamFromJpush($params, $extras);
$templateType = $this->gtPushStatus('message');
if ( $templateType ) {
$result_tmp = $this->gtPushMessage($params['gt_target'],$templateType, array(
'title' => $title,
'content' => $content,
'extras' => $extras,
), $pushObj);
$result = $this->formatResult($result_tmp);
}
break;
}
$this->debugInfo();
// 是否进入下一个app推送
if ( $this->multiAppPush() ) {
$this->sendMessage($_title, $_content, $_params, $_extras);
}
// 是否进入下一个平台推送
if ( $this->multiPlatPush() ) {
$this->sendMessage($_title, $_content, $_params, $_extras);
}
// 所有平台,所有app的通知是否推送完毕
$this->multiTypePush();
return $result;
}
/**
* 统一处理返回值
**/
public function formatResult($result) {
switch( $this->pushPlatUse ) {
case 'jpush':
$status = 'FAIL';
$code = $result->getCode();
$status_desc = $result->getMessage();
if ($code == 0) { // 正确
$status = 'OK';
$code = 200;
}
$info = array(
'msgId' => $result->getMesId(),
'sendno' => $result->getSendno(),
'code' => $result->getCode(),
'message' => $result->getMessage(),
'responseContent' => $result->getResponseContent(),
);
break;
case 'baidu':
$status = 'FAIL';
$status_desc = '';
if ( $result['request_id'] ) {
$status = 'OK';
$code = 200;
}
$info = $result;
break;
case 'yl1001':
$status = 'FAIL';
$status_desc = '';
$code = 0;
$info = array();
if( $result==1 ){
$status = 'OK';
$code = 200;
}
break;
case 'getui':
$status = 'FAIL';
$code = 0;
$status_desc = $result['status'];
$info = array();
if ($result['result'] == 'ok') { // 正确
$status = 'OK';
$code = 200;
if ( $result['taskId'] ) {
$info['taskId'] = $result['taskId'];
}
if ( $result['contentId'] ) {
$info['contentId'] = $result['contentId'];
}
} else {
$status_desc = $result['result'];
}
break;
}
$result = array(
'status' => $status,
'code' => $code,
'status_desc' => $status_desc,
'info' => $info,
);
return $result;
}
/**
* 过滤特殊字符
* @param $str string/array 需要过滤的字符
* @param $exclude string/array 不过滤的字符串
**/
public function filterSpecialChar($str, $exclude = null) {
if( empty($str) ){
return $str;
}
// 非必须去除的特殊字符
$search_char = array(' ', '&', '"', ''', '“', '”', '—', '<', '>', '·', '…');
$replace_char = array(' ', '&', '"', "'", '“', '”', '—', '<', '>', '·', '…');
if( $exclude ) {
// 不过滤字符
if ( !is_array($exclude) ) {
$exclude = explode(',', $exclude);
}
foreach( $exclude as $val ){
$search_key = array_search($val, $search_char);
if( $search_key !== false ){
unset( $search_char[$search_key] );
unset( $replace_char[$search_key] );
}
}
}
// 必须去掉的字符
$search_char_must = array("\r", "\n", "\r\n", ';', '&');
$replace_char_must = array('', '', '', ";", '');
$search_char = array_merge($search_char, $search_char_must);
$replace_char = array_merge($replace_char, $replace_char_must);
// 进行替换
if ( is_array($str) ) {
foreach($str as $k=>$v) {
$str[$k] = $this->filterSpecialChar($v,$exclude);
}
} else {
$str = str_replace($search_char, $replace_char, $str);
}
return $str;
}
/**
* 获取合适长度的内容
* @notice $content和$extras内容过长时,对$content进行截取
**/
public function getAppropriateLen($title, $content, $params, $extras, $type){
switch( $this->pushPlatUse ) {
case 'jpush':
if( $type == '1' ){
// 通知类型, 长度不超过220字节($content和$extras的总和)
$content_len = strlen($content);// 内容的长度
$extras_len = strlen(json_encode($extras));// 扩展内容的长度
$cut_len = $extras_len + $content_len - 220; // 要剪切的字节长度
if( $cut_len > 0 ){
// 如果cut_len值大于0,则表示内容需要截取
$str = mb_strcut($content, 0, $content_len-$cut_len, 'utf-8');
} else {
$str = $content;
}
} else {
// 消息类型,不得超过1000个字节
}
break;
case 'baidu':
break;
case 'getui':
if ( $type = '3' ) { // apns 256限制
$str = mb_strcut($content, 0, 150, 'utf-8');
}
break;
}
return $str;
}
/**
* 截取extras和content
**/
public function getAppropriateExtras($title, &$content, $params, &$extras, $type, $cut_arr){
switch( $this->pushPlatUse ) {
case 'jpush':
if( $this->initParams['platform']=='' || strpos($this->initParams['platform'], 'ios')!==false ){
// ios处理
$extras['ios'] = array(
'badge' => 1,
'sound' => 'default'
);
}
if( $this->pushCharset['jpush']=='utf-8' ){
if( !$this->checkStringIsUtf8($content) ){
$content = iconv('gbk', 'utf-8', $content);
$content_to_gbk = true;
}
foreach ($extras as $key => $value) {
if( !$this->checkStringIsUtf8($value) ){
$extras[$key] = iconv('gbk', 'utf-8', $value);
$extras_to_gbk = true;
}
}
}
if( $type == '1' ){
// 通知类型, 长度不超过220字节
// 计算长度
$content_len = strlen($content);// 内容的长度
$extras_len = strlen(json_encode($extras));// 扩展内容的长度
$cut_len = $extras_len + $content_len - 220; // 要剪切的字节长度
if( $cut_len > 0 ){
// 如果cut_len值大于0,则表示内容需要截取
if( !empty($cut_arr) ){
$cut_arr_count = count($cut_arr);
$e_val_len_c = ceil( $cut_len/$cut_arr_count ); // 如果传入多个可截取值,则平均截取
// $e_val_len_c = $cut_arr_count==1 ? ceil( $cut_len/5*4 ) : $e_val_len_c;
foreach ($cut_arr as $key => $value) {
if( $cut_len<=0 ){
break;
}
$e_val_len = strlen($extras[$value]);
$extras[$value] = mb_strcut($extras[$value], 0, abs($e_val_len-$e_val_len_c)-1, 'utf-8').'...';
$cut_len -= $e_val_len_c;// 剩余要截取的长度
}
}
}
} else {
// 消息类型,
}
if( $this->pushCharset['jpush']=='utf-8' ){
if( $this->checkStringIsUtf8($content) && $content_to_gbk==true ){
$content = iconv('utf-8', 'gbk', $content);
}
foreach ($extras as $key => $value) {
if( $this->checkStringIsUtf8($value) && $extras_to_gbk==true){
$extras[$key] = iconv('utf-8', 'gbk', $value);
}
}
}
unset($extras['ios']);
break;
case 'baidu':
break;
}
}
/**
* 剪切alias数组长度,默认1000个alias为一个长度。
*/
public function getAliasStringByStr($str, $len = 1000) {
if ( empty($str) ) {
return array();
}
if ( !is_array($str) ) {
$aliasArr = explode(',', $str);
}
$aliasArr = array_unique($aliasArr);
$aliasArr = array_filter($aliasArr);
$aliasArr = array_chunk($aliasArr, $len);
$strArr = array();
foreach( $aliasArr as $data ) {
$strArr[] = implode(',', $data);
}
return $strArr;
}
/**
* 判断字符串是否是utf-8编码
**/
public function checkStringIsUtf8($str) {
$len = strlen($str);
for($i = 0; $i < $len; $i++) {
$c = ord($str[$i]);
if ($c > 128) {
if (($c > 247)) return false;
elseif ($c > 239) $bytes = 4;
elseif ($c > 223) $bytes = 3;
elseif ($c > 191) $bytes = 2;
else return false;
if (($i + $bytes) > $len) return false;
while ($bytes > 1) {
$i++;
$b = ord($str[$i]);
if ($b < 128 || $b > 191) return false;
$bytes--;
}
}
}
return true;
}
/Start 个推方法
/**
* 根据接收者调用不同的推送方法
* @param $targets string/array 接收者
* @param $templateType string 模板的类型
* @param $templateParam array 生成模板时的参数
* @author sugang
* @date 2015-1-6
**/
public function gtPushMessage($targets, $templateType, $templateParam = array(), $pushObj) {
// 通过接收人判断推送方式
if ( $targets == '0' ) {
// 广播
$type = 'app';
} else {
if ( !is_array($targets) ) {
$targets = explode(',', $targets);
}
if ( count($targets) == 1 ) {
$type = 'single';
} else {
$type = 'list';
}
}
// 不同的推送方法
if ( $type == 'app' ) {
$message = new IGtAppMessage();
} else if ( $type == 'list' ) {
$message = new IGtListMessage();
} else if ( $type == 'single' ){
$message = new IGtSingleMessage();
}
$template = $this->gtTemplateGenerate($templateType, $templateParam);
$message->set_isOffline(true); //是否离线
$message->set_offlineExpireTime(3600*12*1000); //离线时间
$message->set_data($template); //设置推送消息类型
$message->set_PushNetWorkType(0); //设置是否根据WIFI推送消息,1为wifi推送,0为不限制推送
if ( is_null($pushObj) || !($pushObj instanceof IGeTui) ) {
$pushObj = new IGeTui($this->gt_host,$this->appKey,$this->secretKey);
}
if ( $type == 'single' ) {
$targetList = $this->gtTargetGenerate($targets);
$pushResult = $pushObj->pushMessageToSingle($message, $targetList[0]);
} else if ( $type == 'list' ) {
$targetList = $this->gtTargetGenerate($targets);
$contentId = $pushObj->getContentId($message);
$pushResult = $pushObj->pushMessageToList($contentId, $targetList);
} else if ( $type == 'app' ) {
$message->set_appIdList(array($this->appId));
// $message->set_phoneTypeList(array('ANDROID')); // 只有薪闻是广播,暂时先禁用 sugang 2015-7-7
// $message->set_provinceList(array('浙江','北京','河南'));
// $message->set_tagList(array('开心'));
$pushResult = $pushObj->pushMessageToApp($message);
}
return $pushResult;
}
/**
* 生成对应的推送模板
* @param $type string 模板类型
* @param $params array 各个模板需要的参数(此处应该要考虑默认值)
* @author sugang
* @date 2015-1-6
**/
public function gtTemplateGenerate($type, $params = array()) {
$title = $params['title'];
$content = $params['content'];
$logo = $params['logo'];
$url = $params['url'];
// 透传内容
$extras = array();
if ( $params['extras'] ) {
$extras = $params['extras'];
}
$extras['title'] = $title;
$extras['content'] = $content;
$extras_json = json_encode($extras);
switch( $type ) {
case 'notice':
$template = new IGtNotificationTemplate();
$template->set_appId($this->appId); //应用appid
$template->set_appkey($this->appKey); //应用appkey
$template->set_transmissionType(2); //透传消息类型,1启动应用2等待(不启动应用)
$template->set_transmissionContent($extras_json); //透传内容
$template->set_title($title); //通知栏标题
$template->set_text($content); //通知栏内容
$template->set_logo($logo); //通知栏logo
$template->set_isRing(true); //是否响铃
$template->set_isVibrate(true); //是否震动
$template->set_isClearable(true); //通知栏是否可清除
break;
case 'link':
$template = new IGtLinkTemplate();
$template ->set_appId($this->appId);
$template ->set_appkey($this->appKey);
$template ->set_title($title);
$template ->set_text($content);
$template ->set_logo($logo);
$template ->set_isRing(true);
$template ->set_isVibrate(true);
$template ->set_isClearable(true);
$template ->set_url($url); //打开连接地址
break;
case 'download':
$template = new IGtNotyPopLoadTemplate();
$template ->set_appId($this->appId);
$template ->set_appkey($this->appKey);
//通知栏
$template ->set_notyTitle($title); //通知栏标题
$template ->set_notyContent($content); //通知栏内容
$template ->set_notyIcon($logo); //通知栏logo
$template ->set_isBelled(true); //是否响铃
$template ->set_isVibrationed(true); //是否震动
$template ->set_isCleared(true); //通知栏是否可清除
//弹框
$template ->set_popTitle($params['pop_title']); //弹框标题
$template ->set_popContent($params['pop_content']); //弹框内容
$template ->set_popImage($params['pop_image']); //弹框图片
$template ->set_popButton1("下载"); //左键
$template ->set_popButton2("取消"); //右键
//下载
$template ->set_loadIcon($params['load_icon']); //下载图标
$template ->set_loadTitle($params['load_title']); //下载标题
$template ->set_loadUrl($params['load_url']); //下载地址
$template ->set_isAutoInstall(false); //是否自动安装
$template ->set_isActived(true); //安装完成后是否自动启动应用程序
break;
case 'message':
$template = new IGtTransmissionTemplate();
$template->set_appId($this->appId);
$template->set_appkey($this->appKey);
$template->set_transmissionType(2);
$template->set_transmissionContent($extras_json); //透传内容
// ios特殊处理
$payload = array('type'=>$extras['type']);
if ( $extras['ios']['payload'] && is_array($extras['ios']['payload']) ) {
$payload = array_merge($payload, $extras['ios']['payload']);
}
$payload = json_encode($payload);
$content = $this->getAppropriateLen($title, $content, $params, $extras, '3');
// ios声音特殊处理
$sound = 'default';
if ( $extras['ios']['sound'] ) {
$sound = $extras['ios']['sound'];
}
$template->set_pushInfo("","1","",$sound,$payload,$content,"","");
// $template->set_pushInfo("actionLocKey","badge","message","sound","payload","locKey","locArgs","launchImage");
break;
}
return $template;
}
/**
* 生成接收方
* @param $targets string/array 接收者标识,可以是客户端ID或者别名
* @type $type string $targets标识的类型,client表示传的客户端ID,alias表示传的别名
* @author sugang
* @date 2015-1-6
**/
public function gtTargetGenerate($targets, $type = 'alias') {
$targetList = array();
if ( !is_array($targets) ) {
$targets = explode(',', $targets);
}
foreach( $targets as $data ) {
$target = new IGtTarget();
$target->set_appId($this->appId);
if ( $type == 'client' ) {
$target->set_clientId($data);
} else if ( $type == 'alias' ) {
$target->set_alias($data);
}
$targetList[] = $target;
}
return $targetList;
}
/**
* 通过极光推送的相关参数得到个推的参数
* @author sugang
* @date 2015-1-6
**/
public function gtParamFromJpush(&$param, &$extras) {
if ( isset($param['receiver_type']) ) {
// 2标签 3别名 4广播 5注册ID
if ( $param['receiver_type'] == 4 ) {
$param['gt_target'] = '0';
} else if ( isset($param['receiver_value']) ) {
$param['gt_target'] = $param['receiver_value'];
}
}
}
/**
* 通过个推的相关参数得到极光推送的参数
* @author sugang
* @date 2015-1-7
**/
public function jpushParamFromGt() {
if ( isset($param['gt_target']) ) {
// 2标签 3别名 4广播 5注册ID
if ( $param['gt_target'] == '0' ) {
$param['receiver_type'] = '4';
$param['receiver_value']= '';
} else {
$param['receiver_type'] = '3';
$param['receiver_value']= $param['gt_target'];
}
}
}
/**
* 对个推推送增加开关和转化参数控制
* @param $template string 个推的模板类型,notice通知,message消息
* @notice 通过构造函数中的initParams参数控制
* $initParams['gt_notice_switch'] 是否推送通知,true推送,false不推送
* $initParams['gt_notice_change'] 只能传message,表示通知将使用消息的方式推送
* $initParams['gt_message_switch'] 是否推送消息,true推送,false不推送
* $initParams['gt_message_change'] 只能传notice,表示消息将使用通知的方式推送
* @author sugang
* @date 2015-1-7
**/
public function gtPushStatus($template) {
if ( $template == 'notice' ) {
if ( isset($this->initParams['gt_notice_switch']) && !$this->initParams['gt_notice_switch'] ) {
return false;
}
if ( $this->initParams['gt_notice_change'] == 'message' ) {
return 'message';
}
} else {
if ( isset($this->initParams['gt_message_switch']) && !$this->initParams['gt_message_switch'] ) {
return false;
}
if ( $this->initParams['gt_message_switch'] == 'notice' ) {
return 'notice';
}
}
return $template;
}
/End 个推方法
}
?>
App推送程序
最新推荐文章于 2020-11-25 14:47:38 发布