如何使用PHP向iOS设备推送通知?服务器搭建方法咨询
PHP 搭建 iOS 推送通知服务器指南(针对已获取设备令牌场景)
嘿,既然你已经在Swift 4 + Xcode 10环境下用UserNotifications完成了设备注册,拿到了设备令牌,那搭建PHP推送服务器其实就差最后几步了,我一步步给你捋清楚:
一、先搞定APNs推送证书转换
苹果的APNs服务需要证书验证,你应该已经在开发者后台创建了推送证书(区分开发/生产环境),接下来要把导出的.p12文件转换成PHP能识别的.pem格式:
- 打开终端,执行这条命令(替换成你的证书路径):
openssl pkcs12 -in your_push_certificate.p12 -out apns_cert.pem -nodes -clcerts - 如果你的
.p12设置了密码,执行时会提示输入,记得后续PHP代码里要对应配置。 - 注意:开发环境用Sandbox证书,生产环境用Production证书,别搞混!
二、PHP推送代码实现(两种方式)
方式1:传统二进制协议(兼容旧环境)
这种方式用socket连接APNs服务器,适合没有HTTP/2支持的环境:
<?php // 替换成你获取到的设备令牌(记得去掉空格) $deviceToken = 'abc123456789abc123456789abc123456789abc123456789abc123456789abc1'; // 你的pem证书路径 $certificatePath = './apns_cert.pem'; // 推送内容,遵循APNs格式 $payload = json_encode([ 'aps' => [ 'alert' => [ 'title' => '来自PHP的测试推送', 'body' => '这是一条测试通知!' ], 'sound' => 'default', 'badge' => 1 ] ]); // 选择环境:开发环境用sandbox,生产环境切换到下面的地址 $apnsServer = 'ssl://gateway.sandbox.push.apple.com:2195'; // $apnsServer = 'ssl://gateway.push.apple.com:2195'; // 生产环境 // 创建SSL上下文 $ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'local_cert', $certificatePath); // 如果证书有密码,解开下面这行并填写密码 // stream_context_set_option($ctx, 'ssl', 'passphrase', 'your_cert_password'); // 连接APNs服务器 $fp = stream_socket_client( $apnsServer, $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx ); if (!$fp) { exit("连接APNs失败: $err $errstr" . PHP_EOL); } echo '成功连接到APNs服务器' . PHP_EOL; // 构建二进制推送消息 $msg = chr(0) . pack('n', 32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack('n', strlen($payload)) . $payload; // 发送推送 $result = fwrite($fp, $msg, strlen($msg)); if (!$result) { echo '推送发送失败' . PHP_EOL; } else { echo '推送发送成功!' . PHP_EOL; } // 关闭连接 fclose($fp); ?>
方式2:HTTP/2协议(苹果推荐)
这种方式更现代,能返回详细的错误信息,需要你的PHP环境支持HTTP/2(需安装nghttp2扩展,curl版本>=7.47.0):
<?php $deviceToken = 'abc123456789abc123456789abc123456789abc123456789abc123456789abc1'; $certPath = './apns_cert.pem'; $certPass = 'your_cert_password'; // 证书密码(如果有的话) $bundleId = 'com.your.app.bundleid'; // 替换成你的App Bundle ID // 推送内容 $payload = json_encode([ 'aps' => [ 'alert' => 'PHP HTTP/2测试推送', 'sound' => 'default' ] ]); // 环境URL:开发环境用development,生产环境用push $url = "https://api.development.push.apple.com/3/device/$deviceToken"; // $url = "https://api.push.apple.com/3/device/$deviceToken"; // 生产环境 // 请求头 $headers = [ "apns-topic: $bundleId", 'Content-Type: application/json' ]; // 初始化curl $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_SSLCERT, $certPath); curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $certPass); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); // 启用HTTP/2 // 执行请求 $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 处理结果 if ($httpCode == 200) { echo '推送成功!'; } else { echo "推送失败,HTTP状态码: $httpCode,响应信息: $response"; } curl_close($ch); ?>
三、测试必看注意事项
- 设备令牌格式:确保你上传到服务器的令牌是十六进制字符串(Swift里可以用
deviceToken.map { String(format: "%02.2hhx", $0) }.joined()转换),不要有空格或多余字符。 - 环境匹配:开发环境用Sandbox证书+测试设备(安装开发包),生产环境用Production证书+上架/Ad Hoc包,混配会导致推送失败。
- 端口开放:服务器要开放2195端口(二进制协议)或443端口(HTTP/2协议),避免防火墙拦截。
- PHP环境检查:确保curl扩展已启用,HTTP/2方式需要额外安装
nghttp2扩展。
四、Swift端小补充(确认配置)
你已经完成了UserNotifications注册,再检查下这两点:
- 已经请求了通知权限:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 请求通知权限 UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in if granted { DispatchQueue.main.async { application.registerForRemoteNotifications() } } } return true }
- 正确获取设备令牌并上传:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let tokenString = deviceToken.map { String(format: "%02.2hhx", $0) }.joined() print("设备令牌:\(tokenString)") // 这里把tokenString上传到你的PHP服务器存储 }
内容的提问来源于stack exchange,提问作者Ryland Goldman
相关产品推荐
相关产品推荐

