PHP 服务端友盟推送

以前也用过友盟推送,但是整合的方法当时没整理

结果前段时间在使用的时候,找不到了诶

友盟推送文档地址:https://developer.umeng.com/docs/67966/detail/68343

于是再次百度了一番

找到了现在这篇,整合的比较不错,适合我这种面向百度编程的

废话不多说

直接开始

首先对应配置

在友盟 的 应用中找到对应Android与ios的 AppKey 和 App Master Secret

或者对应配置信息并在配置中配置

'umeng' => [
        'android_app_key'    => '####',  //友盟android AppKey
        'android_app_secret' => '####',  //友盟android App Master Secret
        'ios_app_key'        => '####',  //友盟ios AppKey
        'ios_app_secret'     => '####',  //友盟android App Master Secret
    ],

然后推送核心类库

代码如下:

<?php
namespace umeng;
/**
 * 友盟消息 安卓 IOS 推送类
 *
 */
class Push 
{
    protected $host; //发送地址
    protected $app_key; //appkey
    protected $appMasterSecret; //app secret
    protected $description; //app secret
    //
    public function __construct($options = null) 
    {
        if (is_array($options)) {
            $this->host = 'https://msgapi.umeng.com/api/send';
            $this->app_key = $options['app_key'];
            $this->appMasterSecret = $options['appMasterSecret'];
            $this->description = "友盟接口推送";
        } else {
            return false;
        }
    }
    /**
     * @param $info
     * @param $device_token
     * @return mixed|string
     * 用户单播 和 列播
     */
    public function Android_Device_Push($info, $device_token) 
    {
        $data['appkey'] = $this->app_key;
        $data['timestamp'] = time(); //时间戳
        if (is_array($device_token)) {
            //批量用户列播
            $data['type'] = 'listcast';
            $data['device_tokens'] = implode(',', $device_token); //数组转字符串
            
        } else {
            //一个用户单播
            $data['type'] = 'unicast';
            $data['device_tokens'] = $device_token;
        }
        //payload内容
        $data['payload']['display_type'] = 'notification'; //通知消息
        //payload body内容
        $data['payload']['body']['after_open'] = "go_custom"; //后续操作打开app
        $data['payload']['body']['ticker'] = $info['ticker'];
        $data['payload']['body']['title'] = $info['title'];
        $data['payload']['body']['text'] = $info['title']; //广播通知不能为空补填
        //这里可以写附加字段
        $data['payload']['extra']['type'] = $info['type']; //附加字段类型
        $data['production_mode'] = $info['production_mode'];
        $data['description'] = $this->description;
        return $this->send($data, $this->host, $this->appMasterSecret);
    }
    /**
     * @param $info
     * @return mixed|string
     * 广播
     */
    public function Android_Broadcast($info) 
    {
        $data['appkey'] = $this->app_key;
        $data['timestamp'] = time(); //时间戳
        //广播消息
        $data['type'] = 'broadcast';
        //payload内容
        $data['payload']['display_type'] = 'notification'; //通知消息
        //payload body内容
        $data['payload']['body']['after_open'] = "go_custom"; //后续操作打开app
        $data['payload']['body']['ticker'] = $info['ticker'];
        $data['payload']['body']['title'] = $info['title'];
        $data['payload']['body']['text'] = $info['title']; //广播通知不能为空补填
        $data['payload']['extra']['type'] = $info['type']; //附加字段类型1 跳转消息详情
        $data['payload']['extra']['prod_id'] = $info['prod_id']; //附加字段消息详情id
        $data['payload']['extra']['text'] = $info['text']; //
        $data['production_mode'] = $info['production_mode'];
        $data['description'] = $this->description;
        return $this->send($data, $this->host, $this->appMasterSecret);
    }
    /**
     * @param $info
     * @param $device_token
     * @return mixed|string
     * 单播 和 列播
     */
    public function Ios_Device_Push($info, $device_token) 
    {
        $data = array();
        $data['appkey'] = $this->app_key;
        $data['timestamp'] = time(); //时间戳
        if (is_array($device_token)) {
            //批量用户列播
            $data['type'] = 'listcast';
            $data['device_tokens'] = implode(',', $device_token); //数组转字符串
            
        } else {
            //一个用户单播
            $data['type'] = 'unicast';
            $data['device_tokens'] = $device_token;
        }
        //payload内容
        $data['payload']['aps']['alert'] = $info['text']; //消息主体
        $data['payload']['aps']['sound'] = 'default'; //声音
        $data['payload']['type'] = $info['type']; //消息类型 0打开消息详情
        $data['payload']['prod_id'] = $info['prod_id']; //消息id
        $data['payload']['title'] = $info['title'];
        $data['payload']['text'] = $info['text']; //
        $data['production_mode'] = $info['production_mode'];
        $data['description'] = $this->description;
        return $this->send($data, $this->host, $this->appMasterSecret);
    }

