You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP实现iOS推送通知失效 求适配新协议的可行代码及方案

iOS推送失效调试方案(适配APNs HTTP/2协议)

为什么需要HTTP/2?

Apple从iOS 10开始强制要求APNs推送使用HTTP/2协议,替代旧的二进制协议。HTTP/2提供更明确的错误反馈、多路复用能力,是当前唯一官方支持的推送协议,这也是你必须采用它的核心原因。

第一步:用openssl s_client命令行调试

既然服务器curl不支持SSL,先通过openssl s_client验证服务器到APNs的连通性,同时模拟推送请求:

1. 验证HTTP/2连接

执行以下命令(替换证书路径,开发环境替换为sandbox地址):

openssl s_client -connect api.push.apple.com:443 -cert /path/to/your/certificate.pem -key /path/to/your/private-key.pem -alpn h2

若连接成功,输出中会包含ALPN protocol: h2,说明服务器支持HTTP/2并能和APNs建立SSL连接。

2. 发送测试推送请求

连接成功后,在交互模式下输入以下HTTP/2请求(替换device-token、topic和推送内容):

POST /3/device/<device-token> HTTP/2
Host: api.push.apple.com
apns-topic: <your-app-bundle-id>

{
  "aps": {
    "alert": "测试推送",
    "sound": "default"
  }
}

注:证书验证模式下无需Authorization头,APNs会通过SSL证书识别应用。输入完后按两次回车发送请求,观察返回状态码:

  • 200:推送成功
  • 400/403/410等:对应具体错误,可查阅Apple官方文档定位问题

第二步:PHP调试代码(适配HTTP/2 + OpenSSL)

以下是基于PHP openssl扩展的APNs推送代码,无需依赖curl的HTTP2支持,直接通过SSL连接发送HTTP/2请求:

<?php
// 配置参数
$isProduction = true; // 生产环境设为true,开发环境设为false
$deviceToken = "你的设备推送token";
$bundleId = "你的App Bundle ID";
$certPath = "/path/to/your/certificate.pem";
$certPassphrase = "证书密码(无则留空)";

// 选择APNs服务器地址
$apnsHost = $isProduction ? "api.push.apple.com" : "api.sandbox.push.apple.com";
$apnsPort = 443;

// 构建推送内容
$payload = json_encode([
    "aps" => [
        "alert" => "PHP调试测试推送",
        "sound" => "default"
    ]
]);

// 初始化SSL上下文,指定HTTP/2协议
$context = stream_context_create([
    "ssl" => [
        "local_cert" => $certPath,
        "passphrase" => $certPassphrase,
        "verify_peer" => true,
        "verify_peer_name" => true,
        "alpn_protocols" => ["h2"]
    ]
]);

// 建立SSL连接
$socket = stream_socket_client(
    "ssl://{$apnsHost}:{$apnsPort}",
    $errno,
    $errstr,
    60,
    STREAM_CLIENT_CONNECT,
    $context
);

if (!$socket) {
    die("连接失败: {$errstr} ({$errno})");
}

// 构建HTTP/2请求
$request = "POST /3/device/{$deviceToken} HTTP/2\r\n";
$request .= "Host: {$apnsHost}\r\n";
$request .= "apns-topic: {$bundleId}\r\n";
$request .= "Content-Length: " . strlen($payload) . "\r\n\r\n";
$request .= $payload;

// 发送请求并读取响应
fwrite($socket, $request);
$response = fread($socket, 4096);
echo "响应内容:\n" . $response . "\n";

// 关闭连接
fclose($socket);
?>

代码说明:

  • 用stream_socket_client建立SSL连接,通过alpn_protocols强制使用HTTP/2
  • 直接构建HTTP/2格式请求,避免依赖curl的HTTP2扩展支持
  • 响应中包含的HTTP状态码和错误信息,可直接用于定位问题

常见排查点

  • 连接失败:检查证书路径、密码是否正确,服务器防火墙是否开放443端口出站权限
  • 返回403:确认证书绑定的Bundle ID与推送topic一致,证书是否过期
  • 返回410:设备token已失效,需重新获取用户设备的推送token

内容的提问来源于stack exchange,提问作者Ondrej

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 02:18:19