在thinkphp框架里封装百度云推送的一个尝试

百度云推送,地址:http://push.baidu.com/,优点挺多,大平台,稳定灵活,安全,免费,应用广。

最近的公司项目需要后端给移动端发送通知,第一次接触这种需求,同事推荐我了解下个推,后来又推荐了百度云,比较起来选择了百度云。

于是在官方SDK中心下载了 php服务端SDK,地址:http://push.baidu.com/sdk/push_server_sdk_for_php。

起初看着SDK一头雾水,结构比较复杂,后来发现最终程序使用了通用的curl请求方式,想想推送模块可以单独一块,也可以封装。

因为项目使用的thinkphp框架,在基本熟悉SDK后,有了把几个类型接口封装到框架一个模型里的想法。

 模型代码如下:

  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 }

限于篇幅,这里只写单播和批量单播这个例子

控制器调用代码:

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();
    }
}            
原文地址:https://www.cnblogs.com/hero-89/p/4717121.html