Настройте сервер для push-уведомлений

Google Play генерирует уведомления в ответ на события, которые происходят и могут повлиять на предприятие. Поставщики решений EMM могут получать эти уведомления и реагировать на них, например, предоставляя оповещения или другие механизмы для своих администраторов клиентов.

В этом руководстве рассказывается, как настроить серверную инфраструктуру, необходимую для получения и обработки только push- уведомлений EMM. Уведомления по запросу не требуют настройки, подробно описанной в этом руководстве.

Помимо настройки сервера, описанной в этом руководстве, для push-уведомлений вам также необходимо предоставить соответствующие привилегии и выполнить другие задачи настройки в консоли Google API. Подробности см. в разделе «Включение push-уведомлений EMM» .

Дополнительную информацию о Google Cloud Pub/Sub, включая примеры, см. в документации Cloud Pub/Sub .

Вы можете настроить свою систему так, чтобы push-уведомления отправлялись на указанную конечную точку HTTPS или на сервер, который ожидает отправки уведомлений.

О настройке конечной точки push-уведомлений

Чтобы настроить конечную точку принудительной отправки, вам понадобится сервер с действительным сертификатом SSL. В этом примере вы создаете и загружаете сертификат SSL в центр сертификации (CA), а затем настраиваете сервер NGINX. Наконец, вы компилируете и запускаете тестовый код, чтобы подтвердить правильность настроек.

В этом примере показано, как настроить сервер NGINX в режиме обратного прокси-сервера для подключения к приложению подписчика (в PushSubscriber.java ), работающему на порту 8093, с использованием Ubuntu 14.04. Ваше предприятие может использовать другой сервер, но пример установки должен работать без изменений во всех дистрибутивах на основе Debian. Другие дистрибутивы (например, основанные на RedHat) аналогичны, но расположение файлов конфигурации может быть другим.

Прежде чем вы сможете получать уведомления, вы должны настроить конечную точку, соответствующую следующим критериям:

  • Вы должны быть владельцем домена и подтвердить свое право собственности в консоли Google API .

  • У вас должна быть возможность запустить службу на порту 443 (SSL).

  • У вас должен быть SSL-сертификат, подписанный центром сертификации. Самоподписанные сертификаты не работают.

  • Веб-сервер, который вы используете, должен поддерживать веб-перехватчики .

Ваша конечная точка не обязательно должна работать на Google App Engine (хотя это возможно).

Создайте и загрузите сертификат SSL

1. Создайте сертификат Secure Sockets Layer (SSL):

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

Это генерирует следующий ответ. Замените примеры значений (например, push.solarmora.com и myusername@myhost ) фактическим именем вашего сервера, компанией, адресом и т. д. в следующем коде. Вы можете использовать любой субдомен, если запись A этого субдомена указывает на ваш сервер.

    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. Убедитесь, что файл сертификата создан:

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

3. Чтобы подписать этот сертификат, создайте запрос на подпись сертификата (CSR) и загрузите его подписывающей стороне:

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. Убедитесь, что содержимое файла CSR выглядит следующим образом:

    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. Загрузите часть вашего сертификата между строками BEGIN и END (включительно) в свой ЦС. Точный процесс будет зависеть от вашего центра сертификации и будет включать в себя следующие шаги:

  1. Загрузите файл CSR на сайт CA или вставьте содержимое файла на сайт CA. Затем ваш центр сертификации проверяет и обрабатывает эти данные.
  2. Загрузите подписанный сертификат, созданный вашим центром сертификации.

6. Выходные данные ЦС должны содержать несколько файлов: сам подписанный сертификат и сертификат ЦС, подтверждающий, что они имеют право подписывать сертификаты. Объедините все файлы сертификатов *.crt в загруженном пакете в один файл пакета, например bundle.push.solarmora.com.crt :

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

Настройте свой прокси-сервер

В этом разделе вы настраиваете веб-сервер NGINX с открытым исходным кодом и обратный прокси-сервер для обслуживания конечной точки и пересылки всех входящих запросов на сервер подписчика. В качестве примера используется NGINX, но вместо него вы можете использовать любой другой HTTP-прокси.

