2009-07-23 117 views
12

我试图使用Python向iPhone发送推送通知。我已经导出我的证书和私钥成从钥匙串访问P12文件,然后使用以下命令转换成PEM文件:使用Python连接到iPhone的APNS

openssl pkcs12 -in cred.p12 -out cert.pem -nodes -clcerts 

我使用APNSWrapper在Python进行连接。

我运行下面的代码:

 
deviceToken = 'Qun\xaa\xd ... c0\x9c\xf6\xca' 

# create wrapper 
wrapper = APNSNotificationWrapper('/path/to/cert/cert.pem', True) 

# create message 
message = APNSNotification() 
message.token(deviceToken) 
message.badge(5) 

# add message to tuple and send it to APNS server 
wrapper.append(message) 
wrapper.notify() 

然后我得到的错误信息:

 
ssl.SSLError: (1, '_ssl.c:485: 
error:14094416:SSL routines:SSL3_READ_BYTES:sslv3 alert certificate unknown') 

谁能帮我这个?

+0

那么问题是什么?证书或服务? – JackLeo 2011-04-13 14:32:41

回答

8

我最近做此使用Django - http://leecutsco.de/2009/07/14/push-on-the-iphone/

可能有用吗?它已经不再使用Python以外的库了。不会花太多的时间来提取send_message()方法。

+1

我建议把内容放到答案而不是链接上。最终链接可能会过时,在这种情况下,其他人可能不会从答案中受益。 – 2012-05-05 16:54:39

2

您是否考虑过Twisted包?下面的代码是从here采取:

from struct import pack 
from OpenSSL import SSL 
from twisted.internet import reactor 
from twisted.internet.protocol import ClientFactory, Protocol 
from twisted.internet.ssl import ClientContextFactory 

APNS_SERVER_HOSTNAME = "<insert the push hostname from your iPhone developer portal>" 
APNS_SERVER_PORT = 2195 
APNS_SSL_CERTIFICATE_FILE = "<your ssl certificate.pem>" 
APNS_SSL_PRIVATE_KEY_FILE = "<your ssl private key.pem>" 

class APNSClientContextFactory(ClientContextFactory): 
    def __init__(self): 
     self.ctx = SSL.Context(SSL.SSLv3_METHOD) 
     self.ctx.use_certificate_file(APNS_SSL_CERTIFICATE_FILE) 
     self.ctx.use_privatekey_file(APNS_SSL_PRIVATE_KEY_FILE) 

    def getContext(self): 
     return self.ctx 

class APNSProtocol(Protocol): 
    def sendMessage(self, deviceToken, payload): 
     # notification messages are binary messages in network order 
     # using the following format: 
     # <1 byte command> <2 bytes length><token> <2 bytes length><payload> 
     fmt = "!cH32cH%dc" % len(payload) 
     command = 0 
     msg = struct.pack(fmt, command, deviceToken, 
          len(payload), payload) 
     self.transport.write(msg) 

class APNSClientFactory(ClientFactory): 
    def buildProtocol(self, addr): 
     print "Connected to APNS Server %s:%u" % (addr.host, addr.port) 
     return APNSProtocol() 

    def clientConnectionLost(self, connector, reason): 
     print "Lost connection. Reason: %s" % reason 

    def clientConnectionFailed(self, connector, reason): 
     print "Connection failed. Reason: %s" % reason 

if __name__ == '__main__': 
    reactor.connectSSL(APNS_SERVER_HOSTNAME, 
         APNS_SERVER_PORT, 
         APNSClientFactory(), 
         APNSClientContextFactory()) 
    reactor.run() 
+0

@coonj你有没有试过这个成功?你有任何使用代码发送消息的例子吗? 谢谢。 – elioty 2009-07-27 13:19:35

1

最初发布的代码中有一些错误,所以这里是一个适合我的修正版本。

from struct import pack 
from OpenSSL import SSL 
from twisted.internet import reactor 
from twisted.internet.protocol import ClientFactory, Protocol 
from twisted.internet.ssl import ClientContextFactory 
import binascii 
import struct 

APNS_SERVER_HOSTNAME = "gateway.sandbox.push.apple.com" 
APNS_SERVER_PORT = 2195 
APNS_SSL_CERTIFICATE_FILE = "<your ssl certificate.pem>" 
APNS_SSL_PRIVATE_KEY_FILE = "<your ssl private key.pem>" 
DEVICE_TOKEN = "<hexlified device token>" 
MESSAGE = '{"aps":{"alert":"twisted test"}}' 

class APNSClientContextFactory(ClientContextFactory): 
    def __init__(self): 
     self.ctx = SSL.Context(SSL.SSLv3_METHOD) 
     self.ctx.use_certificate_file(APNS_SSL_CERTIFICATE_FILE) 
     self.ctx.use_privatekey_file(APNS_SSL_PRIVATE_KEY_FILE) 

    def getContext(self): 
     return self.ctx 

class APNSProtocol(Protocol): 

    def connectionMade(self): 
     print "connection made" 
     self.sendMessage(binascii.unhexlify(DEVICE_TOKEN), MESSAGE) 
     self.transport.loseConnection() 

    def sendMessage(self, deviceToken, payload): 
     # notification messages are binary messages in network order 
     # using the following format: 
     # <1 byte command> <2 bytes length><token> <2 bytes length><payload> 
     fmt = "!cH32sH%ds" % len(payload) 
     command = '\x00' 
     msg = struct.pack(fmt, command, 32, deviceToken, 
          len(payload), payload) 
     print "%s: %s" %(binascii.hexlify(deviceToken), binascii.hexlify(msg)) 
     self.transport.write(msg) 

class APNSClientFactory(ClientFactory): 
    def buildProtocol(self, addr): 
     print "Connected to APNS Server %s:%u" % (addr.host, addr.port) 
     return APNSProtocol() 

    def clientConnectionLost(self, connector, reason): 
     print "Lost connection. Reason: %s" % reason 

    def clientConnectionFailed(self, connector, reason): 
     print "Connection failed. Reason: %s" % reason 

if __name__ == '__main__': 
    reactor.connectSSL(APNS_SERVER_HOSTNAME, 
         APNS_SERVER_PORT, 
         APNSClientFactory(), 
         APNSClientContextFactory()) 
    reactor.run() 
0

我都尝试APNSWrapper和李佩卡姆的代码,不能让它在雪豹工作与Python 2.6。经过大量的试验和错误,它终于与pyOpenSSL合作。

我已经做了一个帖子,详细信息和代码片段here,所以我只是在那里引用你。

1

尝试更新到最新的APNSWrapper版本(0.4)。现在有对openssl命令行工具(openssl s_client)的内置支持。