Laravel實做Google Cloud Pub/Sub及Google Play RTDN介紹

2020/12/14

Google Cloud Pub/Sub

Google Cloud Pub/Sub是一個集中管理訊息的服務

透過Pub/Sub可以讓多個服務之間可以做溝通並且可以達到解耦合

主要概念如下

 

主題(Topic)

可以用來建立訊息

 

訂閱項目(Subscription)

用來訂閱指定的主題

 

Push訊息

使用者或是程式透過Service Account對指定主題建立訊息

 

Pull訊息

程式主動透過Service Account Pull指定訂閱主題的訊息

詳見官方文件

 

Push Subscription(Webhook)

透過設定Http API Endpoint

被動讓Google Pub/Sub來call這個API做訊息通知

詳見官方文件

 

Ack(acknowledge)

官方文件的中文叫做確認

可以想像成將Pull下來讀取的訊息標記為已讀

當訊息被確認

將無法再被Pull

反之如果都一直未針對訊息做確認動作

該訊息將會一直存在直到該訊息過期被回收

 

官方文件

 

設定Google Cloud專案

 

操作人員需要設定的權限

接下來要的GCP操作人員

需要有以下幾個權限才能完成

  • 安全管理員(IAM): 建立Service Account用
  • 服務帳戶管理員: 一樣需要設定Service Account用
  • 服務帳戶管理員: 一樣需要設定Service Account金鑰用(給程式碼使用的憑證)
  • 發佈/訂閱管理員: 就是Google Cloud Pub/Sub的最高權限

 

GCP-IAM.png

 

建立主題

建立一個叫做demo的主題(topic)

建立主題的選項跟UI操作都很簡單就不多做說明

 

建立pull類型的訂閱項目

如果要選擇用程式做主動pull訊息的機制可參考此步驟

建立一個叫demo-subscription的訂閱項目(subscription)

並選擇Pull(提取)類型

create-subscription.png

 

建立push類型的訂閱項目

如果要選擇用webhook endpoint機制可參考此步驟

選擇Push(推送)類型

並且設定server的webhook endpoint(local開發機可使用ngrok)

push-subscription.png

 

 

Service Account的權限、金鑰設定

service-account-create.png

前往IAM設定頁面建立Service Account

並且依照需求賦予權限

看是純訂閱、純發佈、或是訂閱、發佈都可以做的權限

設定完之後要另外建立Service Account金鑰(JSON)格式

金鑰下載後保留好準備做後續Demo用

 

使用Laravel實做訊息的Push/Pull

以下使用Laravel的Console來實做建立訊息、pull訊息

 

專案簡介

Github: https://github.com/ciao-chung/gcloud-pubsub-pull

使用套件: 官方的PHP Library

使用兩個command分別來demo訊息的Push及Pull

 

GCP認證機制

基本上就是跟官方的PHP Library一樣

在new任何服務Class的時候

帶入keyFile(Service Account金鑰內容)或是keyFilePath(Service Account金鑰路徑)選項即可

任何Gcloud服務的認證方式都一樣

可參考Authentication

 

Push訊息指令

範例原始碼

 

這邊主要是透過topic物件的publish method來發訊息

publish method參數可參考官方Rest API文件

<?php

$pubSub = new PubSubClient([
    'keyFilePath' => $this->serviceAccountKeyPath,
]);
$topic = $pubSub->topic($this->topicName);
$result = $topic->publish([
    'data' => 'data...',
    'attributes' => [
        'time' => now()->format('Y-m-d H:i:s'),
    ]
]);
$this->question('訊息Push完成');

 

Pull訊息指令

範例原始碼

 

這邊主要是透過subscription物件的pull method來發訊息

pull method參數可參考官方Rest API文件returnImmediatelymaxMessages

 

而ack動作則是透過subscription的acknowledge把message物件丟進去

才能將訊息標記為已讀

可參考官方Rest API文件的acknowledge操作

 

<?php

$pubSub = new PubSubClient([
    'keyFilePath' => $this->serviceAccountKeyPath,
]);
$this->subscription = $pubSub->subscription($this->subscriptionName);
$messages = $this->subscription->pull();
foreach ($messages as $index => $message) {
    $no = $index+1;
    $this->question("正在讀取第{$no}筆訊息");
    $this->line("messageId: {$message->id()}");
    $this->line("attributes: ".json_encode($message->attributes(), true));

    // 確認(Ack)
    $this->subscription->acknowledge($message);
}

 

Pull的訊息陣列

Screenshot_20201214_165057.png

 

價格

官方文件

 

規則滿多的

有訊息傳輸費、跨Region傳輸費、同樣使用Google產品可免費、跨專案計費等規則

不過計價的單價為GB

基本上每GB都幾塊台幣而已

如果用量不大的話倒是還好不用管太多規則

 

Google Play RTDN

RTDN(Real-time developer notification)

簡單來說就是Google Play透過Cloud Pub/Sub功能傳訊息

而我們Server可透過Pull Cloud Pub/Sub訊息來接收Google Play的訂單相關通知

像是一次扣款成功、定期定額訂閱扣款成功等訂單資訊

 

RTDN權限設定

根據官方文件Grant publish rights on your topic段落的第4點有提到

要將google-play-developer-notifications@system.gserviceaccount.com這個service account

新增Pub/Sub主題的publisher權限

Google Play才能針對這個主題發訊息

 

Screenshot_20201225_142733.png

Screenshot_20201225_143155.png

 

 

測試訊息發送

可以在Google Play Console專案內的營利設定內設定Cloud Pub/Sub主題名稱

按傳送測試通知來對該主題發送訊息

Screenshot_20201225_143335.png

 

RTDN透過Pull Pub/Sub訊息取得資料

官方文件

 

基本上就是透過錢面的pull訊息或是push webhook方式取得訊息

把訊息物件內的data做base64 decode後

subscriptionNotification物件取得訂單的purchaseToken

再透過訂單的purchaseToken

Google Play Rest API去反查訂單詳細資訊

就可以用這些資訊來回寫自己系統的扣款紀錄

如果是測試訊息的話

 

data欄位示意

Screenshot_20201225_143631.png

 

參考影片