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

發佈了60 篇原創文章 · 獲贊 51 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章