Đồng bộ hoá Quyền của người dùng (Tích hợp phía máy chủ)

Nhà xuất bản chủ yếu sử dụng tính năng tích hợp phía máy chủ để quản lý độc giả và các quyền. Chủ yếu, các nhà xuất bản sử dụng UpdateReaderEntitlements để cập nhật Bản ghi của Google về quyền sử dụng mã sản phẩm đối với PPID.

Thiết lập Google Cloud

Quá trình định cấu hình tính năng Liên kết gói thuê bao trong Google Cloud bao gồm 2 hoạt động chính:

  1. Bật API cho một dự án cụ thể
  2. Tạo tài khoản dịch vụ để truy cập API

Bật Subscription linking API (API Liên kết gói thuê bao)

Để sử dụng tài khoản dịch vụ và quản lý quyền của độc giả, Google Cloud dự án phải bật cả Subscription linking API (API Liên kết gói thuê bao) và tài khoản dịch vụ OAuth đã định cấu hình. Để bật Subscription linking API (API Liên kết gói thuê bao) cho một dự án, hãy điều hướng từ trình đơn -> API và Dịch vụ -> Thư viện và tìm kiếm Subscription Linking hoặc truy cập trực tiếp vào trang:


https://console.cloud.google.com/apis/library?project=gcp_project_id

API

Hình 1. Chuyển đến Thư viện API và bật API cho một Dự án trên đám mây.

Tạo Tài khoản dịch vụ

Tài khoản dịch vụ được dùng để cho phép ứng dụng của bạn truy cập vào Subscription linking API (API Liên kết gói thuê bao).

  1. Tạo tài khoản dịch vụ trong Google Play.
  2. Tạo thông tin đăng nhập cho tài khoản dịch vụ rồi lưu trữ tệp credentials.json ở một vị trí an toàn mà ứng dụng của bạn có thể truy cập.
  3. Cấp cho vai trò IAM "Quản trị viên liên kết gói thuê bao" vào tài khoản dịch vụ bạn đã tạo. Để kiểm soát chi tiết các khả năng của tài khoản dịch vụ, bạn có thể chỉ định vai trò thích hợp trong bảng sau.
Chức năng / Vai trò Quản trị viên liên kết gói thuê bao Người xem liên kết gói thuê bao Người xem có quyền liên kết gói thuê bao
Nhận quyền của độc giả
Thu hút độc giả
Cập nhật quyền của độc giả
Xoá độc giả

Sử dụng tài khoản dịch vụ bằng Subscription linking API (API Liên kết gói thuê bao)

Sử dụng tài khoản dịch vụ để xác thực lệnh gọi đến Subscription linking API (API Liên kết gói thuê bao), với thư viện ứng dụng googleapis hoặc bằng cách ký các yêu cầu bằng API REST. Thư viện ứng dụng tự động xử lý việc yêu cầu access_token thích hợp, trong khi API REST yêu cầu truy xuất một id_token rồi đổi lấy access_token.

Cả ứng dụng sau thư viện và các ví dụ về API REST sử dụng điểm cuối getReader(). Để phát trực tiếp phần minh hoạ về tất cả các phương thức API, hãy xem Trang web Bản minh hoạ về cách liên kết gói thuê bao hoặc của trang web đó.

Yêu cầu mẫu với thư viện ứng dụng googleapis củanode.js

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
  });
};

Ký yêu cầu API REST theo cách thủ công

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
}