2009-07-23 21 views
12

Estoy tratando de enviar notificaciones automáticas a un iPhone usando Python. He exportado mi certificado y clave secreta en un archivo de p12 del acceso llavero y luego se convierte en archivo PEM con el siguiente comando:Conectando a APNS para iPhone usando Python

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

estoy usando APNSWrapper en Python para la conexión.

que ejecute el siguiente código:

 
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() 

Y luego me sale el mensaje de error:

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

¿Puede alguien ayudarme en esto?

+0

¿Cuál era el problema? Certificado o servicio? – JackLeo

Respuesta

8

Hace poco hizo esto usando Django - http://leecutsco.de/2009/07/14/push-on-the-iphone/

puede ser útil? No está haciendo uso de otras bibliotecas además de las incluidas con Python. No tomaría mucho extraer el método send_message().

+1

Sugiero poner el contenido a la respuesta en lugar del enlace. Eventualmente, el enlace puede quedar obsoleto, en cuyo caso otros pueden no beneficiarse de la respuesta. –

+0

Tal como predijo @Walty, el enlace se rompió. El nuevo enlace es http://leecutsco.de/2009/07/14/push-on-the-iphone/ - sería bueno si el contenido estuviera en respuesta. – johndodo

2

¿Has considerado el paquete Twisted? El código siguiente es tomado de 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 ¿Has probado esto con éxito? ¿Tiene algún ejemplo de usar el código para enviar mensajes? Gracias. – elioty

1

Hubo algunos errores en el código publicado originalmente, así que aquí hay una versión corregida que funciona para mí.

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

He intentado tanto APNSWrapper y el código de Lee Peckham y no podía conseguir que funcione bajo Snow Leopard con Python 2.6. Después de una gran cantidad de prueba y error finalmente funcionó con pyOpenSSL.

Ya hice una publicación con detalles y fragmentos de código here, así que solo lo referiré allí.

1

Intente actualizar a la última versión de APNSWrapper (0.4). Ahora se admite la herramienta de línea de comandos de openssl (openssl s_client).