Serverseitige Integration

Die serverseitige Integration verwenden Verlage und Webpublisher hauptsächlich, um Leser und ihre Berechtigungen zu verwalten. In erster Linie verwenden Publisher UpdateReaderEntitlements, um den Google-Eintrag einer Produkt-ID-Berechtigung für eine PPID zu aktualisieren.

Google Cloud-Einrichtung

Das Konfigurieren der Aboverknüpfung in Google Cloud umfasst zwei Hauptkomponenten:

  1. API für ein bestimmtes Projekt aktivieren
  2. Dienstkonto für den Zugriff auf die API erstellen

Subscription Linking API aktivieren

Damit ein Dienstkonto verwendet und die Berechtigungen eines Lesers verwaltet werden können, muss in einem Google Cloud-Projekt sowohl die Subscription Linking API als auch ein ordnungsgemäß konfiguriertes OAuth-Dienstkonto aktiviert sein. Wenn du die Subscription Linking API für ein Projekt aktivieren möchtest, öffne das Menü -> „APIs und Dienste“ -> „Bibliothek“ und suche nach Subscription Linking. Du kannst die Seite aber auch direkt aufrufen:


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

api

Abbildung 1: API-Bibliothek aufrufen und die API für ein Google Cloud-Projekt aktivieren

Dienstkonto erstellen

Dienstkonten werden verwendet, um den Zugriff deiner Anwendung auf die Subscription Linking API zu ermöglichen.

  1. Erstellen Sie ein Dienstkonto in der Konsole Ihres Projekts.
  2. Erstellen Sie Anmeldedaten für das Dienstkonto und speichern Sie die Datei credentials.json an einem sicheren Ort, auf den Ihre Anwendung zugreifen kann.
  3. Weisen Sie dem von Ihnen erstellten Dienstkonto die IAM-Rolle „Aboverknüpfungsadministrator“ zu. Für eine detaillierte Kontrolle über die Berechtigungen des Dienstkontos können Sie die entsprechende Rolle aus der folgenden Tabelle zuweisen.
Funktion / Rolle Administrator von Aboverknüpfungen Betrachter von Aboverknüpfungen Betrachter von Berechtigungen für Aboverknüpfungen
Leserberechtigungen abrufen
Leser gewinnen
Leserberechtigungen aktualisieren
Leser löschen

Dienstkonten mit der Subscription Linking API verwenden

Verwende Dienstkonten, um Aufrufe der Subscription Linking API zu authentifizieren. Dazu kannst du entweder die googleapis-Clientbibliothek verwenden oder Anfragen mit der REST API signieren. Die Clientbibliotheken fordern automatisch das entsprechende access_token an. Bei der REST API muss hingegen ein id_token abgerufen und dann gegen ein access_token ausgetauscht werden.

Die folgende Clientbibliothek und die folgende REST API verwenden den Endpunkt getReader(). Eine Live-Demo aller API-Methoden findest du auf der Demoseite für die Aboverknüpfung oder im entsprechenden Code.

Beispielanfrage mit der googleapis-Clientbibliothek für Node.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}`,
  })
}

REST API-Anfragen manuell signieren

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
}