Jak používat Notification Hubs z Pythonu

Ke všem funkcím Notification Hubs můžete přistupovat z back-endu Java/PHP/Python/Ruby pomocí rozhraní REST centra oznámení, jak je popsáno v článku o rozhraníCH REST API služby Notification Hubs na webu MSDN.

Poznámka

Toto je ukázková referenční implementace pro implementaci oznámení odesílaných v Pythonu a nejedná se o oficiálně podporovanou sadu Sdk centra oznámení v Pythonu. Ukázka byla vytvořena pomocí Pythonu 3.4.

V tomto článku se dozvíte, jak:

  • Sestavte klienta REST pro funkce Notification Hubs v Pythonu.
  • Odesílat oznámení pomocí rozhraní Pythonu do rozhraní REST API centra oznámení.
  • Získejte výpis požadavku a odpovědi HTTP REST pro účely ladění nebo pro vzdělávací účely.

Můžete postupovat podle kurzu Začínáme pro mobilní platformu podle vašeho výběru a implementovat back-endovou část v Pythonu.

Poznámka

Rozsah ukázky je omezený pouze na odesílání oznámení a neprovádí žádnou správu registrace.

Klientské rozhraní

Hlavní klientské rozhraní může poskytovat stejné metody, které jsou k dispozici v sadě .NET Notification Hubs SDK. Toto rozhraní vám umožní přímo přeložit všechny kurzy a ukázky, které jsou aktuálně k dispozici na tomto webu, a přispěly komunitou na internetu.

Veškerý kód, který je k dispozici, najdete v ukázce obálky REST v Pythonu.

Pokud chcete například vytvořit klienta:

isDebug = True
hub = NotificationHub("myConnectionString", "myNotificationHubName", isDebug)

Odeslání informační zprávy windows:

wns_payload = """<toast><visual><binding template=\"ToastText01\"><text id=\"1\">Hello world!</text></binding></visual></toast>"""
hub.send_windows_notification(wns_payload)

Implementace

Pokud jste to ještě neudělali, postupujte podle kurzu Začínáme až do poslední části, kde musíte implementovat back-end.

Všechny podrobnosti o implementaci úplné obálky REST najdete na webu MSDN. Tato část popisuje implementaci hlavního postupu v Pythonu pro přístup ke koncovým bodům REST služby Notification Hubs a odesílání oznámení.

  1. Analýza připojovacího řetězce
  2. Vygenerování autorizačního tokenu
  3. Odeslání oznámení pomocí rozhraní HTTP REST API

Analýza připojovacího řetězce

Tady je hlavní třída implementovaná klienta, jejíž konstruktor analyzuje připojovací řetězec:

class NotificationHub:
    API_VERSION = "?api-version=2013-10"
    DEBUG_SEND = "&test"

    def __init__(self, connection_string=None, hub_name=None, debug=0):
        self.HubName = hub_name
        self.Debug = debug

        # Parse connection string
        parts = connection_string.split(';')
        if len(parts) != 3:
            raise Exception("Invalid ConnectionString.")

        for part in parts:
            if part.startswith('Endpoint'):
                self.Endpoint = 'https' + part[11:].lower()
            if part.startswith('SharedAccessKeyName'):
                self.SasKeyName = part[20:]
            if part.startswith('SharedAccessKey'):
                self.SasKeyValue = part[16:]

Vytvoření tokenu zabezpečení

Podrobnosti o vytvoření tokenu zabezpečení najdete tady. Přidejte do NotificationHub třídy následující metody pro vytvoření tokenu na základě identifikátoru URI aktuálního požadavku a přihlašovacích údajů extrahovaných z připojovacího řetězce.

@staticmethod
def get_expiry():
    # By default returns an expiration of 5 minutes (=300 seconds) from now
    return int(round(time.time() + 300))


@staticmethod
def encode_base64(data):
    return base64.b64encode(data)


