2011-04-26 101 views
10

我想实现使用Python和Django的苹果推送通知。SSL错误而实施苹果推送通知

我使用下面库来实现它

http://leepa.github.com/django-iphone-push/

这里是我的代码,创建发送消息

from django.http import HttpResponse 
from django.utils import simplejson 
import json 
from push.models import iPhone 

def SendMessage(request,data): 

     t = iPhone('XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX ') # 64 digit token 
     t.send_message("hi") # at this line i am getting ERROR 
     return HttpResponse(data,mimetype='application/javascript') 

settings.py

import os 
PROJECT_ROOT = '/' 

# Full path to the APN Certificate/Private Key .pem 
IPHONE_SANDBOX_APN_PUSH_CERT = os.path.join(PROJECT_ROOT, "apns-dev-tubeteam.pem") 
IPHONE_LIVE_APN_PUSH_CERT = os.path.join(PROJECT_ROOT, "apns-dev-tubeteam.pem") 

# Set this to the hostname for the outgoing push server 
IPHONE_SANDBOX_APN_HOST = 'gateway.sandbox.push.apple.com' 
IPHONE_LIVE_APN_HOST = 'gateway.push.apple.com' 

# Set this to the hostname for the feedback server 
IPHONE_SANDBOX_FEEDBACK_HOST = 'feedback.sandbox.push.apple.com' 
IPHONE_LIVE_FEEDBACK_HOST = 'feedback.push.apple.com' 

错误

[Errno 336265218] _ssl.c:337: error:140B0002:SSL routines:SSL_CTX_use_PrivateKey_file:system lib 

任何人都可以请告诉我如何摆脱掉它。

+0

你读过错误了吗?很显然,您的64位令牌或您的SSL证书或两者都有问题。您是否按照设置证书的说明进行操作? – jathanism 2011-04-26 13:12:58

+0

嗯,我有一个.pem文件,我已经指定了该文件的路径,现在我不知道如何设置证书,请问您能否详细告诉我 – Hunt 2011-04-26 13:24:17

回答

16

我有完全相同的问题。原来这是一个简单的错误 - 我曾在IPHONE_SANDBOX_APN_PUSH_CERT错误和Python无法找到我的证书。一旦我将它指向正确的位置,它就开始工作。

请注意,您可能需要先仔细检查您的证书使用OpenSSL的命令行,如:

openssl x509 -text -in cert.pem 

这会给你考证关于您的证书,其有效性等信息

另外,仔细检查证书文件的文件权限(python进程必须有足够的权限来访问它)。

+2

+1“找不到证书”。就我而言,这只是文件名中的一个错字。真的感觉像'ssl.wrap_socket'可能会抛出一个简单的“文件未找到”,而不是让ssl错误冒出来 – ckhan 2012-12-12 18:55:05

+0

还值得注意的是,如果您尝试发送过多的推送消息未注册,Apple显然可能会关闭连接设备(来源:https://github.com/jleclanche/django-push-notifications/issues/69#issuecomment-53712129) – gregoltsov 2014-09-17 10:35:00

-3

使用此代码:

#!/usr/bin/python2.7 

import socket 
import ssl 
import json 
import struct 
import argparse 



APNS_HOST = ('gateway.sandbox.push.apple.com', 2195) 


class Payload: 
    PAYLOAD = '{"aps":{${MESSAGE}${BADGE}${SOUND}}}' 
    def __init__(self): 
     pass 

    def set_message(self, msg): 
     if msg is None: 
      self.PAYLOAD = self.PAYLOAD.replace('${MESSAGE}', '') 
     else: 
      self.PAYLOAD = self.PAYLOAD.replace('${MESSAGE}', '"alert":"%s",' % msg) 

    def set_badge(self, num): 
     if num is None: 
      self.PAYLOAD = self.PAYLOAD.replace('${BADGE}', '') 
     else: 
      self.PAYLOAD = self.PAYLOAD.replace('${BADGE}', '"badge":%s,' % num) 

    def set_sound(self, sound): 
     if sound is None: 
      self.PAYLOAD = self.PAYLOAD.replace('${SOUND}', '') 
     else: 
      self.PAYLOAD = self.PAYLOAD.replace('${SOUND}', '"sound":"%s",' % sound) 

    def toString(self): 
     return (self.PAYLOAD.replace('${MESSAGE}','').replace('${BADGE}','').replace('${SOUND}','')) 

def connectAPNS(host, cert): 
    ssl_sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), certfile = cert) 
    ssl_sock.connect(APNS_HOST) 
    return ssl_sock 

