Configura il server per le notifiche push

Google Play genera notifiche in risposta a eventi che si verificano e possono interessare un'azienda. I provider di soluzioni EMM possono ricevere queste notifiche e intervenire su di esse, ad esempio fornendo avvisi o altri meccanismi per gli amministratori dei loro clienti.

Questa guida illustra come configurare l'infrastruttura server necessaria per ricevere ed elaborare solo le notifiche push EMM. Le notifiche pull non richiedono la configurazione descritta in questa guida.

Oltre alla configurazione del server descritta in questa guida, per le notifiche push devi anche concedere i privilegi appropriati ed eseguire altre attività di configurazione nella Console API di Google. Per maggiori dettagli, vedi Attivare le notifiche push EMM.

Per ulteriori informazioni su Google Cloud Pub/Sub, inclusi alcuni esempi, consulta la documentazione di Cloud Pub/Sub.

Puoi configurare il tuo sistema in modo che le notifiche push vengano inviate a un endpoint HTTPS specificato o a un server in attesa dell'invio delle notifiche.

Informazioni sulla configurazione push dell'endpoint

Per configurare un endpoint push, è necessario un server con un certificato SSL valido. In questo esempio, crei e carichi un certificato SSL in un'autorità di certificazione, quindi configuri il server NGINX. Infine, compili ed esegui il codice di test per confermare che la configurazione sia corretta.

Questo esempio mostra come configurare un server NGINX in modalità proxy inverso per la connessione all'app dell'abbonato (in PushSubscriber.java) in esecuzione sulla porta 8093, utilizzando Ubuntu 14.04. La tua azienda potrebbe utilizzare un server diverso, ma la configurazione di esempio dovrebbe funzionare, senza modifiche, su tutte le distribuzioni basate su Debian. Altre distribuzioni (ad esempio quelle basate su RedHat) sono simili, ma il percorso dei file di configurazione potrebbe essere diverso.

Prima di poter ricevere notifiche, devi configurare un endpoint che soddisfi i seguenti criteri:

  • Devi essere il proprietario del dominio e verificarne la proprietà nella console API di Google.

  • Devi essere in grado di eseguire un servizio sulla porta 443 (SSL).

  • Devi disporre di un certificato SSL firmato da un'autorità di certificazione. I certificati autofirmati non funzionano.

  • Il server web in esecuzione deve supportare i webhook.

L'endpoint non deve necessariamente essere eseguito su Google App Engine.

Crea e carica un certificato SSL

1. Crea un certificato SSL (Secure Sockets Layer):

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

Ciò genera la seguente risposta. Sostituisci i valori di esempio (come push.solarmora.com e myusername@myhost) con il nome effettivo del server, l'azienda, l'indirizzo e così via, nel codice seguente. Puoi utilizzare qualsiasi sottodominio a condizione che il record A di questo sottodominio rimandi al tuo server.

    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. Verifica che sia stato creato un file di certificato:

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

3. Per ottenere la firma di questo certificato, genera una richiesta di firma del certificato (CSR) da caricare sul firmatario:

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. Assicurati che i contenuti del file CSR siano simili ai seguenti:

    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. Carica nella tua CA la parte del certificato tra le righe BEGIN e END (incluse). La procedura esatta dipenderà dalla CA, ma includerà i seguenti passaggi:

  1. Carica il file di richiesta di firma del certificato sul sito della CA o incolla i contenuti del file sul sito della CA. La CA convalida ed elabora questi dati.
  2. Scarica il certificato firmato generato dalla tua CA.

6. L'output della CA deve contenere più file: il certificato firmato e quello della CA confermano l'idoneità alla firma dei certificati. Concatena tutti i file dei certificati *.crt nel bundle scaricato in un unico file di bundle, ad esempio bundle.push.solarmora.com.crt:

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

Configura il server proxy

In questa sezione configurerai il server web open source NGINX e il server proxy inverso per gestire l'endpoint e inoltrare tutte le richieste in entrata al server del sottoscrittore. NGINX viene utilizzato come esempio, ma puoi utilizzare qualsiasi altro proxy HTTP.

