Skip to content

Instantly share code, notes, and snippets.

@alucard001
Created June 2, 2017 04:13
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save alucard001/a141b32e22f6d183db7a777bd72be27d to your computer and use it in GitHub Desktop.
Save alucard001/a141b32e22f6d183db7a777bd72be27d to your computer and use it in GitHub Desktop.
Python Apple Push Notification HTTP/2 Example - Silent Push
"""
Use HTTP/2 send APNS Example main reference
===========================================
http://gobiko.com/blog/token-based-authentication-http2-example-apns/
Error 410 to detect uninstalls
==============================
https://leftshift.io/mobile-tracking-uninstalls-on-ios-and-android
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW1
Expected result from below code:
410
{"reason":"Unregistered","timestamp":1496371306210}
HTTP/2 push
===========
https://tpu.thinkpower.com.tw/tpu/File/html/201611/20161122001842_f.html?f=3dj6j8kd38895ksgtdddd93865jhr9sn3rqkh
"""
import json
import jwt
import time
from hyper import HTTPConnection, HTTP20Connection
ALGORITHM = 'ES256'
APNS_KEY_ID = 'YOUR_KEY'
# http://disq.us/p/1ecxfqv:
# CMD: fold -w 64 APNsAuthKey_my_id.p8 > certs/APNsAuthKey_my_id_fold.p8
APNS_AUTH_KEY = 'Your .p8 cert path'
TEAM_ID = 'your_team_id'
BUNDLE_ID = 'your_bundle_id'
PUSH_ID = 'some_push_id'
f = open(APNS_AUTH_KEY)
secret = f.read()
token = jwt.encode(
{
'iss': TEAM_ID,
'iat': time.time()
},
secret,
algorithm= ALGORITHM,
headers={
'alg': ALGORITHM,
'kid': APNS_KEY_ID
}
)
path = '/3/device/{0}'.format(PUSH_ID)
request_headers = {
'apns-expiration': '0',
'apns-priority': '10',
'apns-topic': BUNDLE_ID,
'authorization': 'bearer {0}'.format(token.decode('ascii'))
}
# Open a connection the APNS server
# https://github.com/genesluder/python-apns/pull/3
# https://github.com/genesluder/python-apns/pull/3/commits/0f543b773c25b1a1d817f5f681912ed3c9c2ca35
# Development
conn = HTTP20Connection('api.development.push.apple.com:443', force_proto='h2')
# Production
# conn = HTTP20Connection('api.push.apple.com:443', force_proto='h2')
payload_data = {
'aps': {
'alert' : 'All your base are belong to us.',
# This is silent push
'sound' : '',
# Key to silent push
'content-available': 1
}
}
payload = json.dumps(payload_data).encode('utf-8')
# Send our request
conn.request(
'POST',
path,
payload,
headers=request_headers
)
# https://github.com/genesluder/python-apns/pull/3
# http://www.ehowstuff.com/how-to-install-and-update-openssl-on-centos-6-centos-7/
resp = conn.get_response()
print(resp.status)
print(resp.read())
# If we are sending multiple requests, use the same connection
payload_data = {
'aps': {
'alert' : 'You have no chance to survive. Make your time.',
'sound' : '',
'content-available': 1
}
}
payload = json.dumps(payload_data).encode('utf-8')
conn.request(
'POST',
path,
payload,
headers=request_headers
)
resp = conn.get_response()
print(resp.status)
print(resp.read())
@alucard001
Copy link
Author

alucard001 commented Jun 2, 2017

Points To Note

  • I am using Python 2.7 because the linux is old, you are recommended to convert this code to python 3
  • You need to install necessary Python packages before running this gist. Reading the Main reference is very important. Do not ignore that.
  • If you encounter ConnectionReset error from hyper. You may want to follow the reference I gave you by updating your OpenSSL to 1.0.2 AND using HTTP20Connection AND force_proto='h2'

My other works:

@emanuelelaface
Copy link

emanuelelaface commented Oct 28, 2020

Thanks for this very useful example. Just one note: if you want to push on WatchOS you have to specify in the headers also the 'apns-push-type' that must reflect what you put in the payload, for example 'apns-push-type': 'alert', as explained on the Apple site.
This is due to the fact that on the Watch you may want to use also a push to update a complication on the main screen instead of the watch app, so the operating system needs to know the destination of the notification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment