Laravel實做Google Cloud Pub/Sub及Google Play RTDN介紹
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的最高權限
建立主題
建立一個叫做demo的主題(topic)
建立主題的選項跟UI操作都很簡單就不多做說明
建立pull類型的訂閱項目
如果要選擇用程式做主動pull訊息的機制可參考此步驟
建立一個叫demo-subscription的訂閱項目(subscription)
並選擇Pull(提取)類型
建立push類型的訂閱項目
如果要選擇用webhook endpoint機制可參考此步驟
選擇Push(推送)類型
並且設定server的webhook endpoint(local開發機可使用ngrok)
Service Account的權限、金鑰設定
前往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服務的認證方式都一樣
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文件的returnImmediately及maxMessages
而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的訊息陣列
價格
規則滿多的
有訊息傳輸費、跨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才能針對這個主題發訊息
測試訊息發送
可以在Google Play Console專案內的營利設定內設定Cloud Pub/Sub主題名稱
按傳送測試通知來對該主題發送訊息
RTDN透過Pull Pub/Sub訊息取得資料
基本上就是透過錢面的pull訊息或是push webhook方式取得訊息
把訊息物件內的data做base64 decode後
從subscriptionNotification物件取得訂單的purchaseToken
再透過訂單的purchaseToken
發Google Play Rest API去反查訂單詳細資訊
就可以用這些資訊來回寫自己系統的扣款紀錄
如果是測試訊息的話
data欄位示意
參考影片