App推送程序

<?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 个推方法
    }
?>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值