Skonfiguruj serwer do obsługi powiadomień push

Google Play generuje powiadomienia w reakcji na zdarzenia, które mogą mieć wpływ na całą firmę. Dostawcy rozwiązań EMM mogą otrzymywać te powiadomienia i reagować na nie, na przykład udostępniając alerty lub inne mechanizmy administratorom klientów.

Z tego przewodnika dowiesz się, jak skonfigurować infrastrukturę serwera niezbędną do odbierania i przetwarzania tylko powiadomień push z EMM. Powiadomienia pull nie wymagają konfigurowania opisanej w tym przewodniku.

Oprócz konfigurowania serwera opisanego w tym przewodniku dla powiadomień push musisz też przyznać odpowiednie uprawnienia i wykonywać inne czynności konfiguracyjne w konsoli interfejsów API Google. Więcej informacji znajdziesz w artykule Włączanie powiadomień push w usłudze EMM.

Więcej informacji o Google Cloud Pub/Sub (w tym przykłady) znajdziesz w dokumentacji Cloud Pub/Sub.

Możesz skonfigurować system tak, aby powiadomienia push były wysyłane do określonego punktu końcowego HTTPS lub serwera, który czeka na wysłanie powiadomień.

Informacje o konfiguracji punktu końcowego push

Aby skonfigurować punkt końcowy push, potrzebujesz serwera z prawidłowym certyfikatem SSL. W tym przykładzie należy utworzyć certyfikat SSL i przesłać go do urzędu certyfikacji, a następnie skonfigurować serwer NGINX. Na koniec kompilowasz i uruchamiasz kod testowy, aby sprawdzić, czy konfiguracja jest prawidłowa.

Ten przykład pokazuje, jak skonfigurować serwer NGINX w trybie odwrotnego serwera proxy, aby połączyć się z aplikacją subskrybenta (w PushSubscriber.java) działającą na porcie 8093 przy użyciu Ubuntu 14.04. Twoja firma może używać innego serwera, ale przykładowa konfiguracja powinna działać bez zmian we wszystkich dystrybucji opartych na Debianie. Inne dystrybucje (na przykład oparte na RedHat) są podobne, ale lokalizacja plików konfiguracji może się różnić.

Aby otrzymywać powiadomienia, musisz skonfigurować punkt końcowy, który spełnia te kryteria:

  • Musisz być właścicielem domeny i potwierdzić tę własność w Konsoli interfejsów API Google.

  • Musisz mieć możliwość uruchamiania usługi na porcie 443 (SSL).

  • Musisz mieć certyfikat SSL podpisany przez urząd certyfikacji. Certyfikaty podpisane samodzielnie nie działają.

  • Używany serwer WWW musi obsługiwać webhooki.

Punkt końcowy nie musi uruchamiać w Google App Engine (chociaż może).

Tworzenie i przesyłanie certyfikatu SSL

1. Wygeneruj certyfikat SSL:

    myusername@myhost:/tmp$ sudo openssl req -x509 -nodes -days 365 \
      -newkey rsa:2048 -keyout cert.key -out cert.crt

Spowoduje to wygenerowanie poniższej odpowiedzi. Zastąp przykładowe wartości (np. push.solarmora.com i myusername@myhost) w poniższym kodzie rzeczywistą nazwą serwera, firmą, adresem itp. Możesz użyć dowolnej subdomeny, o ile rekord A tej subdomeny wskazuje Twój serwer.

    Generating a 2048 bit RSA private key
    ...........................................................................
    .....+++
    writing new private key to 'cert.key'
    -----
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [AU]:GB
    State or Province Name (full name) [Some-State]:England
    Locality Name (eg, city) []:London
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Solarmora, Inc.
    Organizational Unit Name (eg, section) []:Creative Publications
    Common Name (e.g. server FQDN or YOUR name) []:push.solarmora.com
    Email Address []:admin@solarmora.com

2. Sprawdź, czy utworzono plik certyfikatu:

$ myusername@myhost:/tmp$ ls cert*
cert.crt  cert.key