1. Installa NGINX sul tuo server:

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

2. Per assicurarti che i file di configurazione del server aggiuntivi che crei nella directory sites-enabled vengano elaborati da NGINX, modifica /etc/nginx/nginx.conf e includi quanto segue:

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

3. Copia i file dei certificati in una posizione sicura, leggibile dall'utente www-data, ma preferibilmente non leggibile da qualsiasi altro utente (potrebbe essere necessario modificare il nome utente se il server web è in esecuzione con un utente diverso):

    $ 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. Crea una nuova configurazione di server. Modifica push.solarmora.com in /etc/nginx/sites-enabled e utilizza il nome di dominio completo del tuo server effettivo come nome file:

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. Riavvia NGINX per implementare le modifiche:

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

6. Ora il tuo server è configurato. Per verificare la configurazione, prova a eseguire una query sul server utilizzando 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>

Questa è la risposta prevista, dato che non è stato configurato alcun server downstream (localhost:8093 nel nostro file di configurazione).

Compila ed esegui esempi

Per eseguire gli esempi in questa sezione devi avere un progetto attivo della console API di Google. Ti consigliamo di crearne una specifica a scopo di test e di tenerla separata dal progetto di produzione. Dopo aver creato un progetto di test, devi creare un account di servizio. Prendi nota dell'indirizzo email dell'account di servizio e inserisci il file .p12 associato in qualche punto del server.

Configurare la struttura ad albero del codice sorgente

1. Clona il repository 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. Nei sistemi basati su Debian, installa sia Maven sia il compilatore Google Protocol Buffers:
    $ sudo apt-get install maven protobuf-compiler

3. Verifica che sia Maven sia il compilatore Google Protocol Buffers siano installati correttamente:

    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. Il file di configurazione Maven pom.xml presuppone che il compilatore Protocol Buffers sia installato nella directory /usr/bin/protoc:

    myusername@myhost:~$ which protoc
    /usr/bin/protoc
In caso contrario, puoi modificare pom.xml o il link simbolico protoc:
    $ sudo ln -s which protoc /usr/bin/protoc
5. Compila gli esempi. Verifica di poter creare il codice eseguendo mvn clean compile assembly:single. Questo dovrebbe produrre un file denominato emm-notifications-[version-number]-jar-with-dependencies.jar, dove [version number] è la versione corrente dell'esempio, ad esempio 1.0-SNAPSHOT:
    myusername@myhost:~/code/play-work/examples/emm-notifications$ ls target/*
    target/emm-notifications-1.0-SNAPSHOT-jar-with-dependencies.jar
6. Verifica di poter eseguire il codice TestPublisher compilato. Si prevede che il codice non vada a buon fine:

    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. Devi eseguire l'override di alcuni valori nel file settings.properties. Per farlo, crea una copia del file e modificane le proprietà nel seguente modo:

    # 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. Esegui di nuovo il codice TestPublisher per assicurarti che non si arresti più in modo anomalo. (Potresti visualizzare un singolo errore nell'output del log.)

Esegui il codice di test del publisher

Devi eseguire il codice campione per la pubblicazione delle notifiche, in modo che l'iscritto abbia alcuni messaggi da leggere.

Nell'esempio seguente, il codice cerca l'argomento specificato in my_settings.properties ma non lo trova e pertanto lo crea. Quindi pubblica un messaggio nell'argomento. Questo esempio fornisce un prezioso strumento di test che ti consente di emulare i messaggi inviati dall'API EMM di Google Play.

    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}]}

Esegui il codice per il test degli abbonati

Il codice del test degli abbonati conferma che puoi ricevere i messaggi pubblicati dal codice TestPublisher.

1. Assicurati che il codice sia aggiornato e compilato, quindi esegui il codice di test del sottoscrittore:

    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" }
Il sottoscrittore ora è in esecuzione e pronto ad accettare i messaggi in entrata.

2. Esegui di nuovo l'editore e verranno aggiunti nuovi messaggi al log:

    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 }
Un messaggio è stato ricevuto ed elaborato correttamente.