Pergunta

Estou tentando enviar notificações push para um iPhone usando o Python. Eu exportei meu certificado e chave privada em um arquivo p12 do Keychain Access e depois o converteu em arquivo PEM usando o seguinte comando:

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

estou a usar Apnswrapper em python para a conexão.

Eu corro o seguinte 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()

E então eu recebo a mensagem de erro:

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

Alguém pode me ajudar sobre isso?

Foi útil?

Solução

Recentemente fiz isso usando Django - http://leecutsco.de/2009/07/14/push-on-the-iphone/

Pode ser útil? Ele já está usando bibliotecas extras que não são incluídas no Python. Não levaria muito para extrair o método send_message ().

Outras dicas

Você já considerou o Torcido pacote? O código abaixo é retirado de aqui:

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

Havia alguns bugs no código publicado originalmente, então aqui está uma versão corrigida que funciona para mim.

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

Tente atualizar para a versão mais recente do apnswrapper (0.4). Há suporte de construção da ferramenta de linha de comando OpenSSL (OpenSSL S_Client) agora.

Eu tentei os dois APNSWrapper e o código de Lee Peckham e não conseguiu fazer funcionar sob o Snow Leopard com o Python 2.6. Depois de muita tentativa e erro, finalmente funcionou pyOpenSSL.

Eu já fiz uma postagem com detalhes e trechos de código aqui Então, vou apenas te referir lá.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top