設定推播通知的伺服器

Google Play 會根據 並可能影響到企業EMM 解決方案供應商可接收 通知及採取行動,例如發出警示或其他機制 客戶管理員

本指南說明如何設定所需的伺服器基礎架構 僅用於接收及處理 EMM 推播通知。 提取通知不需要進行本指南中詳述的設定。

除了本指南所述的伺服器設定之外,您也適用推播通知 您也必須授予適當權限 執行其他設定 建立工作詳情請見 啟用 EMM 推播通知

如要進一步瞭解 Google Cloud Pub/Sub (包含範例),請參閱: Cloud Pub/Sub 說明文件

您可以將系統設定為 或等待通知傳送的伺服器。

關於推送端點設定

如要設定推送端點,您需要伺服器具備有效的 SSL 憑證。於 在此範例中,您會建立 SSL 憑證並上傳到憑證授權單位 (CA),然後設定 NGINX 伺服器。最後,在 Python 中 確認您的設定正確無誤。

這個範例說明如何設定 NGINX 伺服器 反向 Proxy 模式,用來連結訂閱者應用程式 (在 PushSubscriber.java 中) 是透過 Ubuntu 14.04 來執行貴企業可能使用不同的 不過,所有以 Debian 為基礎的範例設定應可正常運作 發行。其他分佈情形 (例如以 RedHat 為基礎的模型) 但設定檔的位置可能會有所不同。

如要接收通知,您必須先設定 必須符合下列條件:

  • 您必須在 Google API 控制台

  • 您必須能夠透過通訊埠 443 (SSL) 執行服務。

  • 您必須具有 CA 簽署的 SSL 憑證。自行簽署的憑證無法運作。

  • 您所執行的網路伺服器必須支援 Webhook

您的端點無須在 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.commyusername@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 而定,但包含下列步驟:

  1. 將 CSR 檔案上傳到 CA 網站,或是將檔案內容貼到 CA 網站上。接著,您的 CA 會驗證及處理這項資料。
  2. 下載 CA 產生的已簽署憑證。

6. CA 的輸出內容應包含多個檔案:已簽署 以及確認他們有資格使用的 CA 憑證 簽署憑證串連已下載的所有 *.crt 憑證檔案 並整合到單一套件檔案中,例如 bundle.push.solarmora.com.crt

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

設定 Proxy 伺服器

在本節中,您將設定 NGINX 開放原始碼網路伺服器,然後反向操作 來提供端點服務,並將所有傳入要求轉送至 訂閱者伺服器。NGINX 可做為範例,但您可以使用 請改用 HTTP Proxy。

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 通訊協定緩衝區編譯器
    $ sudo apt-get install maven protobuf-compiler

3. 確認 Maven 和 Google 通訊協定緩衝區編譯器皆已 正確安裝:

    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. AI 必須採行 隱私保護設計原則編譯範例。確認您可以執行 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 中指定的主題,因此建立了該主題。 然後將訊息發布至主題。這個範例提供了 這個測試工具可用於模擬 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 }
敬上 系統已正確接收並處理郵件。