게시자는 주로 서버 측 통합을 사용하여 독자와 독자의 사용 권한을 관리합니다. 기본적으로 게시자는 UpdateReaderEntitlements
를 사용하여 PPID의 제품 ID 사용 권한에 관한 Google의 레코드를 업데이트합니다.
Google Cloud 설정
Google Cloud에서 정기 결제 연결을 구성하는 작업에는 다음 두 가지 주요 구성요소가 포함됩니다.
- 지정된 프로젝트에 API 사용 설정
- API에 액세스하기 위한 서비스 계정 만들기
Subscription Linking API 사용 설정
서비스 계정을 사용하고 독자의 사용 권한을 관리하려면 Google Cloud 프로젝트에 Subscription Linking API가 사용 설정되어 있고 OAuth 서비스 계정이 올바르게 구성되어 있어야 합니다. 프로젝트에 Subscription Linking API를 사용 설정하려면 메뉴 -> API 및 서비스 -> 라이브러리로 이동하여 Subscription Linking
를 검색하거나 페이지를 직접 방문합니다.
https://console.cloud.google.com/apis/library?project=gcp_project_id
그림 1. API 라이브러리로 이동하여 Google Cloud 프로젝트에 API를 사용 설정합니다.
서비스 계정 만들기
서비스 계정은 애플리케이션에서 Subscription Linking API에 액세스하도록 허용하는 데 사용됩니다.
- 프로젝트 콘솔에서 서비스 계정을 만듭니다.
- 서비스 계정의 사용자 인증 정보를 만들고 애플리케이션에서 액세스할 수 있는 안전한 위치에
credentials.json
파일을 저장합니다. - 만든 서비스 계정에 '구독 연결 관리자' IAM 역할을 부여합니다. 서비스 계정의 기능을 세부적으로 제어하려면 다음 표에서 적절한 역할을 할당하면 됩니다.
기능 / 역할 | 구독 연결 관리자 | 구독 연결 뷰어 | 구독 연결 사용 권한 뷰어 |
---|---|---|---|
구독자 사용 권한 가져오기 | |||
독자 확보 | |||
구독자 사용 권한 업데이트 | |||
독자 삭제 |
Subscription Linking API에서 서비스 계정 사용
서비스 계정을 사용하여 googleapis 클라이언트 라이브러리 또는 REST API로 요청에 서명하여 Subscription Linking 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}/entitlements`,
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
}