    public function Ios_Broadcast($info) 
    {
        $data = array();
        $data['appkey'] = $this->app_key;
        $data['timestamp'] = time(); //时间戳
        //广播消息
        $data['type'] = 'broadcast';
        //payload内容
        $data['payload']['aps']['alert'] = $info['title']; //消息主体
        $data['payload']['aps']['sound'] = 'chime'; //声音
        $data['payload']['aps']['badge'] = 1; //显示角标
        $data['payload']['type'] = $info['type']; //消息类型 0打开消息详情
        $data['payload']['prod_id'] = $info['prod_id']; //消息id
        $data['payload']['title'] = $info['title'];
        $data['payload']['text'] = $info['ticker']; //
        $data['production_mode'] = $info['production_mode'];
        $data['description'] = $this->description;
        return $this->send($data, $this->host, $this->appMasterSecret);
    }
    /**
     * @param $data
     * @param $url_s
     * @param $appMasterSecret
     * @return mixed|string
     * curl 请求
     */
    private function send($data, $url_s, $appMasterSecret) 
    {
        $postBody = json_encode($data);
        //加密
        $sign = md5("POST" . $url_s . $postBody . $appMasterSecret);
        $url = $url_s . "?sign=" . $sign;
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postBody);
        $result = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlErrNo = curl_errno($ch);
        $curlErr = curl_error($ch);
        curl_close($ch);
        // print_r($result);
        // exit;
        if ($httpCode == "0") {
            // Time out
            return ("Curl error number:" . $curlErrNo . " , Curl error details:" . $curlErr . "
");
        } else if ($httpCode != "200") {
            return ("Http code:" . $httpCode . " details:" . $result . "
");
        } else {
            return $result;
        }
    }
}
?>

调用方法示例:

use umengPush;
function umengsend($device_token)
{

    $info['ticker'] = '推送测试提示栏';  #提示栏文字
    $info['title'] ='推送测试标题';    #通知标题
    $info['text'] = '推送测试文字描述';  #文字描述
    $info['type'] = 4;     //附加字段类型1 跳转消息详情
    $info['production_mode'] = 'false';
    $info['prod_id'] = "";

    #IOS 单播与广播
    $options_ios = [
            'app_key' => config('umeng.ios_app_key'),
            'appMasterSecret' => config('umeng.ios_app_secret'),
        ];
    $ios_umeng = new Push($options_ios);
    #IOS单播
    $ios_umeng->Ios_Device_Push($info,$device_token);
    #IOS广播
    $ios_umeng->Ios_Broadcast($info);


    #Android 单播与广播
    $options_android = [
            'app_key' => config('umeng.android_app_key'),
            'appMasterSecret' => config('umeng.android_app_secret'),
        ];
    $android_umeng = new Push($options_android);

    #安卓单播
    $android_umeng->Android_Device_Push($info,$device_token);
    #安卓广播
    $android_umeng->Android_Broadcast($info);
}

 自己使用:

#推送相关设定
use umengPush;
    

#公共测试
#$title 通知标题
#$text  文字描述
#$type  类型 1单播2广播
#$userlist  device_token 列表
function umengpublic($title,$text,$type="1",$userlist=[])
{
    $info = [];
    $info['ticker'] = $title;  #提示栏文字
    $info['title'] = $title;    #通知标题
    $info['text'] = $text;  #文字描述
    $info['type'] = 4;     //附加字段类型1 跳转消息详情
    $info['production_mode'] = 'false';  #false 测试  true 正式
    $info['prod_id'] = "";
    if($type == '1')
    {
        umengpushuser($info,$userlist);
    }else{
        umengpushpublic($info);
    }
    return true;
}

#公共推送 -- 广播
function  umengpushpublic($info)
{
    #安卓广播
    $android_umeng = new Push(['app_key' => config('umeng.android_app_key'),'appMasterSecret' => config('umeng.android_app_secret')]);
    $android_umeng->Android_Broadcast($info);
    #########################################
    #IOS广播
    $ios_umeng = new Push(['app_key' => config('umeng.ios_app_key'),'appMasterSecret' => config('umeng.ios_app_secret')]);
    $ios_umeng->Ios_Broadcast($info);
    return true;
}

#公共推送  -- 单播
function umengpushuser($info,$userlist)
{
    #对应相关用户
    $userlists = []; #获取device_token 列表
    foreach($userlists as $key=>$val)
    {
        #安卓单推
        if($val['ismodel'] == '1')
        {
            #安卓配置
            $android_umeng = new Push(['app_key' => config('umeng.android_app_key'),'appMasterSecret' => config('umeng.android_app_secret')]);
            $android_umeng->Android_Device_Push($info,$val['device_token']);
        }
        #ios 单推
        else if($val['ismodel'] == '2')
        {
            #IOS配置
            $ios_umeng = new Push(['app_key' => config('umeng.ios_app_key'),'appMasterSecret' => config('umeng.ios_app_secret')]);
            $ios_umeng->Ios_Device_Push($info,$val['device_token']);
        }
        else
        {
            // return 
        }
    }
    return true;
}

