如何调试Python向iPhone推送通知?

1 投票
1 回答
2908 浏览
提问于 2025-04-16 23:16

如何调试从提供者到苹果推送通知服务器的连接?

我正在使用一个叫做PyAPNs的库(github链接),下面是我的代码:

from apns import APNs, Payload

print "start"

apns = APNs(use_sandbox=True, cert_file='apns-prod.pem', key_file='apns-prod.pem')

# Send a notification
token_hex = '*******'
payload = Payload(alert="Hello World!", sound="default", badge=1)
apns.gateway_server.send_notification(token_hex, payload)

# Get feedback messages
for (token_hex, fail_time) in apns.feedback_server.items():
    print token_hex
    print fail_time


print "end"

我的应用已经注册为接收远程通知,iPhone上的通知设置看起来一切正常。但是就是没有收到任何通知。

我想知道该如何调试这个问题。当我运行脚本时,没有任何错误信息,而且apns.feedback_server.items是空的。我试着打印反馈服务器的缓冲区,但什么也没有。

有没有办法查看SSL套接字中发生了什么?或者从苹果的服务器获取一些响应?

..fredrik

编辑

我解决了这个问题。问题出在token_hex上。我使用了来自Xcode组织的标识符,而不是在注册应用时生成的token。

1 个回答

1

使用这段代码:

#!/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()

撰写回答