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

iOS APNs推送返回发送成功但移动端无法接收的问题求助

APNs 显示发送成功但收不到的排查方向

核心误区澄清

你现在代码返回的「Message successfully delivered」根本不能代表APNs已经成功处理了你的推送请求。旧版基于2195端口的二进制帧协议是单向传输逻辑,fwrite只要把数据塞进本地TCP缓冲区、没碰到连接断开的情况,就会返回写入成功——哪怕苹果服务端已经把你的请求静默丢了,代码也不会有任何异常提示。

逐一核对的故障点

  • 环境匹配类问题
    • 先查deviceToken对应的环境:沙盒网关只认开发调试包生成的token,如果你的测试token是从TestFlight、Ad-Hoc、正式安装包里拿的生产环境值,往沙盒网关发请求,苹果会直接丢包不回应。反过来拿沙盒token发生产网关,也会被静默丢弃。
    • 不要只看证书文件的过期时间:哪怕pem文件显示有效期到2021年12月,也要确认证书没有被提前吊销、对应的App ID推送权限没有被关闭、代码读的pem文件路径和你预期的一致(很多时候因为相对路径配错,实际加载的是早就作废的旧证书)。
    • 匹配你提到的故障时间点:苹果在2021年4月下旬逐步关停旧版2195端口的二进制协议服务,现在哪怕TCP连接能正常建立、数据能写进去,服务端也不会再处理这些旧协议的请求,刚好和你说的4月23日开始失效的时间线对上。
  • 代码本身的逻辑漏洞
    • 你的代码开了STREAM_CLIENT_PERSISTENT持久化连接:如果之前的连接已经被苹果服务端断开,PHP会复用这个已经失效的句柄,这时候往句柄里写数据当然返回成功,但实际数据根本到不了苹果那边。
    • 完全没读服务端的错误返回:旧协议在遇到无效token、格式错的payload、不合法的帧结构时,会在关连接前返回一个8字节的错误标识,你现在写完数据就直接fclose,根本拿不到这些错误信息,自然一直以为发送成功了。
    • 检查payload长度和格式:旧协议单帧最多支持256字节的payload,超了就会被丢;还要确保json是严格UTF-8编码,没有转义错误的特殊字符导致解析失败。
  • 客户端侧的拦截问题
    • 确认测试手机上对应App的通知权限是开着的,没有被专注模式、系统通知拦截规则挡住。

快速验证的修复步骤

  1. 先把STREAM_CLIENT_PERSISTENT参数去掉,每次发推送都新建独立连接,先排除持久化句柄失效导致的假成功问题。
  2. 写完数据之后别立刻关连接,留1-2秒的时间窗口读一下返回值,对照官方公开的APNs错误码就能定位具体是哪块出问题。
  3. 逐步把旧版二进制协议的实现,迁移到官方现在要求的HTTP/2协议接口(走443端口),迁完之后可以拿到明确的HTTP状态码和错误详情,不会再出现这种“发出去了但没人收到也不报错”的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 04:54:00