3. Aby podpisać ten certyfikat, utwórz żądanie podpisania certyfikatu i prześlij je do osoby podpisującej:

myusername@myhost:/tmp$ sudo openssl x509 -x509toreq -in cert.crt \
  -out cert.csr -signkey cert.key
Getting request Private Key
Generating certificate request
myusername@myhost:/tmp$ ls cert.*
cert.crt  cert.csr  cert.key

4. Sprawdź, czy zawartość pliku żądania podpisania certyfikatu wygląda tak:

    Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=GB, ST=England, L=London, O=Solarmora, Inc.,
        OU=Creative Publications,
        CN=push.solarmora.com/emailAddress=admin@solarmora.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:cc:0f:54:26:3d:d9:17:eb:8f:6c:f7:27:5e:77:
                    64:65:00:db:fe:2a:1f:fa:ea:de:21:7a:c5:5d:87:
                    ...
                    ...
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha256WithRSAEncryption
         1d:ea:12:b8:c2:6a:d6:f4:6e:92:2f:b9:12:5e:e3:91:15:a0:
         06:b5:81:ce:c5:cf:b7:d2:a7:dd:f2:78:ca:28:8e:21:cd:6d:
         ...
         ...
    -----BEGIN CERTIFICATE REQUEST-----
    MIIC6zCCAdMCAQAwgaUxCzAJBgNVBAYTAkdCMRAwDgYDVQQIDAdFbmdsYW5kMQ8w
    DQYDVQQHDAZMb25kb24xGDAWBgNVBAoMD0FDTUUgQ29ycCwgSW5jLjEYMBYGA1UE
    CwwPQ3JlYXRpdmUgQW52aWxzMRswGQYDVQQDDBJwdXNoLmFjbWUtY29ycC5jb20x
    IjAgBgkqhkiG9w0BCQEWE2FkbWluQGFjbWUtY29ycC5jb20wggEiMA0GCSqGSIb3
    ...
    ...
    -----END CERTIFICATE REQUEST-----

5. Prześlij do urzędu certyfikacji tę część certyfikatu między wierszami BEGIN i END (włącznie). Dokładny proces zależy od urzędu certyfikacji, ale obejmuje te kroki:

  1. Prześlij plik żądania podpisania certyfikatu do witryny urzędu certyfikacji lub wklej zawartość pliku w witrynie urzędu certyfikacji. Urząd certyfikacji weryfikuje i przetwarza te dane.
  2. Pobierz podpisany certyfikat wygenerowany przez urząd certyfikacji.

6. Dane wyjściowe z urzędu certyfikacji powinny zawierać wiele plików: podpisany certyfikat i certyfikat urzędu certyfikacji potwierdzający uprawnienia do podpisywania certyfikatów. Połącz wszystkie pliki certyfikatów *.crt z pobranego pakietu w jeden plik pakietu, na przykład bundle.push.solarmora.com.crt:

$ cat *.crt > bundle.push.solarmora.com.crt

Konfigurowanie serwera proxy

W tej sekcji skonfigurujesz serwer WWW typu open source i odwrotny serwer proxy NGINX, aby obsługiwać punkt końcowy i przekazywać wszystkie żądania przychodzące do serwera subskrybenta. Jako przykład podano NGINX, ale możesz używać dowolnego innego serwera proxy HTTP.

1. Zainstaluj NGINX na serwerze:

    $ sudo apt-get update
    $ sudo apt-get install nginx
    $ nginx -v
    $ nginx version: nginx/1.4.6 (Ubuntu)