def sign_string(self, to_sign):
    key = self.SasKeyValue.encode('utf-8')
    to_sign = to_sign.encode('utf-8')
    signed_hmac_sha256 = hmac.HMAC(key, to_sign, hashlib.sha256)
    digest = signed_hmac_sha256.digest()
    encoded_digest = self.encode_base64(digest)
    return encoded_digest


def generate_sas_token(self):
    target_uri = self.Endpoint + self.HubName
    my_uri = urllib.parse.quote(target_uri, '').lower()
    expiry = str(self.get_expiry())
    to_sign = my_uri + '\n' + expiry
    signature = urllib.parse.quote(self.sign_string(to_sign))
    auth_format = 'SharedAccessSignature sig={0}&se={1}&skn={2}&sr={3}'
    sas_token = auth_format.format(signature, expiry, self.SasKeyName, my_uri)
    return sas_token

Odeslání oznámení pomocí rozhraní HTTP REST API

Poznámka

Služba MPNS (Microsoft Push Notification Service) je zastaralá a už se nepodporuje.

Nejprve použijeme definici třídy představující oznámení.

class Notification:
    def __init__(self, notification_format=None, payload=None, debug=0):
        valid_formats = ['template', 'apple', 'gcm',
                         'windows', 'windowsphone', "adm", "baidu"]
        if not any(x in notification_format for x in valid_formats):
            raise Exception(
                "Invalid Notification format. " +
                "Must be one of the following - 'template', 'apple', 'gcm', 'windows', 'windowsphone', 'adm', 'baidu'")

        self.format = notification_format
        self.payload = payload

        # array with keynames for headers
        # Note: Some headers are mandatory: Windows: X-WNS-Type, WindowsPhone: X-NotificationType
        # Note: For Apple you can set Expiry with header: ServiceBusNotification-ApnsExpiry
        # in W3C DTF, YYYY-MM-DDThh:mmTZD (for example, 1997-07-16T19:20+01:00).
        self.headers = None

Tato třída je kontejner pro nativní tělo oznámení nebo sadu vlastností oznámení šablony, sadu hlaviček, která obsahuje formát (nativní platformu nebo šablonu) a vlastnosti specifické pro platformu (například vlastnost vypršení platnosti Apple a hlavičky WNS).

Všechny dostupné možnosti najdete v dokumentaci k rozhraním REST API služby Notification Hubs a v konkrétních formátech oznamovacích platforem.

Nyní s touto třídou zapište metody odeslání oznámení uvnitř NotificationHub třídy .

def make_http_request(self, url, payload, headers):
    parsed_url = urllib.parse.urlparse(url)
    connection = http.client.HTTPSConnection(
        parsed_url.hostname, parsed_url.port)

    if self.Debug > 0:
        connection.set_debuglevel(self.Debug)
        # adding this querystring parameter gets detailed information about the PNS send notification outcome
        url += self.DEBUG_SEND
        print("--- REQUEST ---")
        print("URI: " + url)
        print("Headers: " + json.dumps(headers, sort_keys=True,
                                       indent=4, separators=(' ', ': ')))
        print("--- END REQUEST ---\n")

    connection.request('POST', url, payload, headers)
    response = connection.getresponse()

    if self.Debug > 0:
        # print out detailed response information for debugging purpose
        print("\n\n--- RESPONSE ---")
        print(str(response.status) + " " + response.reason)
        print(response.msg)
        print(response.read())
        print("--- END RESPONSE ---")

    elif response.status != 201:
        # Successful outcome of send message is HTTP 201 - Created
        raise Exception(
            "Error sending notification. Received HTTP code " + str(response.status) + " " + response.reason)

    connection.close()


