本文目录导读:

我来详细介绍PHP项目对接推送服务的方法,涵盖常见推送服务类型和具体实现方案。
常见推送服务类型
第三方推送服务
- 极光推送 - 国内主流
- 个推 - 覆盖广
- 友盟+ - 阿里旗下
- 信鸽/腾讯移动推送 - 腾讯系
平台原生推送
- APNs - Apple Push Notification service
- FCM - Firebase Cloud Messaging
实时通信推送
- WebSocket
- SSE (Server-Sent Events)
- 长轮询
PHP对接实现方案
使用第三方推送服务SDK
极光推送示例
// 1. 安装SDK
composer require jpush/jpush
// 2. 基础推送代码
<?php
require_once 'vendor/autoload.php';
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 pushNotification($title, $content, $audience = 'all') {
try {
$push = $this->client->push();
$push->setPlatform('all')
->addAllAudience()
->iosNotification($content, [
'title' => $title,
'sound' => 'default',
'badge' => '+1',
'extras' => ['key' => 'value']
])
->androidNotification($title, [
'title' => $title,
'builder_id' => 1,
'extras' => ['key' => 'value']
])
->message($content, [
'title' => $title,
'content_type' => 'text',
'extras' => ['key' => 'value']
]);
$response = $push->send();
return $response;
} catch (\JPush\Exceptions\APIConnectionException $e) {
// 网络连接错误
error_log('Push connection error: ' . $e->getMessage());
return false;
} catch (\JPush\Exceptions\APIRequestException $e) {
// API请求错误
error_log('Push API error: ' . $e->getMessage());
return false;
}
}
// 按标签推送
public function pushByTags($tags, $title, $content) {
$push = $this->client->push();
$push->setPlatform('all')
->addTag($tags)
->iosNotification($content, ['title' => $title])
->androidNotification($title, ['title' => $title]);
return $push->send();
}
// 推送统计
public function getPushReport($pushId) {
try {
$report = $this->client->report();
return $report->getReceived($pushId);
} catch (\Exception $e) {
return false;
}
}
}
// 使用示例
$push = new PushService();
$result = $push->pushNotification('新消息', '您有一条新通知');
个推推送示例
<?php
require_once 'vendor/autoload.php';
use Getui\IGtPush;
use Getui\IGtNotification;
use Getui\IGtSingleMessage;
class GetuiPushService {
private $push;
private $appId;
private $appKey;
private $masterSecret;
public function __construct() {
$this->appId = 'your_app_id';
$this->appKey = 'your_app_key';
$this->masterSecret = 'your_master_secret';
$host = 'https://api.getui.com';
$this->push = new IGtPush($host, $this->appKey, $this->masterSecret);
}
// 单推
public function pushToSingle($cid, $title, $content) {
$template = $this->createNotificationTemplate($title, $content);
$message = new IGtSingleMessage();
$message->setData($template);
$message->setOffline(true);
$message->setOfflineExpireTime(24 * 3600 * 1000); // 离线有效期
return $this->push->pushMessageToSingle($message, $cid);
}
// 群推
public function pushToList($cids, $title, $content) {
$template = $this->createNotificationTemplate($title, $content);
$message = new IGtListMessage();
$message->setData($template);
$message->setOffline(true);
$contentId = $this->push->getContentId($message, 'toList_task');
return $this->push->pushMessageToList($contentId, $cids);
}
private function createNotificationTemplate($title, $content) {
$template = new IGtNotification();
$template->setAppId($this->appId);
$template->setAppKey($this->appKey);
$template->setTitle($title);
$template->setText($content);
$template->setLogo('push.png');
$template->setLogoUrl('');
$template->setIsRing(true);
$template->setIsVibrate(true);
$template->setIsClearable(true);
$template->setTransmissionType(2);
$template->setTransmissionContent(json_encode([
'type' => 'message',
'data' => $content
]));
return $template;
}
}
使用cURL直接调用API
<?php
class PushApiClient {
private $apiUrl;
private $appKey;
private $appSecret;
public function __construct($config) {
$this->apiUrl = $config['api_url'];
$this->appKey = $config['app_key'];
$this->appSecret = $config['app_secret'];
}
// 通用API请求
private function request($endpoint, $data = []) {
$url = $this->apiUrl . $endpoint;
$headers = [
'Content-Type: application/json',
'Authorization: ' . $this->getAuthToken()
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode == 200) {
return json_decode($response, true);
}
return false;
}
private function getAuthToken() {
// 实现token获取逻辑
return base64_encode($this->appKey . ':' . $this->appSecret);
}
// 发送推送
public function sendPush($title, $content, $deviceTokens = []) {
$data = [
'title' => $title,
'content' => $content,
'device_tokens' => $deviceTokens,
'platform' => 'all'
];
return $this->request('/push/send', $data);
}
}
WebSocket推送
<?php
// 使用 Ratchet 库实现 WebSocket 服务器
// 安装: composer require cboden/ratchet
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class PushWebSocket implements MessageComponentInterface {
protected $clients;
protected $userConnections; // 用户ID -> 连接映射
public function __construct() {
$this->clients = new \SplObjectStorage;
$this->userConnections = [];
}
public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo "New connection: {$conn->resourceId}\n";
}
public function onMessage(ConnectionInterface $from, $msg) {
$data = json_decode($msg, true);
switch ($data['type']) {
case 'auth':
// 用户认证,绑定用户ID
$userId = $data['user_id'];
$this->userConnections[$userId] = $from;
$from->userId = $userId;
break;
case 'subscribe':
// 订阅特定频道
$channel = $data['channel'];
$from->channels[] = $channel;
break;
}
}
// 向特定用户推送
public function pushToUser($userId, $data) {
if (isset($this->userConnections[$userId])) {
$conn = $this->userConnections[$userId];
$conn->send(json_encode($data));
}
}
// 广播消息
public function broadcast($data) {
foreach ($this->clients as $client) {
$client->send(json_encode($data));
}
}
public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
// 清理用户连接
if (isset($conn->userId)) {
unset($this->userConnections[$conn->userId]);
}
echo "Connection {$conn->resourceId} disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "Error: {$e->getMessage()}\n";
$conn->close();
}
}
// WebSocket 服务启动脚本
// server.php
require 'vendor/autoload.php';
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use React\EventLoop\Factory;
$loop = Factory::create();
$pusher = new PushWebSocket();
// WebSocket服务器
$webSock = new React\Socket\Server('0.0.0.0:8080', $loop);
$webServer = new IoServer(
new HttpServer(
new WsServer(
$pusher
)
),
$webSock
);
// HTTP API服务器(用于内部推送调用)
$httpServer = new React\Http\Server($loop, function ($request, $response) use ($pusher) {
$body = $request->getBody();
$data = json_decode($body, true);
if ($data && isset($data['user_id'])) {
$pusher->pushToUser($data['user_id'], $data['message']);
$response->writeHead(200, ['Content-Type' => 'application/json']);
$response->end(json_encode(['status' => 'success']));
} else {
$response->writeHead(400);
$response->end('Bad Request');
}
});
$httpServer->listen('127.0.0.1:8081');
echo "WebSocket server started on port 8080\n";
echo "Internal API server started on port 8081\n";
$loop->run();
// PHP客户端调用推送
// push_client.php
function sendInternalPush($userId, $message) {
$ch = curl_init('http://127.0.0.1:8081');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'user_id' => $userId,
'message' => $message
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
curl_close($ch);
}
SSE (Server-Sent Events) 推送
<?php
// server_sse.php - SSE推送服务端
class SSEServer {
public function handle() {
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('Access-Control-Allow-Origin: *');
// 获取用户ID(通过token验证)
$userId = $this->authenticate();
// 创建数据库连接检查新消息
$db = new PDO('mysql:host=localhost;dbname=push', 'user', 'pass');
$lastCheck = time();
while (true) {
// 检查是否有新消息
$stmt = $db->prepare("SELECT * FROM messages WHERE user_id = ? AND created_at > ?");
$stmt->execute([$userId, date('Y-m-d H:i:s', $lastCheck)]);
$messages = $stmt->fetchAll();
foreach ($messages as $msg) {
// 发送SSE事件
echo "event: message\n";
echo "id: {$msg['id']}\n";
echo "data: " . json_encode($msg) . "\n\n";
ob_flush();
flush();
}
$lastCheck = time();
// 发送心跳
echo ": heartbeat\n\n";
ob_flush();
flush();
// 检查客户端是否断开
if (connection_aborted()) {
break;
}
sleep(1); // 间隔1秒检查
}
}
private function authenticate() {
// 实现身份验证逻辑
return 1; // 返回用户ID
}
}
// index.php - 入口
$sse = new SSEServer();
$sse->handle();
// 客户端JavaScript
/*
const eventSource = new EventSource('/sse/server_sse.php');
eventSource.addEventListener('message', function(e) {
const data = JSON.parse(e.data);
console.log('New message:', data);
});
eventSource.onerror = function(e) {
console.error('SSE error:', e);
eventSource.close();
};
*/
推送服务管理类
<?php
class PushManager {
private $config;
private $providers = [];
public function __construct($config) {
$this->config = $config;
$this->initProviders();
}
private function initProviders() {
// 初始化不同推送服务商
if (isset($this->config['jiguang'])) {
$this->providers['jiguang'] = new JiguangPush($this->config['jiguang']);
}
if (isset($this->config['getui'])) {
$this->providers['getui'] = new GetuiPush($this->config['getui']);
}
if (isset($this->config['websocket'])) {
$this->providers['websocket'] = new WebSocketPush($this->config['websocket']);
}
}
// 智能推送:根据用户设备选择最优通道
public function smartPush($userId, $title, $content, $options = []) {
$results = [];
// 获取用户设备信息
$devices = $this->getUserDevices($userId);
foreach ($devices as $device) {
switch ($device['platform']) {
case 'ios':
// iOS设备使用APNs
$results[] = $this->pushApns($device['token'], $title, $content);
break;
case 'android':
// Android设备使用FCM或第三方
$results[] = $this->pushFcm($device['token'], $title, $content);
break;
case 'web':
// Web端使用WebSocket或SSE
$results[] = $this->pushWebSocket($userId, $title, $content);
break;
}
}
// 记录推送日志
$this->logPush($userId, $title, $content, $results);
return $results;
}
// 消息队列处理(异步推送)
public function pushToQueue($userId, $title, $content) {
// 使用Redis队列
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$pushData = [
'user_id' => $userId,
'title' => $title,
'content' => $content,
'created_at' => time()
];
$redis->lPush('push_queue', json_encode($pushData));
return true;
}
// 处理队列中的推送
public function processQueue() {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
while ($data = $redis->rPop('push_queue')) {
$pushData = json_decode($data, true);
// 处理推送
$this->smartPush(
$pushData['user_id'],
$pushData['title'],
$pushData['content']
);
// 避免CPU占用过高
usleep(100000); // 0.1秒
}
}
// 推送失败重试机制
public function retryFailedPush($pushId) {
$failedPushes = $this->getFailedPushes();
foreach ($failedPushes as $push) {
if ($push['retry_count'] < 3) {
$result = $this->smartPush(
$push['user_id'],
$push['title'],
$push['content']
);
if ($result) {
$this->markPushSuccess($push['id']);
} else {
$this->incrementRetryCount($push['id']);
}
}
}
}
private function getUserDevices($userId) {
// 从数据库获取用户设备信息
$db = new PDO('mysql:host=localhost;dbname=your_db', 'user', 'pass');
$stmt = $db->prepare("SELECT * FROM user_devices WHERE user_id = ?");
$stmt->execute([$userId]);
return $stmt->fetchAll();
}
private function logPush($userId, $title, $content, $results) {
// 记录推送日志到数据库
$db = new PDO('mysql:host=localhost;dbname=your_db', 'user', 'pass');
$stmt = $db->prepare("
INSERT INTO push_logs (user_id, title, content, results, created_at)
VALUES (?, ?, ?, ?, NOW())
");
$stmt->execute([$userId, $title, $content, json_encode($results)]);
}
}
最佳实践建议
错误处理
try {
$result = $pushService->pushNotification($title, $content);
} catch (Exception $e) {
// 记录错误日志
Log::error('Push failed: ' . $e->getMessage());
// 放入重试队列
Queue::push('RetryPush', [
'title' => $title,
'content' => $content,
'error' => $e->getMessage()
]);
}
速度控制
// 使用令牌桶算法控制推送速率
class RateLimiter {
private $redis;
private $maxTokens;
private $refillRate;
public function __construct($maxTokens = 100, $refillRate = 10) {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
$this->maxTokens = $maxTokens;
$this->refillRate = $refillRate;
}
public function acquire($key) {
$tokens = $this->redis->get("rate_limit:$key");
if ($tokens === false) {
$this->redis->set("rate_limit:$key", $this->maxTokens - 1);
$this->redis->expire("rate_limit:$key", 1);
return true;
}
if ($tokens > 0) {
$this->redis->decr("rate_limit:$key");
return true;
}
return false;
}
}
推送模板管理
class PushTemplate {
private $templates = [];
public function __construct() {
$this->loadTemplates();
}
public function render($templateName, $data = []) {
if (!isset($this->templates[$templateName])) {
throw new Exception("Template not found: $templateName");
}
$template = $this->templates[$templateName];
// 替换变量
foreach ($data as $key => $value) {
$template['title'] = str_replace("{{$key}}", $value, $template['title']);
$template['content'] = str_replace("{{$key}}", $value, $template['content']);
}
return $template;
}
private function loadTemplates() {
// 从数据库或配置文件加载模板
$this->templates = [
'order_notify' => [
'title' => '订单通知',
'content' => '您的订单{{order_no}}状态已更新为{{status}}'
],
'new_message' => [
'title' => '新消息',
'content' => '您收到来自{{sender}}的新消息'
]
];
}
}
配置文件示例
// config/push.php
return [
'default' => 'jiguang',
'providers' => [
'jiguang' => [
'app_key' => env('JPUSH_APP_KEY'),
'master_secret' => env('JPUSH_MASTER_SECRET'),
'apns_production' => env('APP_ENV') === 'production'
],
'getui' => [
'app_id' => env('GETUI_APP_ID'),
'app_key' => env('GETUI_APP_KEY'),
'master_secret' => env('GETUI_MASTER_SECRET')
],
'apns' => [
'certificate' => storage_path('apns-cert.pem'),
'passphrase' => env('APNS_PASSPHRASE'),
'sandbox' => env('APP_ENV') !== 'production'
],
'fcm' => [
'server_key' => env('FCM_SERVER_KEY'),
'sender_id' => env('FCM_SENDER_ID')
]
],
'rate_limit' => [
'max_per_second' => 100,
'max_per_minute' => 5000
],
'retry' => [
'max_attempts' => 3,
'delay' => 300 // 5分钟
]
];
选择推送方案时,建议根据项目规模、用户量、实时性要求和预算来综合考虑,对于大多数PHP项目,使用第三方推送服务是最快速可靠的方案。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播