2011-04-26 44 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