ادغام سمت سرور

ناشران در درجه اول از ادغام سمت سرور برای مدیریت خوانندگان و حقوق آنها استفاده می کنند. در درجه اول، ناشران از UpdateReaderEntitlements برای به‌روزرسانی سابقه Google در مورد حق شناسه محصول برای یک PPID استفاده می‌کنند.

راه اندازی Google Cloud

پیکربندی پیوند اشتراک در Google Cloud شامل دو جزء اصلی است:

  1. فعال کردن API برای یک پروژه معین
  2. ایجاد یک حساب کاربری برای دسترسی به api

API پیوند اشتراک را فعال کنید

برای استفاده از یک حساب سرویس و مدیریت حقوق خواننده، یک پروژه Google Cloud باید هم API پیوند اشتراک را فعال کرده و هم یک حساب سرویس OAuth به درستی پیکربندی شده باشد. برای فعال کردن API پیوند اشتراک برای یک پروژه، از منو -> APIs & Services -> Library پیمایش کنید و Subscription Linking جستجو کنید، یا مستقیماً از صفحه بازدید کنید:


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

api

شکل 1. پیمایش به کتابخانه API و فعال کردن API برای پروژه Google Cloud.

یک حساب خدمات ایجاد کنید

حساب‌های سرویس برای اجازه دسترسی از برنامه شما به API پیوند اشتراک استفاده می‌شوند.

  1. یک حساب سرویس در کنسول پروژه خود ایجاد کنید .
  2. اعتبارنامه ها را برای حساب سرویس ایجاد کنید و فایل credentials.json را در مکانی امن و قابل دسترسی برای برنامه خود ذخیره کنید.
  3. نقش IAM "Subscription Linking Admin" را به حساب سرویسی که ایجاد کردید اعطا کنید . برای کنترل دقیق بر روی قابلیت های اکانت سرویس، می توانید نقش مناسب را از جدول زیر اختصاص دهید.
قابلیت / نقش مدیریت پیوند اشتراک مشاهده کننده پیوند اشتراک مشاهده کننده حقوق پیوند اشتراک
حقوق خواننده را دریافت کنید
خوانندگان را دریافت کنید
به روز رسانی حقوق خواننده
خوانندگان را حذف کنید

از حساب‌های سرویس با API پیوند اشتراک استفاده کنید

از حساب‌های سرویس برای احراز هویت تماس‌ها به 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
}