2. Aby mieć pewność, że dodatkowe pliki konfiguracji serwera utworzone w katalogu sites-enabled zostały przetworzone przez NGINX, edytuj plik /etc/nginx/nginx.conf i dołącz te elementy:

    $ include /etc/nginx/conf.d/*.conf;
    $ include /etc/nginx/sites-enabled/*;

3. Skopiuj pliki certyfikatów w bezpieczne miejsce, w którym będzie mógł je odczytać użytkownik www-data, ale w sposób nieczytelny dla innych użytkowników (jeśli Twój serwer WWW działa jako inny użytkownik, może być konieczne dostosowanie nazwy użytkownika):

    $ sudo mkdir -p /var/openssl/push.solarmora.com
    $ sudo mv /tmp/cert.key 
/var/openssl/push.solarmora.com/push.solarmora.com.key $ sudo mv /tmp/bundle.push.solarmora.com.crt
/var/openssl/push.solarmora.com/bundle.push.solarmora.com.crt

4. Utwórz nową konfigurację server. Edytuj push.solarmora.com w /etc/nginx/sites-enabled i użyj pełnej i jednoznacznej nazwy domeny serwera jako nazwy pliku:

server {
   listen 443;
   server_name push.solarmora.com;

   ssl on;
   ssl_certificate
     /var/openssl/push.solarmora.com/bundle.push.solarmora.com.crt;
   ssl_certificate_key
     /var/openssl/push.solarmora.com/push.solarmora.com.key;

   # it is usually very convenient to have separate files for your
   # access and error log to analyze for possible problems
   access_log /var/log/nginx/nginx.push.solarmora.com.log;
   error_log /var/log/nginx/nginx.push.solarmora.com.log;

   location / {
            # assuming the subscriber will run on the same machine
            # on port 8093
            proxy_pass http://localhost:8093;
   }
}

5. Ponownie uruchom NGINX, aby wprowadzić zmiany:

    myusername@myhost:/etc/nginx$ sudo service nginx restart
    * Restarting nginx nginx
    ...done.

6. Serwer jest teraz skonfigurowany. Aby sprawdzić konfigurację, spróbuj wysłać zapytanie do serwera za pomocą polecenia curl:

    [myusername@myhost:~]$ curl push.solarmora.com
    <html>
    <head><title>502 Bad Gateway</title></head>
    <body bgcolor="white">
    <center><h1>502 Bad Gateway</h1></center>
    <hr><center>nginx/1.4.6 (Ubuntu)</center>
    </body>
    </html>

Jest to oczekiwana odpowiedź, ponieważ nie skonfigurowano żadnego serwera odbierającego (localhost:8093 w naszym pliku konfiguracyjnym).

Kompilowanie i uruchamianie przykładów

Aby uruchomić przykłady z tej sekcji, musisz mieć aktywny projekt w Konsoli interfejsów API Google. Najlepiej jest utworzyć ją specjalnie do celów testowych i trzymać ją oddzielnie od projektu produkcyjnego. Po utworzeniu projektu testowego musisz utworzyć konto usługi. Zapisz adres e-mail konta usługi i umieść powiązany plik .p12 na serwerze.

Konfigurowanie drzewa kodu źródłowego

1. Skopiuj repozytorium play-work.git:

    myusername@myhost:~/code$ git clone
    https://github.com/google/play-work.git
    Cloning into 'play-work'...
    Username for 'https://github.com': username
    Password for 'https://username@github.com':
    remote: Counting objects: 110, done.
    remote: Compressing objects: 100% (60/60), done.
    remote: Total 110 (delta 24), reused 95 (delta 9), pack-reused 0
    Receiving objects: 100% (110/110), 23.88 KiB | 0 bytes/s, done.
    Resolving deltas: 100% (24/24), done.
    Checking connectivity... done.
2. W systemach opartych na Debianie zainstaluj zarówno narzędzie Maven, jak i kompilator Google Protocol Buffers:
    $ sudo apt-get install maven protobuf-compiler

3. Sprawdź, czy kompilator Maven i Google Protocol Buffers są zainstalowane prawidłowo:

    myusername@myhost:~$ mvn -v
    Apache Maven 3.0.5
    Maven home: /usr/share/maven
    Java version: 1.7.0_75, vendor: Oracle Corporation
    Java home: /usr/lib/jvm/java-7-openjdk-amd64/jre
    Default locale: en_US, platform encoding: UTF-8
    OS name: "linux", version: "3.16.0-30-generic", arch: "amd64", family: "unix"
    myusername@myhost:~$ protoc --version
    libprotoc 2.5.0

4. Plik konfiguracji narzędzia Maven pom.xml zakłada, że kompilator Protocol Buffers jest zainstalowany w katalogu /usr/bin/protoc:

    myusername@myhost:~$ which protoc
    /usr/bin/protoc
Jeśli tak nie jest, możesz zmodyfikować pom.xml lub dowiązanie symboliczne protoc:
    $ sudo ln -s which protoc /usr/bin/protoc
5. Skompiluj przykłady. Sprawdź, czy możesz utworzyć kod, uruchamiając polecenie mvn clean compile assembly:single. Powinno to spowodować utworzenie pliku o nazwie emm-notifications-[version-number]-jar-with-dependencies.jar, gdzie [version number] to aktualna wersja przykładu, np. 1.0-SNAPSHOT:
    myusername@myhost:~/code/play-work/examples/emm-notifications$ ls target/*
    target/emm-notifications-1.0-SNAPSHOT-jar-with-dependencies.jar
6. Sprawdź, czy możesz uruchomić skompilowany kod TestPublisher. Kod powinien się zakończyć niepowodzeniem:

    myusername@myhost:~/code/play-work/examples/emm-notifications$ java -cp \
      target/emm-notifications-1.0-SNAPSHOT-jar-with-dependencies.jar \
      com.google.android.work.emmnotifications.TestPublisher
    Exception in thread "main" java.lang.IllegalArgumentException:
    You must specify non-default ServiceAccountEmail in
    settings.properties
        at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:119)
        at com.google.api.client.util.Preconditions.checkArgument(Preconditions.java:69)
        at com.google.android.work.emmnotifications.Settings.verifyVariable(Settings.java:129)
        at com.google.android.work.emmnotifications.Settings.getSettings(Settings.java:103)
        at com.google.android.work.emmnotifications.TestPublisher.main(TestPublisher.java:39)

7. Musisz zastąpić niektóre wartości w pliku settings.properties. Aby to zrobić, utwórz kopię pliku i zmień właściwości w ten sposób:

    # This should be your own service account's email address
    ServiceAccountEmail=368628613713-t4hfexampledn5lhpdcu1qqfgio01626@developer.gserviceaccount.com
    ServiceAccountP12KeyFile=/opt/secret/secret.p12
    # This will be the name of the service account
    ProjectName=enterprise-cloud-pub-sub
    SubscriptionName=projects/enterprise-cloud-pub-sub/subscriptions/default
    TopicName=projects/enterprise-cloud-pub-sub/topics/default
    # The push endpoint in your API Console project
    PushEndpoint=https://push.solarmora.com

8. Uruchom ponownie kod TestPublisher, aby upewnić się, że nie ulega już awarii. (w danych wyjściowych logu może pojawić się pojedynczy błąd).

Uruchamianie kodu testowego wydawcy

Aby subskrybent mógł przeczytać wiadomości, musisz uruchomić przykładowy kod do publikowania powiadomień.

W poniższym przykładzie kod szuka tematu określonego w zasadzie my_settings.properties, ale nie może go znaleźć, więc tworzy temat. Następnie publikuje wiadomość w tym temacie. Ten przykład przedstawia cenne narzędzie do testowania, które umożliwia emulowanie wiadomości wysyłanych przez interfejs Google Play EMM API.

    myusername@myhost:~/code/play-work/examples/emm-notifications$ DEVELOPER_CONSOLE_SETTINGS=./my_settings.properties java -cp \
      target/emm-notifications-1.0-SNAPSHOT-jar-with-dependencies.jar com.google.android.work.emmnotifications.TestPublisher
    Feb 27, 2015 1:39:59 PM com.google.android.work.emmnotifications.RetryHttpInitializerWrapper$1 handleResponse
    INFO: RetryHandler: {
      "error": {
        "code": 404,
        "message": "Resource not found (resource=default).",
        "errors": [
          {
            "message": "Resource not found (resource=default).",
            "domain": "global",
            "reason": "notFound"
          }
        ],
        "status": "NOT_FOUND"
      }
    }

    Feb 27, 2015 1:39:59 PM com.google.android.work.emmnotifications.TestPublisher main
    INFO: Topic projects/enterprise-cloud-pub-sub/topics/default doesn't exists, creating it
    Feb 27, 2015 1:40:02 PM com.google.android.work.emmnotifications.TestPublisher main
    INFO: Topic projects/enterprise-cloud-pub-sub/topics/default created
    Feb 27, 2015 1:40:02 PM com.google.android.work.emmnotifications.TestPublisher main
    INFO: Publishing a request: {messages=[{data=CjEKFQoIMTIzMjEzMjESCXJpZ2h0IG5vdxIWY29tLmdvb2dsZS5hbmRyb2lkLmdtcxgA}]}

Uruchamianie kodu testowego subskrypcji

Kod testowy subskrypcji potwierdza, że możesz otrzymywać wiadomości publikowane za pomocą kodu TestPublisher.

1. Sprawdź, czy Twój kod jest aktualny i skompilowany, a następnie uruchom kod testowy subskrybenta:

    myusername@myhost:~/code/play-work/examples/emm-notifications$ DEVELOPER_CONSOLE_SETTINGS=./my_settings.properties 
java -cp target/emm-notifications-1.0-SNAPSHOT-jar-with-dependencies.jar
com.google.android.work.emmnotifications.PushSubscriber Feb 27, 2015 1:46:37 PM com.google.android.work.emmnotifications.PushSubscriber main INFO: Will be using topic name: projects/enterprise-cloud-pub-sub/topics/default, subscription name:
projects/enterprise-cloud-pub-sub/subscriptions/default Feb 27, 2015 1:46:38 PM com.google.android.work.emmnotifications.PushSubscriber main INFO: Trying to get subscription named projects/enterprise-cloud-pub-sub/subscriptions/default Feb 27, 2015 1:46:38 PM com.google.android.work.emmnotifications.RetryHttpInitializerWrapper$1 handleResponse INFO: RetryHandler: { "error": { "code": 404, "message": "Resource not found (resource=default).", "errors": [ { "message": "Resource not found (resource=default).", "domain": "global", "reason": "notFound" } ], "status": "NOT_FOUND" } } Feb 27, 2015 1:46:38 PM com.google.android.work.emmnotifications.PushSubscriber main INFO: Subscription doesn't exist, will try to create projects/enterprise-cloud-pub-sub/subscriptions/default Feb 27, 2015 1:46:43 PM com.google.android.work.emmnotifications.PushSubscriber main INFO: Created: { "ackDeadlineSeconds" : 600, "name" : "projects/enterprise-cloud-pub-sub/subscriptions/default", "pushConfig" : { "pushEndpoint" : "https://push.solarmora.com" }, "topic" : "projects/enterprise-cloud-pub-sub/topics/default" }
Subskrybent działa i jest gotowy na przyjmowanie wiadomości przychodzących.

2. Ponownie uruchom wydawcę, a do dziennika zostaną dodane nowe wiadomości:

    Feb 27, 2015 1:47:24 PM com.google.android.work.emmnotifications.PushSubscriber$1 handle
    INFO: Raw request: {"message":{"data":"CjEKFQoIMTIzMjEzMjESCXJpZ2h0IG5vdxIWY29tLmdvb2dsZS5hbmRyb2lkLmdtcxgA",
"attributes":{},"message_id":"71571141246"},"subscription":"/subscriptions/enterprise-cloud-pub-sub/default"} Feb 27, 2015 1:47:24 PM com.google.android.work.emmnotifications.PushSubscriber$1 handle INFO: Pubsub message received: { "attributes" : { }, "data" : "CjEKFQoIMTIzMjEzMjESCXJpZ2h0IG5vdxIWY29tLmdvb2dsZS5hbmRyb2lkLmdtcxgA", "message_id" : "71571141246" } Feb 27, 2015 1:47:24 PM com.google.android.work.emmnotifications.PushSubscriber$1 handle INFO: Message received: product_approval_event { common_event_information { enterprise_id: "12321321" event_notification_sent_timestamp: "right now" } product_id: "com.google.android.gms" approved: false }
Wiadomość została prawidłowo odebrana i przetworzona.