def sendNotification(sslSock, device, message, badge, sound): 
    payload = Payload() 
    payload.set_message(message) 
    payload.set_badge(badge) 
    payload.set_sound(sound) 
    payloadAsStr = payload.toString() 

    format = '!BH32sH%ds' % len(payloadAsStr) 
    binaryDeviceToken = device.replace(' ','').decode('hex') 
    binaryNotification = struct.pack(format, 0, 32, binaryDeviceToken, len(payloadAsStr), payloadAsStr) 

    print ("sending payload: ["+payloadAsStr+"] as binary to device: ["+device+"]") 
    sslSock.write(binaryNotification) 

def printUsageAndExit(): 
    print("msg2ios - Version 0.1\nmsg2IOS.py -d <device> -m <message> -s[plays sound] -b <badgeint> -c <certBundlePath>") 
    exit(1) 

if __name__ == '__main__': 
    parser = argparse.ArgumentParser() 
    parser.add_argument('-d', '--device') 
    parser.add_argument('-m', '--message') 
    parser.add_argument('-s', '--sound') 
    parser.add_argument('-b', '--badge') 
    parser.add_argument('-c', '--cert') 
    args = parser.parse_args() 

    if (args.device is None) or ((args.message is None) and (args.sound is None) and (args.badge is None)) or (args.cert is None): 
     printUsageAndExit() 

    sslSock = connectAPNS(APNS_HOST, args.cert) 
    sendNotification(sslSock, args.device, args.message, args.badge, args.sound) 
    sslSock.close() 
+5

这里的一些解释会有所帮助。 – casperOne 2011-12-09 00:05:51

-1

我的解决方案是,创建我的.pem文件时,我设置的密码为空,并认为这意味着没有密码。所以服务器仍然期待使用密码。我不得不手动删除密码。

这里是一个小如何引导它是否有助于人:

注:需要遵循的方向,从苹果的开发者网站创建证书第一 然后导出。p12文件, 通过导出已创建的嵌入式私钥(在“钥匙串访问”中), 不是实际证书 ----------------------- ------------- ------------------------------------ FOR DEVELOPMENT CERT: 获取p12文件后,需要通过从终端执行以下命令将其转换为PEM格式: $ openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns_dev。 p12 $ openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns_dev.p12

如果你w (注意:在导出/转换时使用'空白'密码,仍然确实设置了密码,因此如果您打算没有密码,则仍应该执行以下操作): $ openssl最后,您需要将密钥和证书文件组合成一个apns-dev.pem文件,我们将在连接时使用它APNS:

$猫APNS-DEV-cert.pem APNS-DEV-键noenc.pem> APNS-dev.pem

---------------- ------ ------------- FOR PRODUCTION CERT: 获取p12文件后,需要通过从终端执行以下命令将其转换为PEM格式: $ openssl pkcs12 -clcerts -nokeys退房手续APNS-PROD-cert.pem -in apns_prod.p12 $ OpenSSL的PKCS12 -nocerts退房手续APNS-PROD-key.pem -in apns_prod.p12

如果你想删除密码执行以下命令: (注意:在导出/转换时使用'空白'密码,仍然确实设置了密码,因此如果您打算没有密码,您仍应该执行以下操作) $ openssl rsa -in apns-prod-key.pem -out apns-prod-key-noenc.pem

最后,你需要的密钥和证书文件合并成连接到APNS时,我们将使用APNS-dev.pem文件:

$猫APNS-PROD-cert.pem APNS-PROD-键 - noenc.pem> apns-prod.pem