zoukankan      html  css  js  c++  java
  • 在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();
        }
    }            
  • 相关阅读:
    MySQL Show Processlist 整理
    由linkedin数据库泄漏引发的思考[转发]
    MySQL 严重 Bug 用户登陆漏洞[转发]
    关于博客的开始
    Linux共享库位置配置
    getopt详解
    git使用
    ArrayList读源码心得
    HashMap内部实现机制及优化第一篇
    如何才能做一个好网站系列 第三篇 最初的思路
  • 原文地址:https://www.cnblogs.com/hero-89/p/4717121.html
Copyright © 2011-2022 走看看