没想到做 PHP 还会接触这方面的东西,感觉风马牛不相及,在这里碰头了。从 PHP api到 Cordova 搭建打包 App再到里面的极光推送和小红点的数值,真是秃了半边顶。(话说回来,我们 BOSS 和个推可是校友,我可是力排众议,毅然决然选择了极光推,滑稽.jpg)
--萌新寄语
本篇主要介绍 Cordova 和 PHP 配合,完成极光推送消息( iOS 集成推送的证书申请, PHP 推送代码实现)及角标数值(badgeNum)的自我实现。多以截图为主,直击老铁痛点。
这边主要介绍 jpush ios 推送证书的申请,申请好了的,可以直接跳下面 PHP 部分
先介绍下我的环境,我只用到了 jpush。所以申请极光账号还是很简单的,不需要什么身份认证。
一. 创建应用后的操作
其中 AppKey 是 Cordova 安装 jpush 插件的必须 也是后面推送的必须(还有隐藏的
Master Secret)
- 下面就可以设置推送的相关信息了
安卓的无脑操作这里就不介绍了
注意包名一定要统一 避免不必要的麻烦,这里详细介绍下 iOS 的证书设置(鉴权方式为 证书)我这里用的是个人开发者账号 $99 没有证书、Mac 的之类的兄弟姐妹就早点儿下班休息吧航
首先需要用你的开发者账号登陆苹果开发者中心
-
然后打开这个惨绝人寰的页面
-
Development 顾名思义即开发证书
-
点击加号后出现的页面 选中开发的按钮后就可以下一步 continue 了
-
选择以后继续 continue
-
一直 continue 到这个页面 选择签名 这个时候就需要 Mac 的钥匙串去请求签名证书了 这一步先放在这里
-
Mac 请求证书
-
请求成功之后,保存在本地,创建一个这个包名的文件夹 方便区分
- 回到已经打开的 苹果开发者中心 选择刚才存到本地的证书 down 下来
下载下来的 .cer 后缀的文件就是我们要的了。拖到钥匙串中打开
下面就是导出 .p12 的文件了!!!! 盼星星盼月亮 终于盼到这一步了
-
走完下面这一步就大功告成了
- 都是明白人儿 放进去就行了。虽然下面有提示 是否将生产证书用于开发环境,想都别想,趁热把另一个证书申请了吧
- 开发证书和生产证书操作是一毛一样的 两个同时操作也行 也没意见
-
最终结果
PHP 端处理 badge 的思路的自我实现
关于推送的信息,一定要多看极光的控制台。reg_id和msg_id 平台信息等都在上面。方便你去查找错误信息
之前一直不懂 Jpush 服务器的角标值是怎么玩的,现在大概明白了。关于推送的 badge数量在我上面截图红圈的 badge 参数。这样我们不要自己去计算角标值,根据下面的两个接口定义 就可以根据用户是否点击,在原有的基数上去对应的增加减少即可 但是如果我们想要看到消息日志的话和推送日志方便自己管理的话 就要自己去建表存储状态了
大概思路是 这里我用了三张表去控制 大概实现了角标的核销。
- 用户每一次登陆都会去获取一下设备的 id,也就是极光的 registration_id 。(防止设备 ID 改变,极光介绍,或者用户更换手机,能准确的推送到该设备)
- message 表主要做存储发送消息的记录。方便后台管理员了解曾经推送过得信息。
- message_log 表主要就是存储推送的消息日志(用户太多的话肯定要优化数据表的,暂时不做考虑),根据表里的
status
就可以判断是否已读,用户每次点击消息详情页都要去访问下接口去修改status
的状态,从而完成核销。核销的基础是该用户的 id 和消息 id,因为这两个都是唯一的。
PHP 逻辑代码简单的封装了一下
详见 jpushPHPdemo
protected function pi_push($member_id,$content,$badgeNum,$array){
try {
// 配置引入
$app_key = PI_Config::APP_KEY;
$master_secret = PI_Config::MASTER_SECRET;
// use jpush
$client = new JPush($app_key, $master_secret);
$response = $client->push()
->setPlatform("all")
->addRegistrationId( $member_id )
->iosNotification( $content, array(
'sound' => 'sound.caf',
'badge' => "$badgeNum" + 1,
'content-available' => true,
'mutable-content' => true,
'extras' => $array
))
->androidNotification( $content, array(
// 'title' => ,
'extras' => $array
))
->options(array(
// !!!! apns_production:这里我试过去掉 option参数 以为默认推送生产环境,其实不然。需要生产环境的推送的时候,最好指定!!!
// True 表示推送生产环境,False 表示要推送开发环境;如果不指定则默认为推送生产环境
'apns_production' => true,
))
->send();
if ( $response['http_code'] == 200) {
return $response['body']['msg_id'];
}else{
return false;
}
} catch (\JPush\Exceptions\APIConnectionException $e) {
return false;
} catch (\JPush\Exceptions\APIRequestException $e) {
return false;
}
}
下面执行推送的代码
// 手动推送的设置
public function post_push( $request ){
$res['title'] = $request['title']; // 推送的标题
$res['content'] = $request['content']; // 推送的内容
$res['remark'] = $request['remark']; // 推送的备注
$res['create_date'] = date( "Y-m-d H:i:s" );
// 推送类型
$push_type = $request['push_type'];
// 推送前插入 推送记录表 (WordPress的mysql insert方法)
if ( $push_type === '0' ) {
$info = $this->wpdb->insert(
$this->pi_message,
$res,
array( '%s', '%s', '%s' )
);
}
// 插入成功 推送并插日志表
if( $info ){
// 查找所有设备ID 上面接受过 每次登陆或者注册 都要重新获取一下reg_id
$find_sql = "SELECT device_id FROM $this->pi_bindinguser";
//设备ID的数组集合
$total_user = $this->wpdb->get_results( $find_sql, ARRAY_A );
// 找到所有的设备id 发送数据
foreach ($total_user as $key => $value) {
// 每个设备id
$device_id = $value['device_id'];
// 通过设备id 去查找 member_id 从而计算该用户的未读和已读
$sql = "SELECT member_id FROM $this->pi_bindinguser WHERE device_id = ". " '$device_id' ";
// 计算badge_num的数值
$member_id = $this->wpdb->get_var( $sql );
// 获取当前的状态为零 未读取的小红点
$total_sql = "SELECT count(id) FROM $this->pi_message_log WHERE member_id = $member_id AND status = 0" ;
//如果该用户消息为空的话 即默认为0开始
$badge_num = empty( $this->wpdb->get_var( $total_sql ) ) ? '0' : $this->wpdb->get_var( $total_sql );
$msg_id = $this->pi_push($device_id,$res['content'],$badge_num,$array);
// var_dump( $msg_id );
//推送成功之后 拿到msg_id 和 member_id 也就是消息id和用户id 两个对应的数据唯一 去存入消息列表 做核销使用
if( $msg_id ){
$time = date( "Y-m-d H:i:s" );
$info = $this->wpdb->insert(
$this->pi_message_log,
array('member_id'=>$member_id,'msg_id'=>$msg_id,'content'=>$res['content'],'create_date'=>$time,'push_type'=>$push_type),
array( '%s', '%s', '%s', '%s', '%s' )
);
}
}
return PI_Response::init( 0 );
}else{
return PI_Response::init( 1003 );
}
}
到此 推送和本地计算角标值也就差不多了。客户端的 badge 改动就要他们自己去掉 jpush 的接口了。因为每查看一次消息就去访问接口的,这样的话客户端和服务端的角标值的数值就对应上了,有点像 ajax 的无刷新删除
我是用蒲公英做的内测版 App 发布的。事先打包了 ipa 。这种情况的推送,必须要生产证书,也就是上面说的
'apns_production' => true,
推送成功的条件:设备id、正确的 AppKey master secret 、环境和对应的证书是否一致等。重要的事情说三遍 多看推送历史详情和社区
做完一套流程到后面才发现不需要自己控制消息日志,调用 jpush 的接口就可以去完成角标数值的增删设置、显示对应的小红点。我问老大,我们这样做是不是多余的。老大:相信极光,也相信我们自己。
「本文系极光征文 | 写写文章就能赢 Filco,岂不美滋滋的参赛文章」