Skip to content

Instantly share code, notes, and snippets.

@Hiyorimi
Forked from alucard001/apns.py
Last active January 15, 2023 15:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hiyorimi/41bc8cf1fb913cb9eb3f70d6e9587f5d to your computer and use it in GitHub Desktop.
Save Hiyorimi/41bc8cf1fb913cb9eb3f70d6e9587f5d to your computer and use it in GitHub Desktop.
Python3 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()
def get_token() -> str:
token = jwt.encode(
{
'iss': TEAM_ID,
'iat': time.time()
},
secret,
algorithm= ALGORITHM,
headers={
'alg': ALGORITHM,
'kid': APNS_KEY_ID
}
)
return token
def send_single_push(apns_token: str, payload_data: dict):
token = get_token()
path = '/3/device/{0}'.format(apns_token)
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 = 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()
return resp
payload_data = {
'aps': {
'alert' : 'All your base are belong to us.',
# This is silent push
'sound' : '',
# Key to silent push
'content-available': 1
}
}
resp = send_single_push(APNS_DEVICE_TOKEN, payload_data)
print('Status: {}'.format(resp.status))
print('reps.read(): {}'.format(resp.read()))
# If we are sending multiple requests, use the same connection
payload_2_data = {
'aps': {
'alert' : 'You have no chance to survive. Make your time.',
'sound' : '',
'content-available': 1
}
}
resp = send_single_push(APNS_DEVICE_TOKEN, payload_2_data)
print('Status: {}'.format(resp.status))
print('reps.read(): {}'.format(resp.read()))
@Theunis111
Copy link

Theunis111 commented Jan 5, 2022

Good day, I am really struggling to send push notifications to iOS using django. How do I get the APNS device token?

@sisoje
Copy link

sisoje commented Feb 4, 2022

no error handling from responses?

@Theunis111
Copy link

Keep getting bad device token I am not sure why I cant see or retrieve the APNS registration_id or APNS_DEVICE_TOKEN as specified here.

@Pietro-Putelli
Copy link

ImportError: cannot import name 'Iterable' from 'collections'

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