的APN邮件传递,但iOS设备上没有收到 [英] APNs messages are delivered but not received on iOS device

查看:272
本文介绍了的APN邮件传递,但iOS设备上没有收到的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经设置为指出/苹果推荐prevent DoS检测和认证工作持有的开放连接到的APN转发/调度服务...

我成功连接和邮件发送成功,但消息不iOS设备(iPhone)...(?!?)发送的字节数等于(字节)的数目的fwrite返回上接收。

最后,这些消息可能包含国家特定的字符。在中的APN如何处理这个问题?而如何把这个人物被发送到服务器的APN?

我试图具有和不转发业务,但没有运气。 : - (

到日志所有来电在code片段被删除,以避免混乱。这意味着,粘贴日志消息不能被直接映射到code片段,但它应该有可能从那里日志消息来猜测。

请帮我就这些问题。
在此先感谢

的连接以这种方式进行:

  $ CTX = stream_context_create();
stream_context_set_option($ CTX,SSL,的local_cert',​​$证书路径);
stream_context_set_option($ CTX,'SSL','密​​码',$密码);
$这个 - > apn_link =在stream_socket_client($网址,$犯错,$ errstr,60,STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT,$ CTX);
/ * ... * /

在一个循环,在插座上监听的转发服务:

 的foreach($改变$ changed_socket){
    而(使用isset($ changed_socket)及&放大器; socket_recv($ changed_socket,$ BUF,1024,0)> = 1)
    {
        $ BUF =修剪($ BUF);
        如果($ BUF!=''){
            $这个 - > msg2apn($ BUF);
        }
    }
}
/ * ... * /

另外我用这种方式发送邮件:

 公共职能msg2apn($味精){
如果(使用isset($这个 - > apn_link)){
    而(!$结果= FWRITE($这个 - > apn_link,$味精,strlen的($味精))){
        usleep(400000); // 400毫秒
    }    如果($结果){
        fflush($这个 - > apn_link);
        返回True;
    }
}
}

发送到转发服务消息:

 私有函数send_pn_iosproxy($味精){
    $地址= IOS_APNPROXY_HOST;
    $端口= IOS_APNPROXY_PORT;
    $计划生育=的fsockopen($地址,端口$);
    如果(!$ FP){
        ELOG(连接到[。$地址:$口]不能成立);
        返回False;
    }
    $结果=的fwrite($计划生育,$味精,strlen的($味精));    如果(使用isset($ FP))fflush($ FP);
    如果(使用isset($ FP))FCLOSE($ FP);
    返回True;
}

有关以下列方式产生消息的每个设备的令牌:

  $负载='{APS:{警告:'$消息['消息']'。,徽章:1,声音:默认}}';的foreach($ deviceTokens为$ deviceToken){
//生成二进制通知
$味精= CHR(0)。包('N',32)。 base64_de code($ deviceToken)。包('N',strlen的($有效载荷))。 $有效载荷;//看到上面的函数
$结果= $这个 - > send_pn_iosproxy($味精);如果($结果){
    ILOG(消息传递);
    DLOG(DeviceToken [$ deviceToken],有效载荷[$净荷]);
}其他{
    wlog(消息不正确传递);
    DLOG(消息[$ MSG]);
    DLOG(DeviceToken [$ deviceToken],有效载荷[$净荷]);
}
}

登录从logdisp消息是从转发服务,同时从日志的日志消息来自APP- /网络服务器。 Web服务器使用127.0.0.1/localhost因此,Web服务器和转发服务器托管在同一台物理计算机上连接到转发服务。

  [2015年8月27日11时19分03秒] log.DEBUG:PN :: send_pn_ios()[] []
[2015年8月27日11时19分03秒] log.DEBUG:PN :: send_pn_iosproxy()[] []
[2015年8月27日11时19分03秒] log.INFO:发表留言[] []
[2015年8月27日11时19分03秒] logdisp.DEBUG:客户端[127.0.0.1]连接[] []
[2015年8月27日11时19分03秒] log.DEBUG:DeviceToken [djYBbJepT8NOPKgLd5FoGOog9jxY8LcpQhCGaXAkqy0 =],有效载荷[{APS:{警告:信息,徽章:1,声音: 默认}}] [] []
[2015年8月27日11时19分03秒] logdisp.DEBUG:消息BUF [... {APS:{警告:信息,徽章:1,声音:默认从IP [127.0.0.1] [] []}}]
[2015年8月27日11时19分03秒] log.DEBUG:PN :: send_pn_iosproxy()[] []
[2015年8月27日11时19分03秒] logdisp.DEBUG:调度员:: msg2apn()[] []
[2015年8月27日11时19分03秒] log.INFO:发表留言[] []
[2015年8月27日11时19分03秒] logdisp.DEBUG:成功msg2apn,书面[107],发[107] [] []
[2015年8月27日11时19分03秒] log.DEBUG:DeviceToken [7FH3vRMfmb3qRBOaKY30GT / + 82jU / 6kx7RhBJq2Ihw8 =],有效载荷[{APS:{警告:信息,徽章:1 声音:默认}}] [] []
[2015年8月27日11时19分03秒] log.DEBUG:PN :: send_pn_iosproxy()[] []
[2015年8月27日11时19分03秒] log.INFO:发表留言[] []
[2015年8月27日11时19分03秒] log.DEBUG:DeviceToken [B + 20wASQBp9lD08l1 + EY3CHJjcCl1UBWNmSeI1c9ouQ =],有效载荷[{APS:{警告:信息,徽章:1 声音:默认}}] [] []
[2015年8月27日11时19分03秒] log.DEBUG:PN :: send_pn_iosproxy()[] []
[2015年8月27日11时19分03秒] log.INFO:发表留言[] []
[2015年8月27日11时19分03秒] log.DEBUG:DeviceToken [Yya0lH080lz6fL2B / 1UexOenBLyAJIp3zgSGgV9F5ms =],有效载荷[{APS:{警告:信息,徽章:1,声音:默认}}] [] []
[2015年8月27日11时19分04秒] logdisp.DEBUG:客户端[127.0.0.1]连接[] []
[2015年8月27日11时19分04秒] logdisp.DEBUG:消息BUF [... {APS:{警告:信息,徽章:1,声音:默认从IP [127.0.0.1] [] []}}]
[2015年8月27日11时19分04秒] logdisp.DEBUG:调度员:: msg2apn()[] []
[2015年8月27日11时19分04秒] logdisp.DEBUG:成功msg2apn,书面[107],发[107] [] []
[2015年8月27日11时19分05秒] logdisp.DEBUG:客户端[127.0.0.1]连接[] []
[2015年8月27日11时19分05秒] logdisp.DEBUG:消息BUF [... {APS:{警告:信息,徽章:1,声音:默认从IP [127.0.0.1] [] []}}]
[2015年8月27日11时19分05秒] logdisp.DEBUG:调度员:: msg2apn()[] []
[2015年8月27日11时19分05秒] logdisp.DEBUG:成功msg2apn,书面[107],发[107] [] []
[2015年8月27日11时19分07秒] logdisp.DEBUG:客户端[127.0.0.1]连接[] []
[2015年8月27日11时19分07秒] logdisp.DEBUG:消息BUF [... {APS:{警告:信息,徽章:1,声音:默认从IP [127.0.0.1] [] []}}]
[2015年8月27日11时19分07秒] logdisp.DEBUG:调度员:: msg2apn()[] []
[2015年8月27日11时19分07秒] logdisp.DEBUG:成功msg2apn,书面[107],发[107] [] []

我试图发送有效载荷两种:

  {APS:{警告:信息,徽章:1,声音:默认}}
{APS:{警报:{称号:我的标题,体:我的消息},徽章:2,声音:默认}}

重新生成证书之后,连接时我现在得到以下错误:

  [流浪汉@服务器后端的SRC] $ PHP -f dispatcher.php
日志路径:[/srv/backend/log/log.txt]日志级别:[0]
绑定信息:地址[127.0.0.1],口岸[6060]
连接到[SSL://gateway.push.apple.com:2195],使用证书[/srv/backend/htdocs/ios_distribution.pem]和密码[?]
PHP的警告:在stream_socket_client():未能线182启用/vagrant/backend-sr​​c/dispatcher.php加密
PHP的警告:在stream_socket_client():无法连接到SSL:在/vagrant/backend-sr​​c/dispatcher.php 2195(未知错误)线182://gateway.push.apple.com
警告:在stream_socket_client():无法连接到SSL:在/vagrant/backend-sr​​c/dispatcher.php 2195(未知错误)线182://gateway.push.apple.com
连接失败的错误[0]到网址[SSL://gateway.push.apple.com:2195]与证书模板[/srv/backend/htdocs/ios_distribution.pem]

我现在能够连接!这里的原因很简单。该证书的路径是不正确的。不过推送通知仍然没有使用新证书的设备上接收。

该应用是否需要发布新的证书/发布之前,将工作?无论是发展还是生产都收到的消息装置???

最后,它成功接收为沙盒和生产/特设令牌消息。

  // 64个字符令牌
//沙箱和生产令牌具有相同的长度和
//他们不能区分
$ deviceToken ='1234567890123456789012345678901234567890123456789012345678901234';$身体['APS'] =阵列('警报'=>样品信息,声音= GT;'默认');
$有效载荷= json_en code($体);$ deviceToken = str_replace函数('','',$ deviceToken);
$味精= CHR(0)。包('N',32)。包(H *',$ deviceToken)。包('N',strlen的($有效载荷))。 $有效载荷;FWRITE($ apn_link,$味精,strlen的($味精));
fflush($ apn_link);

不要在生产混合沙盒和生产设备令牌!

的APN生产环境不允许沙箱令牌
它静静地停止传递信息到生产令牌时
沙盒令牌已被使用。


解决方案

  // 64个字符令牌
//沙箱和生产令牌具有相同的长度和
//他们不能区分
$ deviceToken ='1234567890123456789012345678901234567890123456789012345678901234';$身体['APS'] =阵列('警报'=>样品信息,声音= GT;'默认');
$有效载荷= json_en code($体);$ deviceToken = str_replace函数('','',$ deviceToken);
$味精= CHR(0)。包('N',32)。包(H *',$ deviceToken)。包('N',strlen的($有效载荷))。 $有效载荷;FWRITE($ apn_link,$味精,strlen的($味精));
fflush($ apn_link);

不要在生产混合沙盒和生产设备令牌!

该APN生产环境不允许沙盒令牌和它静静地停在沙盒中的令牌已被用来传递信息到生产标记。

I have set up a forwarding / dispatch service which holds an open connection to the APNs as stated / recommended by Apple to prevent DoS detection and the certificate is working...

I am connected successfully and messages are sent successfully, but messages are not received on the iOS device (iPhone)... (?!?) The number of bytes sent are equal to the number (of bytes) fwrite returns.

Finally, the messages might contain country specific characters. How the the APNs handle that? and how should this characters be sent to the APNs server?

I have tried both with and without the forwarding service, but without luck. :-(

All calls to the log are removed in the code snippets to avoid confusing. This means that the log messages pasted cannot be mapped directly into the code snippets, but it should be possible to "guess" from where log messages come.

Please help me regarding these issues. Thanks in advance

The connection is made in this way:

$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $certPath);
stream_context_set_option($ctx, 'ssl', 'passphrase', $passPhrase);
$this->apn_link = stream_socket_client($url, $err, $errstr, 60,                                       STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT, $ctx);
/* ... */

Inside a loop that listens on the socket on the forwarding service:

foreach ($changed as $changed_socket) {
    while(isset($changed_socket) && socket_recv($changed_socket, $buf, 1024, 0) >= 1)
    {
        $buf = trim($buf);
        if ($buf != '') {
            $this->msg2apn($buf);
        }
    }
}
/* ... */

Further I send messages in this way:

public function msg2apn($msg) {
if (isset($this->apn_link)) {
    while(!$result = fwrite($this->apn_link, $msg, strlen($msg))) {
        usleep(400000); //400 msec
    }

    if ($result) {
        fflush($this->apn_link);
        return True;
    }
}
}

Messages sent to the forwarding service:

private function send_pn_iosproxy($msg) {
    $address = IOS_APNPROXY_HOST;
    $port = IOS_APNPROXY_PORT;
    $fp = fsockopen($address,$port);
    if (!$fp) {
        elog("Connection to [".$address.":".$port."] could not be established");
        return False;
    }
    $result = fwrite($fp, $msg, strlen($msg));

    if (isset($fp)) fflush($fp);
    if (isset($fp)) fclose($fp);
    return True;
}

For each device token a message is generated in the following way:

$payload = '{"aps":{"alert":"'.$message['message'].'","badge" : "1","sound":"default"}}';

foreach($deviceTokens as $deviceToken) {
// Build the binary notification
$msg = chr(0) . pack('n', 32) . base64_decode($deviceToken) . pack('n',    strlen($payload)) . $payload;

// see function above
$result = $this->send_pn_iosproxy($msg);

if ($result) {
    ilog("Message delivered");
    dlog("DeviceToken[$deviceToken], Payload[$payload]");
} else {
    wlog("Message not properly delivered");
    dlog("Msg[$msg]");
    dlog("DeviceToken[$deviceToken], Payload[$payload]");
}
}

Log messages from logdisp are from the forwarding service, while log messages from the log are from the app-/web server. The web server connects to the forwarding service using 127.0.0.1/localhost hence the web server and the forwarding server is hosted on the same physical computer.

[2015-08-27 11:19:03] log.DEBUG: pn::send_pn_ios()  [] []
[2015-08-27 11:19:03] log.DEBUG: pn::send_pn_iosproxy()  [] []
[2015-08-27 11:19:03] log.INFO: Message delivered  [] []
[2015-08-27 11:19:03] logdisp.DEBUG: Client [127.0.0.1] connected [] []
[2015-08-27 11:19:03] log.DEBUG: DeviceToken[djYBbJepT8NOPKgLd5FoGOog9jxY8LcpQhCGaXAkqy0=], Payload[{"aps":{"alert":"message","badge" : "1","sound":"default"}}]  [] []
[2015-08-27 11:19:03] logdisp.DEBUG: Message buf[...{"aps":{"alert":"message","badge" : "1","sound":"default"}}] from ip[127.0.0.1]  [] []
[2015-08-27 11:19:03] log.DEBUG: pn::send_pn_iosproxy()  [] []
[2015-08-27 11:19:03] logdisp.DEBUG: dispatcher::msg2apn() [] []
[2015-08-27 11:19:03] log.INFO: Message delivered  [] []
[2015-08-27 11:19:03] logdisp.DEBUG: SUCCESS msg2apn, written[107], sent[107] [] []
[2015-08-27 11:19:03] log.DEBUG: DeviceToken[7FH3vRMfmb3qRBOaKY30GT/+82jU/6kx7RhBJq2Ihw8=], Payload[{"aps":{"alert":"message","badge" : "1","sound":"default"}}]  [] []
[2015-08-27 11:19:03] log.DEBUG: pn::send_pn_iosproxy()  [] []
[2015-08-27 11:19:03] log.INFO: Message delivered  [] []
[2015-08-27 11:19:03] log.DEBUG: DeviceToken[b+20wASQBp9lD08l1+EY3CHJjcCl1UBWNmSeI1c9ouQ=], Payload[{"aps":{"alert":"message","badge" : "1","sound":"default"}}]  [] []
[2015-08-27 11:19:03] log.DEBUG: pn::send_pn_iosproxy()  [] []
[2015-08-27 11:19:03] log.INFO: Message delivered  [] []
[2015-08-27 11:19:03] log.DEBUG: DeviceToken[Yya0lH080lz6fL2B/1UexOenBLyAJIp3zgSGgV9F5ms=], Payload[{"aps":{"alert":"message","badge" : "1","sound":"default"}}]  [] []
[2015-08-27 11:19:04] logdisp.DEBUG: Client [127.0.0.1] connected [] []
[2015-08-27 11:19:04] logdisp.DEBUG: Message buf[...{"aps":{"alert":"message","badge" : "1","sound":"default"}}] from ip[127.0.0.1]  [] []
[2015-08-27 11:19:04] logdisp.DEBUG: dispatcher::msg2apn() [] []
[2015-08-27 11:19:04] logdisp.DEBUG: SUCCESS msg2apn, written[107], sent[107] [] []
[2015-08-27 11:19:05] logdisp.DEBUG: Client [127.0.0.1] connected [] []
[2015-08-27 11:19:05] logdisp.DEBUG: Message buf[...{"aps":{"alert":"message","badge" : "1","sound":"default"}}] from ip[127.0.0.1]  [] []
[2015-08-27 11:19:05] logdisp.DEBUG: dispatcher::msg2apn() [] []
[2015-08-27 11:19:05] logdisp.DEBUG: SUCCESS msg2apn, written[107], sent[107] [] []
[2015-08-27 11:19:07] logdisp.DEBUG: Client [127.0.0.1] connected [] []
[2015-08-27 11:19:07] logdisp.DEBUG: Message buf[...{"aps":{"alert":"message","badge" : "1","sound":"default"}}] from ip[127.0.0.1]  [] []
[2015-08-27 11:19:07] logdisp.DEBUG: dispatcher::msg2apn() [] []
[2015-08-27 11:19:07] logdisp.DEBUG: SUCCESS msg2apn, written[107], sent[107] [] []

I tried to sent two kinds of payload:

{"aps" : {"alert" : "message","badge" : "1","sound" : "default"}} 
{"aps" : { "alert" : { "title" : "My Title", "body" : "My Message" }, "badge" : 2, "sound" : "default" } }

After regenerating the certificates, I do now get the following errors when connecting:

[vagrant@server backend-src]$ php -f dispatcher.php
Log path: [/srv/backend/log/log.txt], Log level: [0],
Binding info: address[127.0.0.1], port[6060]
Connecting to [ssl://gateway.push.apple.com:2195], using certificate [/srv/backend/htdocs/ios_distribution.pem] and passphrase[?]
PHP Warning:  stream_socket_client(): Failed to enable crypto in /vagrant/backend-src/dispatcher.php on line 182
PHP Warning:  stream_socket_client(): unable to connect to ssl://gateway.push.apple.com:2195 (Unknown error) in /vagrant/backend-src/dispatcher.php on line 182
Warning: stream_socket_client(): unable to connect to ssl://gateway.push.apple.com:2195 (Unknown error) in /vagrant/backend-src/dispatcher.php on line 182
Connect failed error[0 ] to url [ssl://gateway.push.apple.com:2195] with certicate [/srv/backend/htdocs/ios_distribution.pem]

I am now able to connect! The reason here was simple. The path to the certificates was incorrect. However push notifications are still not received on the devices with the new certificate.

Does the App need to be published / release with the new certificate before it will work??? Neither on development nor on production are messages received on the device???

Finally, it succeeded receiving messages for both sandbox and production / ad-hoc tokens.

// 64 chars token
// Sandbox and productions tokens have the same length and 
// they cannot be distinguished    
$deviceToken='1234567890123456789012345678901234567890123456789012345678901234';

$body['aps'] = array('alert' => 'Sample message', 'sound' => 'default');
$payload = json_encode($body);

$deviceToken = str_replace(' ', '', $deviceToken);
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

fwrite($apn_link, $msg, strlen($msg));
fflush($apn_link);

Do NOT mix sandbox and production device tokens on production!

The APN production environment does not allow sandbox tokens and it silently stops delivering messages to production tokens when a sandbox token has been used.

解决方案

// 64 chars token
// Sandbox and productions tokens have the same length and 
// they cannot be distinguished    
$deviceToken='1234567890123456789012345678901234567890123456789012345678901234';

$body['aps'] = array('alert' => 'Sample message', 'sound' => 'default');
$payload = json_encode($body);

$deviceToken = str_replace(' ', '', $deviceToken);
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

fwrite($apn_link, $msg, strlen($msg));
fflush($apn_link);

Do NOT mix sandbox and production device tokens on production!

The APN production environment does not allow sandbox tokens and it silently stops delivering messages to production tokens when a sandbox token has been used.

这篇关于的APN邮件传递,但iOS设备上没有收到的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