使用 Python 连接到 iPhone 的 APNS
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1172769/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Connecting to APNS for iPhone Using Python
提问by elioty
I'm trying to send push notifications to an iPhone using Python. I've exported my certificate and private keyinto a p12 file from keychain access and then converted it into pem file using the following command:
我正在尝试使用 Python 向 iPhone 发送推送通知。我已经通过钥匙串访问将我的证书和私钥导出到 p12 文件中,然后使用以下命令将其转换为 pem 文件:
openssl pkcs12 -in cred.p12 -out cert.pem -nodes -clcerts
I'm using APNSWrapperin Python for the connection.
我在 Python 中使用APNSWrapper进行连接。
I run the following code:
我运行以下代码:
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()
And then I get the error message:
然后我收到错误消息:
ssl.SSLError: (1, '_ssl.c:485: error:14094416:SSL routines:SSL3_READ_BYTES:sslv3 alert certificate unknown')
Can anyone help me out on this?
任何人都可以帮我解决这个问题吗?
采纳答案by Lee
I recently did this using Django - http://leecutsco.de/2009/07/14/push-on-the-iphone/
我最近使用 Django 做到了这一点 - http://leecutsco.de/2009/07/14/push-on-the-iphone/
May be useful? It's making use of no extra libraries other than those included with Python already. Wouldn't take much to extract the send_message() method out.
可能有用吗?除了已经包含在 Python 中的库之外,它没有使用任何额外的库。提取 send_message() 方法不需要太多。
回答by Cam
there were a few bugs in the originally posted code, so here's a corrected version that works for me.
最初发布的代码中有一些错误,所以这里有一个对我有用的更正版本。
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()
回答by Jason Coon
Have you considered the Twistedpackage? The below code is taken from 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()
回答by Maksym Klymyshyn
Try to update to latest APNSWrapper version (0.4). There is build-in support of openssl command line tool (openssl s_client) now.
尝试更新到最新的 APNSWrapper 版本 (0.4)。现在有对 openssl 命令行工具 (openssl s_client) 的内置支持。
回答by Ramin
I tried both APNSWrapper
and Lee Peckham's code and couldn't get it to work under Snow Leopard with Python 2.6. After a lot of trial and error it finally worked with pyOpenSSL
.
我尝试了APNSWrapper
Lee Peckham 和 Lee Peckham 的代码,但无法使用 Python 2.6 在 Snow Leopard 下运行它。经过大量的反复试验,它终于可以使用pyOpenSSL
.
I already did a post with details and code snippets hereso I'll just refer you there.
我已经做了与细节和代码段后这里所以我就指你。