def send_notification(self, notification, tag_or_tag_expression=None):
    url = self.Endpoint + self.HubName + '/messages' + self.API_VERSION

    json_platforms = ['template', 'apple', 'gcm', 'adm', 'baidu']

    if any(x in notification.format for x in json_platforms):
        content_type = "application/json"
        payload_to_send = json.dumps(notification.payload)
    else:
        content_type = "application/xml"
        payload_to_send = notification.payload

    headers = {
        'Content-type': content_type,
        'Authorization': self.generate_sas_token(),
        'ServiceBusNotification-Format': notification.format
    }

    if isinstance(tag_or_tag_expression, set):
        tag_list = ' || '.join(tag_or_tag_expression)
    else:
        tag_list = tag_or_tag_expression

    # add the tags/tag expressions to the headers collection
    if tag_list != "":
        headers.update({'ServiceBusNotification-Tags': tag_list})

    # add any custom headers to the headers collection that the user may have added
    if notification.headers is not None:
        headers.update(notification.headers)

    self.make_http_request(url, payload_to_send, headers)


def send_apple_notification(self, payload, tags=""):
    nh = Notification("apple", payload)
    self.send_notification(nh, tags)


def send_google_notification(self, payload, tags=""):
    nh = Notification("gcm", payload)
    self.send_notification(nh, tags)


def send_adm_notification(self, payload, tags=""):
    nh = Notification("adm", payload)
    self.send_notification(nh, tags)


def send_baidu_notification(self, payload, tags=""):
    nh = Notification("baidu", payload)
    self.send_notification(nh, tags)


def send_mpns_notification(self, payload, tags=""):
    nh = Notification("windowsphone", payload)

    if "<wp:Toast>" in payload:
        nh.headers = {'X-WindowsPhone-Target': 'toast',
                      'X-NotificationClass': '2'}
    elif "<wp:Tile>" in payload:
        nh.headers = {'X-WindowsPhone-Target': 'tile',
                      'X-NotificationClass': '1'}

    self.send_notification(nh, tags)


def send_windows_notification(self, payload, tags=""):
    nh = Notification("windows", payload)

    if "<toast>" in payload:
        nh.headers = {'X-WNS-Type': 'wns/toast'}
    elif "<tile>" in payload:
        nh.headers = {'X-WNS-Type': 'wns/tile'}
    elif "<badge>" in payload:
        nh.headers = {'X-WNS-Type': 'wns/badge'}

    self.send_notification(nh, tags)


def send_template_notification(self, properties, tags=""):
    nh = Notification("template", properties)
    self.send_notification(nh, tags)

Tyto metody odesílají požadavek HTTP POST do koncového bodu /messages vašeho centra oznámení se správným textem a hlavičkami pro odeslání oznámení.

Použití vlastnosti ladění k povolení podrobného protokolování

Povolení vlastnosti ladění při inicializaci centra oznámení zapíše podrobné informace protokolování o požadavku HTTP a výpisu odpovědi a také podrobný výsledek odeslání zprávy oznámení. Vlastnost TestSend služby Notification Hubs vrací podrobné informace o výsledku odeslání oznámení. Pokud ho chcete použít, inicializujte ho pomocí následujícího kódu:

hub = NotificationHub("myConnectionString", "myNotificationHubName", isDebug)

V důsledku toho se k adrese HTTP požadavku na odeslání centra oznámení připojí řetězec dotazu "test".

Dokončení kurzu

Teď můžete absolvovat kurz Začínáme odesláním oznámení z back-endu Pythonu.

Inicializujte klienta Notification Hubs (nahraďte připojovací řetězec a název centra podle pokynů v kurzu Začínáme):

hub = NotificationHub("myConnectionString", "myNotificationHubName")

Pak přidejte kód pro odeslání v závislosti na vaší cílové mobilní platformě. Tato ukázka také přidává metody vyšší úrovně pro povolení odesílání oznámení na základě platformy, například send_windows_notification pro Windows; send_apple_notification (pro jablko) atd.

Windows Store a Windows Phone 8.1 (bez Silverlightu)

wns_payload = """<toast><visual><binding template=\"ToastText01\"><text id=\"1\">Test</text></binding></visual></toast>"""
hub.send_windows_notification(wns_payload)

Windows Phone 8.0 a 8.1 Silverlight

hub.send_mpns_notification(toast)

iOS

alert_payload = {
    'data':
        {
            'msg': 'Hello!'
        }
}
hub.send_apple_notification(alert_payload)

