Google Play 会生成通知,以响应发生的并可能影响企业的事件。EMM 解决方案提供商可以接收这些通知并采取相应措施,例如为其客户管理员提供提醒或其他机制。
本指南介绍如何配置仅接收和处理 EMM push通知所需的服务器基础架构。拉取通知不需要本指南中详述的设置。
对于推送通知,除了本指南中介绍的服务器设置外,您还必须在 Google API 控制台中授予适当的权限并执行其他配置任务。如需了解详情,请参阅启用 EMM 推送通知。
如需详细了解 Google Cloud Pub/Sub(包括示例),请参阅 Cloud Pub/Sub 文档。
您可以配置系统,将推送通知发送到指定的 HTTPS 端点,或等待发送通知的服务器。
推送端点配置简介
如需配置推送端点,您需要一台具有有效 SSL 证书的服务器。在此示例中,您将创建 SSL 证书并将其上传到证书授权机构 (CA),然后配置 NGINX 服务器。最后,编译并运行测试代码,以确认您的设置正确无误。
以下示例展示了如何在反向代理模式下配置 NGINX 服务器,以使用 Ubuntu 14.04 连接到在端口 8093 上运行的订阅者应用(在 PushSubscriber.java
中)。您的企业可能使用其他服务器,但示例设置应该在所有基于 Debian 的发行版上无需更改即可正常运行。其他发行版(例如基于 RedHat 的发行版)类似,但配置文件的位置可能有所不同。
您必须先配置符合以下条件的端点,然后才能接收通知:
您必须拥有该网域,并在 Google API 控制台中验证您的所有权。
您必须能够在端口 443 (SSL) 上运行服务。
您必须拥有 CA 签名的 SSL 证书。自签名证书无效。
您运行的 Web 服务器必须支持 webhook。
您的端点不需要在 Google App Engine 上运行(但可以在 Google App Engine 上运行)。
创建并上传 SSL 证书
1. 生成安全套接字层 (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
行(含)之间的部分上传到您的 CA。具体流程取决于您的 CA,但包含以下步骤:
- 将您的 CSR 文件上传到您的 CA 网站,或将文件内容粘贴到您的 CA 网站上。然后,您的 CA 会验证和处理这些数据。
- 下载 CA 生成的签名证书。
6. CA 的输出应包含多个文件:已签名的证书本身以及用于确认其有资格对证书签名的 CA 证书。将下载的软件包中的所有 *.crt
证书文件合并成一个软件包文件,例如 bundle.push.solarmora.com.crt
:
$ cat *.crt > bundle.push.solarmora.com.crt
配置代理服务器
在本部分中,您将配置 NGINX 开源 Web 服务器和反向代理服务器以提供端点,并将所有传入请求转发到订阅者服务器。以 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
配置。在 /etc/nginx/sites-enabled
中修改 push.solarmora.com
,并使用实际服务器的完全限定域名作为文件名:
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
假定 Protocol Buffers 编译器已安装到 /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.jar6. 验证您可以运行编译后的
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
中指定的主题,但未找到该主题,因此会创建该主题。然后向该主题发布一条消息。此示例提供了一个有价值的测试工具,可让您模拟 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}]}
运行订阅者测试代码
订阅者测试代码确认您可以接收 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 }