首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >APN消息是在iOS设备上传递但未接收到的。

APN消息是在iOS设备上传递但未接收到的。
EN

Stack Overflow用户
提问于 2015-08-27 09:52:57
回答 2查看 5.7K关注 0票数 3

我已经建立了一个转发/调度服务,按照苹果公司的声明/建议,它与an保持一个开放的连接,以防止DoS检测,并且该证书正在工作。

我已成功连接并成功发送消息,但没有在iOS设备(IPhone)上接收消息。(?!)发送的字节数等于fwrite返回的字节数。

最后,消息可能包含特定于国家的字符。APN是怎么处理的?如何将这些字符发送到APN服务器?

我已经尝试过了,无论有没有转发服务,但没有运气。:-(

在代码段中删除对日志的所有调用,以避免混淆。这意味着粘贴的日志消息不能直接映射到代码段,但是应该可以“猜测”日志消息的来源。

请在这些问题上帮助我。提前感谢

以这种方式建立连接:

代码语言:javascript
复制
$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);
/* ... */

在侦听转发服务上的套接字的循环中:

代码语言:javascript
复制
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);
        }
    }
}
/* ... */

此外,我以这种方式发送消息:

代码语言:javascript
复制
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;
    }
}
}

发送给转发服务的消息:

代码语言:javascript
复制
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;
}

对于每个设备令牌,以下列方式生成一条消息:

代码语言:javascript
复制
$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]");
}
}

来自logdisp的日志消息来自转发服务,而来自日志的日志消息来自app-/web服务器。web服务器使用127.0.0.1/localhost连接到转发服务,因此web服务器和转发服务器托管在同一台物理计算机上。

代码语言:javascript
复制
[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] [] []

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

代码语言:javascript
复制
{"aps" : {"alert" : "message","badge" : "1","sound" : "default"}} 
{"aps" : { "alert" : { "title" : "My Title", "body" : "My Message" }, "badge" : 2, "sound" : "default" } }

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

代码语言:javascript
复制
[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]

我现在可以连接了!原因很简单。证书的路径不正确。但是,在具有新证书的设备上仍未收到推送通知。

应用程序是否需要发布/发布新的证书才能运行?设备上既没有收到信息,也没有在生产中接收信息?

最后,它成功地接收了沙箱和生产/即席令牌的消息。

代码语言:javascript
复制
// 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);

不要混合沙箱和生产装置令牌的生产!

APN生产环境不允许沙箱令牌,并且在使用沙箱令牌时,它会静默地停止向生产令牌传递消息。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-09-03 13:52:49

代码语言:javascript
复制
// 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);

不要混合沙箱和生产装置令牌的生产!

APN生产环境不允许沙箱令牌,并且在使用沙箱令牌时,它会静默地停止向生产令牌传递消息。

票数 5
EN

Stack Overflow用户

发布于 2016-05-28 02:01:43

苹果已经改变了很多事情:虽然它仍然允许创建沙箱专用证书,但是生产证书可以在沙箱和生产环境中使用。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32246163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档