1. Установите NGINX на свой сервер:

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

2. Чтобы гарантировать, что дополнительные файлы конфигурации сервера, которые вы создаете в каталоге sites-enabled обрабатываются NGINX, отредактируйте /etc/nginx/nginx.conf и включите следующее:

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

3. Скопируйте файлы сертификатов в безопасное место, доступное для чтения пользователю www-data , но желательно недоступное для чтения любому другому пользователю (возможно, вам придется изменить имя пользователя, если ваш веб-сервер работает от имени другого пользователя):

    $ 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. Создайте новую конфигурацию server . Отредактируйте push.solarmora.com в /etc/nginx/sites-enabled и используйте полное доменное имя вашего фактического сервера в качестве имени файла:

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. Перезапустите NGINX, чтобы изменения вступили в силу:

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

6. Ваш сервер настроен. Чтобы проверить конфигурацию, попробуйте запросить ваш сервер с помощью 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>

Это ожидаемый ответ, учитывая, что ни один нижестоящий сервер не настроен ( localhost:8093 в нашем файле конфигурации).

Скомпилируйте и запустите примеры

Для запуска примеров из этого раздела вам понадобится активный проект консоли Google API . Мы рекомендуем вам создать его специально для целей тестирования и хранить его отдельно от вашего производственного проекта. После создания тестового проекта вам необходимо создать сервисную учетную запись . Запишите адрес электронной почты учетной записи службы и поместите связанный файл .p12 где-нибудь на своем сервере.

Настройка дерева исходного кода

1. Клонируйте репозиторий 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. В системах на базе Debian установите Maven и компилятор Google Protocol Buffers :
    $ sudo apt-get install maven protobuf-compiler

3. Убедитесь, что Maven и компилятор Google Protocol Buffers установлены правильно:

    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. Файл конфигурации Maven pom.xml предполагает, что компилятор протокольных буферов установлен в каталоге /usr/bin/protoc :

    myusername@myhost:~$ which protoc
    /usr/bin/protoc
Если это не так, вы можете изменить pom.xml или символическую ссылку protoc :
    $ sudo ln -s which protoc /usr/bin/protoc
5. Скомпилируйте примеры. Убедитесь, что вы можете собрать код, запустив mvn clean compile assembly:single . В результате должен быть создан файл с именем emm-notifications-[version-number]-jar-with-dependencies.jar , где [version number] — текущая версия примера, например 1.0-SNAPSHOT :
    myusername@myhost:~/code/play-work/examples/emm-notifications$ ls target/*
    target/emm-notifications-1.0-SNAPSHOT-jar-with-dependencies.jar
6. Убедитесь, что вы можете запустить скомпилированный код TestPublisher . Ожидается, что код завершится неудачно:

    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. Необходимо переопределить некоторые значения в файле settings.properties . Для этого создайте копию файла и измените свойства копии следующим образом:

    # 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. Запустите код TestPublisher еще раз, чтобы убедиться, что он больше не дает сбоя. (В выводе журнала вы можете увидеть одну ошибку.)

Запустите тестовый код издателя

Вам необходимо запустить пример кода для публикации уведомлений, чтобы у вашего подписчика было несколько сообщений для чтения.

В следующем примере код ищет тему, указанную в my_settings.properties , но не находит ее и поэтому создает тему. Затем он публикует сообщение в теме. В этом примере представлен ценный инструмент тестирования, который позволяет эмулировать сообщения, отправляемые API EMM 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}]}

Запустите тестовый код подписчика

Тестовый код подписчика подтверждает, что вы можете получать сообщения, опубликованные кодом TestPublisher .

1. Убедитесь, что ваш код обновлен и скомпилирован, а затем запустите тестовый код подписчика:

    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" }
Теперь подписчик работает и готов принимать входящие сообщения.

2. Снова запустите издатель, и в журнал будут добавлены новые сообщения:

    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 }
Сообщение было правильно получено и обработано.