在thinkphp框架裏封裝百度雲推送的一個嘗試

百度雲推送,地址:http://push.baidu.com/,優勢挺多,大平臺,穩定靈活,安全,免費,應用廣。php

最近的公司項目須要後端給移動端發送通知,第一次接觸這種需求,同事推薦我瞭解下個推,後來又推薦了百度雲,比較起來選擇了百度雲。android

因而在官方SDK中心下載了 php服務端SDK,地址:http://push.baidu.com/sdk/push_server_sdk_for_php。ios

起初看着SDK一頭霧水,結構比較複雜,後來發現最終程序使用了通用的curl請求方式,想一想推送模塊能夠單獨一塊,也能夠封裝。ajax

由於項目使用的thinkphp框架,在基本熟悉SDK後,有了把幾個類型接口封裝到框架一個模型裏的想法。thinkphp

 模型代碼以下:json

  1 class BdPushModel extends Model {
  2     const TAG_TYPE_LBS_LABEL = 2;       // LBS 推送
  3     const TAG_TYPE_INTEREST_LABEL = 3;  // 興趣組
  4     const TAG_TYPE_AGE_LABEL = 4;       // 年齡組
  5     const TAG_TYPE_SEX_LABEL = 5;       // 性別組
  6     const TAG_TYPE_OP_LABEL = 6;        // 組合運算
  7 
  8 
  9     public $apikey     = "Vek7uG4nhplvh3cpg2H5Ut50";//測試用
 10     public $secret_key = "NdxoxNykVrH6qA3CV33kzK7lsSTTvZA9";//測試用
 11     public $restHostUrl = 'http://api.tuisong.baidu.com/rest/3.0/';
 12     /*$timestamp : 用戶發起請求時的unix時間戳。本次請求籤名的有效時間爲該時間戳+10分鐘。*/
 13     public $timestamp  = '';
 14     public function _initialize(){
 15         $this->timestamp = NOW_TIME + 600;//初始化用戶發起請求時的unix時間戳
 16     }
 17      /**
 18      * 單播, 推送一條消息到指定設備
 19      * $channel_id 目標客戶端設備所屬的惟一id;
 20      * $msg 消息內容.可參見<u>消息體格式說明</u> 當消息體類型爲一個array時,將自動調用json_encode方法來將array轉換爲一個string;
 21      * $opts 可選參數列表, 包含 msg_type, msg_expires, deploy_status, msg_topic幾項可選內容;
 22      *
 23      */
 24     public  function pushMsgToSingleDevice($channel_id,$device_type,$messages){
 25         if(empty($channel_id))
 26             return array('error_code'=>C('RES_PARAM_ERR'),'error_msg'=>'');
 27         $api     = 'push/single_device';//API的資源操做方法名
 28         $msg_type  = 1;//取值以下:0:消息;1:通知。默認爲0
 29         $url = $this->restHostUrl.$api;
 30         $arrContent = array(
 31             'apikey'     => $this->apikey,
 32             'timestamp'  => NOW_TIME,
 33             'device_type'  => $device_type,//3:android;4:ios
 34             'channel_id'  => $channel_id,
 35             'msg'   => $messages,
 36             'msg_type'  => $msg_type
 37         );
 38         $sign  = $this->getSign('POST',$url,$arrContent);
 39         $arrContent['sign'] = $sign;
 40         $return = $this->curlPost($arrContent,$url);
 41         $rs = $this->object_array(json_decode($return));
 42         if($rs['error_code']>0){
 43             return false;
 44         }
 45         return true;
 46     }   
 47 
 48     /**
 49      * 批量單播, 向指定的一組channel_id發送一條消息.
 50      * $channel_ids; 一個數組, 每項爲一個channel_id
 51      * $msg 消息內容.可參見<u>消息體格式說明</u> 當消息體類型爲一個array時,將自動調用json_encode方法來將array轉換爲一個string;
 52      *  $opts 可選參數, 包含
 53      */
 54     public function pushBatchUniMsg($channel_ids,$messages,$device_type){
 55         if(empty($channel_ids))
 56             return array('error_code'=>C('RES_PARAM_ERR'),'error_msg'=>'');
 57         $api     = 'push/batch_device';//API的資源操做方法名
 58         $msg_type  = 1;//取值以下:0:消息;1:通知。默認爲0
 59         $url = $this->restHostUrl.$api;
 60         $arrContent = array(
 61             'apikey'     => $this->apikey,
 62             'timestamp'  => NOW_TIME,
 63             'device_type'  => $device_type,//3:android;4:ios
 64             'channel_ids'  => $channel_ids,
 65             'msg'   => $messages,
 66             'msg_type'  => $msg_type
 67         );
 68         $sign  = $this->getSign('POST',$url,$arrContent);
 69         $arrContent['sign'] = $sign;
 70         $return = $this->curlPost($arrContent,$url);
 71         if($return['error_code']>0){
 72             return false;
 73         }
 74         return true;
 75     }
 76     /**
 77  *@var      curl模擬post提交數據
 78  *@param    $data          提交的全部參數
 79  *@param    $url           請求的地址
 80  *@return   json           百度頁面返回的結果
 81  */
 82 function curlPost($data,$url){
 83     $data = $this->encodePostBody($data);
 84     $port = parse_url($url, PHP_URL_PORT);
 85     $header = array(
 86         'Content-Type: application/x-www-form-urlencoded;charset=utf-8',
 87         'User-Agent: '. $this->makeUA()
 88     );
 89     $ch = curl_init ();
 90     curl_setopt ( $ch, CURLOPT_URL, $url );
 91     curl_setopt ( $ch, CURLOPT_PORT, empty($port)?80:$port );
 92     curl_setopt ($ch, CURLOPT_HTTPHEADER, $header);
 93     curl_setopt ( $ch, CURLOPT_POST, 1 );
 94 //    curl_setopt ( $ch, CURLOPT_HEADER, 0 );
 95 //    curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, false );
 96     curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
 97     curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data );
 98     $return = curl_exec ( $ch );
 99     curl_close ( $ch );
100     return $return;
101 }
102 
103 function encodePostBody($body) {
104     if ($body === null) {
105         return '';
106     }
107 
108     if (! is_array($body)) {
109         return urlencode(strval($body));
110     }
111 
112     $result = array ();
113     foreach ( $body as $k => $v ) {
114         $result [ ] = urlencode($k) . '=' . urlencode($v);
115     }
116 
117     return join('&', $result);
118 }
119 
120 
121 function makeUA(){
122     $sdkVersion = '3.0.0';//百度推送版本
123     $sysName = php_uname('s');
124     $sysVersion = php_uname('v');
125     $machineName = php_uname('m');
126 
127     $systemInfo = "$sysName; $sysVersion; $machineName";
128 
129     $langName = 'PHP';
130     $langVersion = phpversion();
131 
132     $serverName = php_sapi_name();
133     $serverVersion = "Unknown";
134 
135     $sendInfo = 'ZEND/' . zend_version();
136 
137     $serverInfo = "$serverName/$serverVersion";
138 
139     if(isset($_SERVER['SERVER_SOFTWARE'])){
140         $serverInfo .= '(' . $_SERVER['SERVER_SOFTWARE'] . ')';
141     }
142 
143 
144     $tpl = "BCCS_SDK/3.0 ($systemInfo) $langName/$langVersion (Baidu Push SDK for PHP v$sdkVersion) $serverInfo $sendInfo";
145 
146     return $tpl;
147 }
148 //object轉數組
149 function object_array($array){
150     if(is_object($array)){
151         $array = (array)$array;
152     }
153     if(is_array($array)){
154         foreach($array as $key=>$value){
155             $array[$key] = object_array($value);
156         }
157     }
158     return $array;
159 }
160 /**
161      * 計算請求遷名
162      *
163      * @param string $method
164      *        GET|POST
165      * @param string $url
166      *        請求的完整url, 不含query部份
167      * @param array $arrContent
168      *        提交的數據項,包含get及post,但不包含簽名項
169      * @return string
170      */
171     function getSign($method, $url, $arrContent) {
172         $secret_key = $this->secret_key;
173         $baseStr = strtoupper($method) . $url;
174         ksort($arrContent);
175         foreach ( $arrContent as $key => $value ) {
176             $baseStr .= $key . '=' . $value;
177         }
178         $sign = md5(urlencode($baseStr . $secret_key));
179 
180         return $sign;
181     }
182 
183 }

限於篇幅,這裏只寫單播和批量單播這個例子後端

控制器調用代碼:api

class IndexController extends Controller {
    public function index(){
        $channelId = '3785562685113372034';//測試用
        $title = 'Hi!';
        $description = 'hello, this message from baidu push service.';
        $push = new BdPushModel('user_member');
        $messages = json_encode(array('title'=>$title,'description'=>$description));
        $device_type = 3;//3:android,4:ios
        $rs = $push->pushMsgToSingleDevice($channelId,$device_type,$messages);
        // 判斷返回值,當發送失敗時,  , 能夠經過getError來得到錯誤信息.
        if(!$rs){
           $this->ajaxReturn(false, "JSON");
           exit();
        }
        $this->ajaxReturn(true, "JSON");
        exit();
    }
}            
相關文章
相關標籤/搜索