 附录::

推送相关参数

Android:

{
    "appkey":"xx",        // 必填,应用唯一标识
    "timestamp":"xx",    // 必填,时间戳,10位或者13位均可,时间戳有效期为10分钟
    "type":"xx",        // 必填,消息发送类型,其值可以为: 
                        //   unicast-单播
                        //   listcast-列播,要求不超过500个device_token
                        //   filecast-文件播,多个device_token可通过文件形式批量发送
                        //   broadcast-广播
                        //   groupcast-组播,按照filter筛选用户群, 请参照filter参数
                        //   customizedcast,通过alias进行推送,包括以下两种case:
                        //     - alias: 对单个或者多个alias进行推送
                        //     - file_id: 将alias存放到文件后,根据file_id来推送
    "device_tokens":"xx",    // 当type=unicast时, 必填, 表示指定的单个设备
                            // 当type=listcast时, 必填, 要求不超过500个, 以英文逗号分隔
    "alias_type": "xx",    // 当type=customizedcast时, 必填
                        // alias的类型, alias_type可由开发者自定义, 开发者在SDK中
                        // 调用setAlias(alias, alias_type)时所设置的alias_type
    "alias":"xx",        // 当type=customizedcast时, 选填(此参数和file_id二选一)
                        // 开发者填写自己的alias, 要求不超过500个alias, 多个alias以英文逗号间隔
                        // 在SDK中调用setAlias(alias, alias_type)时所设置的alias
    "file_id":"xx",    // 当type=filecast时,必填,file内容为多条device_token,以回车符分割
                    // 当type=customizedcast时,选填(此参数和alias二选一)
                    //   file内容为多条alias,以回车符分隔。注意同一个文件内的alias所对应
                    //   的alias_type必须和接口参数alias_type一致。
                    // 使用文件播需要先调用文件上传接口获取file_id,参照"文件上传"
    "filter":{},    // 当type=groupcast时,必填,用户筛选条件,如用户标签、渠道等,参考附录G。
                    // filter的内容长度最大为3000B)
    "payload": {    // 必填,JSON格式,具体消息内容(Android最大为1840B)
        "display_type":"xx",    // 必填,消息类型: notification(通知)、message(消息)
        "body": {    // 必填,消息体。
                // 当display_type=message时,body的内容只需填写custom字段。
                // 当display_type=notification时,body包含如下参数:
            // 通知展现内容:
            "ticker":"xx",    // 必填,通知栏提示文字
            "title":"xx",    // 必填,通知标题
            "text":"xx",    // 必填,通知文字描述 

            // 自定义通知图标:
            "icon":"xx",    // 可选,状态栏图标ID,R.drawable.[smallIcon],
            // 如果没有,默认使用应用图标。
            // 图片要求为24*24dp的图标,或24*24px放在drawable-mdpi下。
            // 注意四周各留1个dp的空白像素
            "largeIcon":"xx",    // 可选,通知栏拉开后左侧图标ID,R.drawable.[largeIcon],
            // 图片要求为64*64dp的图标,
            // 可设计一张64*64px放在drawable-mdpi下,
            // 注意图片四周留空,不至于显示太拥挤
            "img": "xx",    // 可选,通知栏大图标的URL链接。该字段的优先级大于largeIcon。
                            // 该字段要求以http或者https开头。

            // 自定义通知声音:
            "sound": "xx",    // 可选,通知声音,R.raw.[sound]。
                            // 如果该字段为空,采用SDK默认的声音,即res/raw/下的
                            // umeng_push_notification_default_sound声音文件。如果
                            // SDK默认声音文件不存在,则使用系统默认Notification提示音。

            // 自定义通知样式:
            "builder_id": xx,    // 可选,默认为0,用于标识该通知采用的样式。使用该参数时,
                                // 开发者必须在SDK里面实现自定义通知栏样式。

            // 通知到达设备后的提醒方式,注意,"true/false"为字符串
            "play_vibrate":"true/false",    // 可选,收到通知是否震动,默认为"true"
            "play_lights":"true/false",        // 可选,收到通知是否闪灯,默认为"true"
            "play_sound":"true/false",        // 可选,收到通知是否发出声音,默认为"true"

            // 点击"通知"的后续行为,默认为打开app。
            "after_open": "xx",    // 可选,默认为"go_app",值可以为:
                                //   "go_app": 打开应用
                                //   "go_url": 跳转到URL
                                //   "go_activity": 打开特定的activity
                                //   "go_custom": 用户自定义内容。
            "url": "xx",    // 当after_open=go_url时,必填。
                            // 通知栏点击后跳转的URL,要求以http或者https开头
            "activity":"xx",    // 当after_open=go_activity时,必填。
                                // 通知栏点击后打开的Activity
            "custom":"xx"/{}    // 当display_type=message时, 必填
                                // 当display_type=notification且
                                // after_open=go_custom时,必填
                                // 用户自定义内容,可以为字符串或者JSON格式。
        },
        extra:{    // 可选,JSON格式,用户自定义key-value。只对"通知"
                // (display_type=notification)生效。
                // 可以配合通知到达后,打开App/URL/Activity使用。
            "key1": "value1",
            "key2": "value2",
            ...
        }
    },
    "policy":{    // 可选,发送策略
        "start_time":"xx",    // 可选,定时发送时,若不填写表示立即发送。
                            // 定时发送时间不能小于当前时间
                            // 格式: "yyyy-MM-dd HH:mm:ss"。 
                            // 注意,start_time只对任务类消息生效。
        "expire_time":"xx",    // 可选,消息过期时间,其值不可小于发送时间或者
                            // start_time(如果填写了的话),
                            // 如果不填写此参数,默认为3天后过期。格式同start_time
        "max_send_num": xx,    // 可选,发送限速,每秒发送的最大条数。最小值1000
                            // 开发者发送的消息如果有请求自己服务器的资源,可以考虑此参数。
        "out_biz_no": "xx"    // 可选,消息发送接口对任务类消息的幂等性保证。
                            // 强烈建议开发者在发送任务类消息时填写这个字段,友盟服务端会根据这个字段对消息做去重避免重复发送。
                            // 同一个appkey下面的多个消息会根据out_biz_no去重,不同发送任务的out_biz_no需要保证不同,否则会出现后发消息被去重过滤的情况。
                            // 注意,out_biz_no只对任务类消息有效。
    },
    "production_mode":"true/false",    // 可选,正式/测试模式。默认为true
                                    // 测试模式只对“广播”、“组播”类消息生效,其他类型的消息任务(如“文件播”)不会走测试模式
                                    // 测试模式只会将消息发给测试设备。测试设备需要到web上添加。
                                    // Android: 测试设备属于正式设备的一个子集。
    "description": "xx",    // 可选,发送消息描述,建议填写。  
    //系统弹窗,只有display_type=notification生效
    "mipush": "true/false",    // 可选,默认为false。当为true时,表示MIUI、EMUI、Flyme系统设备离线转为系统下发
    "mi_activity": "xx",    // 可选,mipush值为true时生效,表示走系统通道时打开指定页面acitivity的完整包路径。
    "channel_properties":{ //可选,厂商通道相关的特殊配置
      "xiaomi_channel_id":"",//小米channel_id,具体使用及限制请参考小米推送文档 https://dev.mi.com/console/doc/detail?pId=2086
      "vivo_classification":"1" , //vivo消息分类:0 运营消息,1 系统消息, 需要到vivo申请,具体使用及限制参考[vivo消息推送分类功能说明]https://dev.vivo.com.cn/documentCenter/doc/359
      "oppo_channel_id":"xx"  //可选, android8以上推送消息需要新建通道,否则消息无法触达用户。push sdk 6.0.5及以上创建了默认的通道:upush_default,消息提交厂商通道时默认添加该通道。如果要自定义通道名称或使用私信,请自行创建通道,推送消息时携带该参数 具体可参考 [oppo通知通道适配] https://open.oppomobile.com/wiki/doc#id=10289
    }
}

IOS相关参数:

{
  "appkey":"xx",    // 必填,应用唯一标识
  "timestamp":"xx", // 必填,时间戳,10位或者13位均可,时间戳有效期为10分钟
  "type":"xx",      // 必填,消息发送类型,其值可以为: 
                    //   unicast-单播
                    //   listcast-列播,要求不超过500个device_token
                    //   filecast-文件播,多个device_token可通过文件形式批量发送
                    //   broadcast-广播
                    //   groupcast-组播,按照filter筛选用户群, 请参照filter参数
                    //   customizedcast,通过alias进行推送,包括以下两种case:
                    //     - alias: 对单个或者多个alias进行推送
                    //     - file_id: 将alias存放到文件后,根据file_id来推送
  "device_tokens":"xx", // 当type=unicast时, 必填, 表示指定的单个设备
                        // 当type=listcast时, 必填, 要求不超过500个, 以英文逗号分隔
  "alias_type": "xx", // 当type=customizedcast时, 必填
                      // alias的类型, alias_type可由开发者自定义, 开发者在SDK中
                      // 调用setAlias(alias, alias_type)时所设置的alias_type
  "alias":"xx", // 当type=customizedcast时, 选填(此参数和file_id二选一)
                // 开发者填写自己的alias, 要求不超过500个alias, 多个alias以英文逗号间隔
                // 在SDK中调用setAlias(alias, alias_type)时所设置的alias
  "file_id":"xx", // 当type=filecast时,必填,file内容为多条device_token,以回车符分割
                  // 当type=customizedcast时,选填(此参数和alias二选一)
                  //   file内容为多条alias,以回车符分隔。注意同一个文件内的alias所对应
                  //   的alias_type必须和接口参数alias_type一致。
                  // 使用文件播需要先调用文件上传接口获取file_id,参照"2.4文件上传接口"
  "filter":{}, // 当type=groupcast时,必填,用户筛选条件,如用户标签、渠道等,参考附录G。
  "payload":   // 必填,JSON格式,具体消息内容(iOS最大为2012B)
  {
    "aps":      // 必填,严格按照APNs定义来填写
    {
        "alert":""/{ // 当content-available=1时(静默推送),可选; 否则必填。
                     // 可为JSON类型和字符串类型
            "title":"title",
            "subtitle":"subtitle",
            "body":"body"
        }                   
        "badge": xx,           // 可选        
        "sound": "xx",         // 可选         
        "content-available":1  // 可选,代表静默推送     
        "category": "xx",      // 可选,注意: ios8才支持该字段。
    },
    "key1":"value1",       // 可选,用户自定义内容, "d","p"为友盟保留字段,
                           // key不可以是"d","p"
    "key2":"value2",       
    ...
  },
  "policy":               // 可选,发送策略
  {
      "start_time":"xx",   // 可选,定时发送时间,若不填写表示立即发送。
                           // 定时发送时间不能小于当前时间
                           // 格式: "yyyy-MM-dd HH:mm:ss"。 
                           // 注意,start_time只对任务生效。
      "expire_time":"xx",  // 可选,消息过期时间,其值不可小于发送时间或者
                           // start_time(如果填写了的话), 
                           // 如果不填写此参数,默认为3天后过期。格式同start_time
      "out_biz_no": "xx"   // 可选,消息发送接口对任务类消息的幂等性保证。
                           // 强烈建议开发者在发送任务类消息时填写这个字段,友盟服务端会根据这个字段对消息做去重避免重复发送。
                           // 同一个appkey下面的多个消息会根据out_biz_no去重,不同发送任务的out_biz_no需要保证不同,否则会出现后发消息被去重过滤的情况。
                           // 注意,out_biz_no只对任务类消息有效。
      "apns_collapse_id": "xx" // 可选,多条带有相同apns_collapse_id的消息,iOS设备仅展示
                               // 最新的一条,字段长度不得超过64bytes
  },
  "production_mode":"true/false" // 可选,正式/测试模式。默认为true
                                 // 测试模式只对“广播”、“组播”类消息生效,其他类型的消息任务(如“文件播”)不会走测试模式
                                 // 测试模式只会将消息发给测试设备。测试设备需要到web上添加。
  "description": "xx"      // 可选,发送消息描述,建议填写。     
}

分享完毕..

漫漫人生路,终究还是要找合得来的人...

2020年08月28日

原文地址:https://www.cnblogs.com/YFYQ/p/13576298.html