百度雲推送,地址: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(); } }