發布者主要使用伺服器端整合來管理讀者及其讀者
授權。主要,發布商會使用 UpdateReaderEntitlements
來更新
Google 的 PPID 產品 ID 授權記錄。
Google Cloud 設定
在 Google Cloud 中設定訂閱連結功能包含兩個主要元件:
- 啟用特定專案的 API
- 建立用來存取 API 的服務帳戶
啟用 Subscription Links API
如要使用服務帳戶及管理讀取者授權,需要採用 Google Cloud
專案必須同時啟用 Subscription Links API,
設定 OAuth 服務帳戶如要為
請前往選單 ->API 與服務 ->媒體庫並搜尋
Subscription Linking
,或直接造訪該網頁:
https://console.cloud.google.com/apis/library?project=gcp_project_id
圖 1. 前往 API 程式庫,並啟用 Cloud 專案
建立服務帳戶
服務帳戶的用途是讓您從應用程式存取 Subscription Links API。
- 在專案的內建立服務帳戶 控制台。
- 建立服務帳戶的憑證,然後儲存
位於應用程式可存取的安全位置,讀取
credentials.json
檔案。 - 授予 IAM 角色「訂閱連結管理員」加入 建立的服務帳戶如需精細地控管 服務帳戶,您可以從下表指派適當的角色。
能力 / 角色 | 訂閱連結管理員 | 訂閱連結檢視者 | 訂閱連結授權檢視者 |
---|---|---|---|
取得讀者授權 | |||
吸引讀者 | |||
更新讀者授權 | |||
刪除讀者 |
將服務帳戶與 Subscription Links API 搭配使用
使用服務帳戶來驗證對 Subscription Links API 的呼叫。
使用 googleapis 用戶端程式庫或簽署要求
與 REST API 互動用戶端程式庫會自動處理
適當的 access_token
,而 REST API 需要擷取 id_token
然後對 access_token
交換此項目。
下列用戶端
程式庫和 REST API 範例會使用 getReader()
端點。直播
完整示範所有 API 方法,請參閱
訂閱連結示範網站或網站程式碼。
使用 node.js googleapis 用戶端程式庫的要求範例
import {readerrevenuesubscriptionlinking_v1, Auth} from 'googleapis';
const subscriptionLinking = readerrevenuesubscriptionlinking_v1.Readerrevenuesubscriptionlinking;
class SubscriptionLinking {
constructor() {
this.auth = new Auth.GoogleAuth({
keyFile: process.env.KEY_FILE,
scopes: [
'https://www.googleapis.com/auth/readerrevenue.subscriptionlinking.manage'
],
})
}
init() {
return new subscriptionLinking(
{version: 'v1', auth: this.auth})
}
}
const api = new SubscriptionLinking();
const client = api.init();
async function getReader(ppid) {
const publicationId = process.env.PUBLICATION_ID;
return await client.publications.readers.get({
name: `publications/${publicationId}/readers/${ppid}`,
});
};
async function updateEntitlements(ppid) {
const publicationId = process.env.PUBLICATION_ID;
const requestBody = {
/*
Refer to
https://developers.google.com/news/subscribe/subscription-linking/appendix/glossary#entitlements_object
*/
entitlements : [{
product_id: `${publicationId}:basic`,
subscription_token: 'abc1234',
detail: 'This is our basic plan',
expire_time: '2025-10-21T03:05:08.200564Z'
}]
};
return await client.publications.readers.updateEntitlements({
name: `publications/${publicationId}/readers/${ppid}`,
requestBody
});
};
手動簽署 REST API 要求
import fetch from 'node-fetch'
import jwt from 'jsonwebtoken'
function getSignedJwt() {
/*
Either store the credentials string in an environmental variable
Or implement logic to fetch it.
*/
const key_file = process.env.CREDENTIALS_STRING
const issueDate = new Date()
const expireMinutes = 60
const offsetInSeconds = issueDate.getTimezoneOffset() * 60000
const expireDate = new Date(issueDate.getTime() + (expireMinutes * 60000))
const iat = Math.floor((issueDate.getTime() + offsetInSeconds) / 1000)
const exp = Math.floor((expireDate.getTime() + offsetInSeconds) / 1000)
const token = {
iss: key_file.client_email,
iat,
exp,
aud: 'https://oauth2.googleapis.com/token',
scope:'https://www.googleapis.com/auth/readerrevenue.subscriptionlinking.manage',
}
return jwt.sign(token, key_file.private_key, {
algorithm: 'RS256',
keyid: key_file.private_key_id,
})
}
async function getAccessToken(signedJwt) {
let body = new URLSearchParams();
body.set('grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer')
body.set('assertion', signedJwt)
const request = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body
})
const accessResponse = await accessFetch.json()
return accessResponse.access_token
}
async function getReader(ppid) {
const publicationId = process.env.PUBLICATION_ID
const base_url = 'https://readerrevenuesubscriptionlinking.googleapis.com/v1'
const endpoint = `${base_url}/publications/${publicationId}/readers/${ppid}`
const signedJwt = await getSignedJwt()
const accessToken = await getAccessToken(signedJwt)
const reader = await fetch(endpoint, {
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`,
},
}).then((response) => {
return response.json()
})
return reader
}