本文目录导读:

我来详细介绍PHP项目对接APP推送消息的完整实现方案。
主流推送方案对比
第三方推送服务(推荐)
- 极光推送:支持Android和iOS
- 个推:国内主流选择
- 友盟+:阿里系产品
- 腾讯移动推送:TPNS
原生推送
- Android:Firebase Cloud Messaging (FCM)
- iOS:Apple Push Notification Service (APNs)
使用极光推送示例
安装SDK
composer require jpush/jpush
基础推送实现
<?php
namespace App\Services;
use JPush\Client;
class PushService
{
private $client;
public function __construct()
{
$appKey = 'your_app_key';
$masterSecret = 'your_master_secret';
$this->client = new Client($appKey, $masterSecret);
}
/**
* 推送给所有用户
*/
public function pushToAll($title, $content, $extras = [])
{
try {
$response = $this->client->push()
->setPlatform('all') // 全平台推送
->addAllAudience() // 所有用户
->setNotificationAlert($content)
->androidNotification($title, [
'title' => $title,
'extras' => $extras
])
->iosNotification($title, [
'title' => $title,
'extras' => $extras
])
->send();
return $response;
} catch (\Exception $e) {
throw new \Exception('推送失败: ' . $e->getMessage());
}
}
/**
* 推送给指定用户
*/
public function pushToUser($userId, $title, $content, $extras = [])
{
try {
$response = $this->client->push()
->setPlatform('all')
->addAlias($userId) // 使用别名推送给特定用户
->setNotificationAlert($content)
->androidNotification($title, [
'title' => $title,
'extras' => $extras
])
->iosNotification($title, [
'title' => $title,
'extras' => $extras
])
->send();
return $response;
} catch (\Exception $e) {
throw new \Exception('推送失败: ' . $e->getMessage());
}
}
/**
* 推送给标签用户
*/
public function pushByTag($tag, $title, $content, $extras = [])
{
try {
$response = $this->client->push()
->setPlatform('all')
->addTag($tag)
->setNotificationAlert($content)
->androidNotification($title, [
'title' => $title,
'extras' => $extras
])
->iosNotification($title, [
'title' => $title,
'extras' => $extras
])
->send();
return $response;
} catch (\Exception $e) {
throw new \Exception('推送失败: ' . $e->getMessage());
}
}
}
用户注册设备
<?php
namespace App\Http\Controllers;
use App\Models\UserDevice;
use Illuminate\Http\Request;
class DeviceController extends Controller
{
/**
* 注册设备token
*/
public function registerDevice(Request $request)
{
$validated = $request->validate([
'user_id' => 'required|integer',
'device_token' => 'required|string',
'platform' => 'required|in:ios,android',
'app_version' => 'nullable|string'
]);
// 保存设备信息
UserDevice::updateOrCreate(
['user_id' => $validated['user_id'], 'device_token' => $validated['device_token']],
[
'platform' => $validated['platform'],
'app_version' => $validated['app_version'] ?? null,
'last_active_at' => now()
]
);
return response()->json(['message' => '设备注册成功']);
}
}
使用FCM(Firebase Cloud Messaging)
安装SDK
composer require kreait/firebase-php
FCM推送实现
<?php
namespace App\Services;
use Kreait\Firebase\Factory;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Messaging\Notification;
class FcmService
{
private $messaging;
public function __construct()
{
$factory = (new Factory)
->withServiceAccount('/path/to/firebase_credentials.json');
$this->messaging = $factory->createMessaging();
}
/**
* 推送给指定设备
*/
public function sendToDevice($deviceToken, $title, $body, $data = [])
{
$message = CloudMessage::withTarget('token', $deviceToken)
->withNotification(Notification::create($title, $body))
->withData($data);
try {
$response = $this->messaging->send($message);
return $response;
} catch (\Exception $e) {
throw new \Exception('FCM推送失败: ' . $e->getMessage());
}
}
/**
* 推送给多个设备
*/
public function sendToMultipleDevices($deviceTokens, $title, $body, $data = [])
{
$messages = [];
foreach ($deviceTokens as $token) {
$messages[] = CloudMessage::withTarget('token', $token)
->withNotification(Notification::create($title, $body))
->withData($data);
}
try {
$response = $this->messaging->sendAll($messages);
return $response;
} catch (\Exception $e) {
throw new \Exception('批量推送失败: ' . $e->getMessage());
}
}
/**
* 推送给主题订阅者
*/
public function sendToTopic($topic, $title, $body, $data = [])
{
$message = CloudMessage::withTarget('topic', $topic)
->withNotification(Notification::create($title, $body))
->withData($data);
try {
$response = $this->messaging->send($message);
return $response;
} catch (\Exception $e) {
throw new \Exception('主题推送失败: ' . $e->getMessage());
}
}
}
使用个推
安装SDK
composer require getui/getui
个推推送实现
<?php
namespace App\Services;
use getui\Client\PushAPI;
use getui\Client\PushMessage;
use getui\Client\Target;
class GeTuiService
{
private $pushApi;
public function __construct()
{
$appId = 'your_app_id';
$appKey = 'your_app_key';
$masterSecret = 'your_master_secret';
$this->pushApi = new PushAPI($appId, $appKey, $masterSecret);
}
/**
* 推送给单个用户
*/
public function pushToSingle($cid, $title, $content, $payload = [])
{
$message = new PushMessage();
$message->setMsgType(PushMessage::MSG_TYPE_NOTIFICATION);
$message->setTitle($title);
$message->setContent($content);
$message->setPayload($payload);
$target = new Target();
$target->setCid($cid);
try {
$response = $this->pushApi->pushToSingle($target, $message);
return $response;
} catch (\Exception $e) {
throw new \Exception('个推推送失败: ' . $e->getMessage());
}
}
/**
* 推送给所有用户
*/
public function pushToAll($title, $content, $payload = [])
{
$message = new PushMessage();
$message->setMsgType(PushMessage::MSG_TYPE_NOTIFICATION);
$message->setTitle($title);
$message->setContent($content);
$message->setPayload($payload);
try {
$response = $this->pushApi->pushToAll($message);
return $response;
} catch (\Exception $e) {
throw new \Exception('群推失败: ' . $e->getMessage());
}
}
}
APNs原生推送(iOS)
<?php
namespace App\Services;
class ApnsService
{
private $pemFile;
private $topic;
public function __construct()
{
$this->pemFile = storage_path('app/apns.pem');
$this->topic = 'com.yourcompany.app';
}
/**
* 发送iOS推送
*/
public function send($deviceToken, $title, $body, $badge = 0, $sound = 'default')
{
$payload = json_encode([
'aps' => [
'alert' => [
'title' => $title,
'body' => $body
],
'badge' => $badge,
'sound' => $sound,
'content-available' => 1
]
]);
$url = 'https://api.push.apple.com/3/device/' . $deviceToken;
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'apns-topic: ' . $this->topic
],
CURLOPT_SSLCERT => $this->pemFile,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new \Exception('APNs推送失败,HTTP状态码: ' . $httpCode);
}
return $response;
}
}
使用场景示例(控制器)
<?php
namespace App\Http\Controllers;
use App\Services\PushService;
use App\Models\User;
use Illuminate\Http\Request;
class NotificationController extends Controller
{
private $pushService;
public function __construct(PushService $pushService)
{
$this->pushService = $pushService;
}
/**
* 发送订单通知
*/
public function sendOrderNotification(Request $request)
{
$validated = $request->validate([
'user_id' => 'required|integer',
'order_id' => 'required|integer',
'status' => 'required|string'
]);
$user = User::findOrFail($validated['user_id']);
$title = '订单通知';
$content = "您的订单 ({$validated['order_id']}) 状态已更新为:{$validated['status']}";
$extras = [
'type' => 'order_status',
'order_id' => $validated['order_id'],
'status' => $validated['status']
];
try {
$response = $this->pushService->pushToUser(
$user->id,
$title,
$content,
$extras
);
return response()->json([
'success' => true,
'message' => '推送成功',
'data' => $response
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => $e->getMessage()
], 500);
}
}
/**
* 发送活动通知(所有用户)
*/
public function sendActivityNotification(Request $request)
{
$validated = $request->validate([
'title' => 'required|string',
'content' => 'required|string',
'activity_id' => 'required|integer'
]);
try {
$extras = [
'type' => 'activity',
'activity_id' => $validated['activity_id']
];
$response = $this->pushService->pushToAll(
$validated['title'],
$validated['content'],
$extras
);
return response()->json([
'success' => true,
'message' => '群发推送成功'
]);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => $e->getMessage()
], 500);
}
}
}
注意事项
性能优化
- 使用消息队列处理推送(Redis、RabbitMQ)
- 批量推送时注意速率限制
- 缓存设备token信息
错误处理
// 处理无效token
public function handleInvalidToken($response)
{
if (isset($response['error'])) {
// 标记设备token无效
UserDevice::where('device_token', $response['failed_token'])
->update(['is_valid' => false]);
}
}
安全建议
- 使用HTTPS连接
- 证书定期更新
- 密钥存储在环境变量中
- 实现访问令牌验证
选择哪种方案取决于你的具体需求、预算和技术栈,对于国内项目,推荐使用极光或个推;国际项目则推荐FCM。