Android

gcm_payload = {
    'data':
        {
            'msg': 'Hello!'
        }
}
hub.send_google_notification(gcm_payload)

Kindle Fire

adm_payload = {
    'data':
        {
            'msg': 'Hello!'
        }
}
hub.send_adm_notification(adm_payload)

Baidu

baidu_payload = {
    'data':
        {
            'msg': 'Hello!'
        }
}
hub.send_baidu_notification(baidu_payload)

Spuštění kódu Pythonu by mělo vygenerovat oznámení, které se zobrazí na cílovém zařízení.

Příklady

debug Povolení vlastnosti

Když při inicializaci NotificationHubu povolíte příznak ladění, zobrazí se podrobný výpis požadavku HTTP a odpovědi a také NotificationOutcome, kde zjistíte, jaké hlavičky HTTP se předávají v požadavku a jaká odpověď HTTP byla přijata z centra oznámení:

Snímek obrazovky konzoly s podrobnostmi o výpisu požadavku H T T P a výpisu odpovědí a červeně vyznačenými zprávami o výsledku oznámení

Zobrazí se například podrobný výsledek centra oznámení.

  • po úspěšném odeslání zprávy do služby nabízených oznámení.
    <Outcome>The Notification was successfully sent to the Push Notification System</Outcome>
    
  • Pokud nebyly nalezeny žádné cíle pro jakékoli nabízené oznámení, pak se pravděpodobně zobrazí následující výstup jako odpověď (což značí, že nebyly nalezeny žádné registrace pro doručení oznámení, pravděpodobně proto, že registrace měly některé neodpovídající značky).
    '<NotificationOutcome xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect" xmlns:i="https://www.w3.org/2001/XMLSchema-instance"><Success>0</Success><Failure>0</Failure><Results i:nil="true"/></NotificationOutcome>'
    

Oznámení o vysílání informační zprávy do Windows

Všimněte si hlaviček, které se odesílají, když odesíláte informační zprávu všesměrového vysílání klientovi Windows.

hub.send_windows_notification(wns_payload)

Snímek obrazovky konzoly s podrobnostmi o požadavku H T T P a formátem oznámení služby Service Bus a červeně vyznačenými hodnotami typu X W N S

Odeslat oznámení s určením značky (nebo výrazu značky)

Všimněte si hlavičky HTTP značek, která se přidá do požadavku HTTP (v následujícím příkladu se oznámení odešle jenom registracím s datovou částí "sports")).

hub.send_windows_notification(wns_payload, "sports")

Snímek obrazovky konzoly s podrobnostmi o požadavku H T T P a formátem oznámení služby Service Bus, značkou oznámení služby Service Bus a červeně vyznačenými hodnotami typu X W N S

Odeslat oznámení s více značkami

Všimněte si, jak se hlavička HTTP značek změní, když se odešle více značek.

tags = {'sports', 'politics'}
hub.send_windows_notification(wns_payload, tags)

Snímek obrazovky konzoly s podrobnostmi o požadavku H T T P a formátu oznámení služby Service Bus, několika značkami oznámení služby Service Bus a červeně vyznačenými hodnotami typu X W N S

Oznámení podle šablony

Všimněte si, že se změní hlavička FORMÁT HTTP a text datové části se odešle jako součást textu požadavku HTTP:

Na straně klienta – zaregistrovaná šablona:

var template = @"<toast><visual><binding template=""ToastText01""><text id=""1"">$(greeting_en)</text></binding></visual></toast>";

Na straně serveru – odesílání datové části:

template_payload = {'greeting_en': 'Hello', 'greeting_fr': 'Salut'}
hub.send_template_notification(template_payload)

Snímek obrazovky konzoly s červeně vyznačenými podrobnostmi o požadavku H T T P a typem obsahu a formátem oznámení služby Service Bus

Další kroky

Tento článek ukazuje, jak vytvořit pythonového klienta REST pro Notification Hubs. Odsud můžete: