Web API を使ってみる

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

Web API を使用する前に、前提条件を満たす必要があります。Web API で処理を行うには、サービス アカウントとサービス アカウント キーが必要です。また、サービス アカウントへのアクセス権を付与して Google Wallet API を呼び出す必要があります。

GitHub からサンプルコードをダウンロードして、以下の手順で参照するコード スニペットを実行します。

認証と認可

Google Wallet API へのリクエストは、アプリケーションがリクエストであることを Google Wallet API が識別できるように、認証される必要があります。そのためには、サービス アカウント キーを使用してアクセス トークンを取得します。

まず、必要なライブラリのインポートを行い、サービス アカウント JSON の変数と、保存する発行者、クラス、一意のユーザー、オブジェクトの ID を定義します。

Java

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.google.api.client.googleapis.batch.BatchRequest;
import com.google.api.client.googleapis.batch.json.JsonBatchCallback;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.googleapis.json.GoogleJsonError;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.*;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.walletobjects.Walletobjects;
import com.google.api.services.walletobjects.model.*;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;
import java.io.*;
import java.security.interfaces.RSAPrivateKey;
import java.util.*;

/** Demo class for creating and managing Loyalty cards in Google Wallet. */
public class DemoLoyalty {
  /**
   * Path to service account key file from Google Cloud Console. Environment variable:
   * GOOGLE_APPLICATION_CREDENTIALS.
   */
  public static String keyFilePath;

  /** Service account credentials for Google Wallet APIs. */
  public static GoogleCredentials credentials;

  /** Google Wallet service client. */
  public static Walletobjects service;

  public DemoLoyalty() {
    keyFilePath =
        System.getenv().getOrDefault("GOOGLE_APPLICATION_CREDENTIALS", "/path/to/key.json");
  }

PHP

use Firebase\JWT\JWT;
use Google\Auth\Credentials\ServiceAccountCredentials;
use Google\Client as Google_Client;

/** Demo class for creating and managing Loyalty cards in Google Wallet. */
class DemoLoyalty
{
  /**
   * Path to service account key file from Google Cloud Console. Environment
   * variable: GOOGLE_APPLICATION_CREDENTIALS.
   */
  public string $keyFilePath;

  /**
   * Service account credentials for Google Wallet APIs.
   */
  public ServiceAccountCredentials $credentials;

  /**
   * Google Wallet service client.
   */
  public Google_Service_Walletobjects $service;

  public function __construct()
  {
    $this->keyFilePath = getenv('GOOGLE_APPLICATION_CREDENTIALS') ?: '/path/to/key.json';
  }

Python

import json
import os
import re
from typing import List
import uuid

from google.auth.transport.requests import AuthorizedSession
from google.oauth2.service_account import Credentials
from google.auth import jwt, crypt


class DemoLoyalty:
    """Demo class for creating and managing Loyalty cards in Google Wallet.

    Attributes:
        key_file_path: Path to service account key file from Google Cloud
            Console. Environment variable: GOOGLE_APPLICATION_CREDENTIALS.
        base_url: Base URL for Google Wallet API requests.
    """

    def __init__(self):
        self.key_file_path = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS',
                                            '/path/to/key.json')
        self.base_url = 'https://walletobjects.googleapis.com/walletobjects/v1'

        # Set up authenticated client
        self.auth()

C#

using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Headers;
using System.Text.RegularExpressions;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Walletobjects.v1;
using Google.Apis.Walletobjects.v1.Data;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;


/// <summary>
/// Demo class for creating and managing Loyalty cards in Google Wallet.
/// </summary>
class DemoLoyalty
{
  /// <summary>
  /// Path to service account key file from Google Cloud Console. Environment
  /// variable: GOOGLE_APPLICATION_CREDENTIALS.
  /// </summary>
  public static string keyFilePath;

  /// <summary>
  /// Service account credentials for Google Wallet APIs
  /// </summary>
  public static ServiceAccountCredential credentials;

  /// <summary>
  /// Google Wallet service client
  /// </summary>
  public static WalletobjectsService service;

  public DemoLoyalty()
  {
    keyFilePath = Environment.GetEnvironmentVariable(
        "GOOGLE_APPLICATION_CREDENTIALS") ?? "/path/to/key.json";
  }

Node.js

const { GoogleAuth } = require('google-auth-library');
const jwt = require('jsonwebtoken');
const { v4: uuidv4 } = require('uuid');

/**
 * Demo class for creating and managing Loyalty cards in Google Wallet.
 */
class DemoLoyalty {
  constructor() {
    /**
     * Path to service account key file from Google Cloud Console. Environment
     * variable: GOOGLE_APPLICATION_CREDENTIALS.
     */
    this.keyFilePath = process.env.GOOGLE_APPLICATION_CREDENTIALS || '/path/to/key.json';

    /**
     * Base URL for Google Wallet API requests.
     */
    this.baseUrl = 'https://walletobjects.googleapis.com/walletobjects/v1'
  }

次に、いずれかのフレームワーク ライブラリを使用して、{ api_name } を呼び出すために必要な認証情報を取得します。

Java

/**
 * Create authenticated HTTP client using a service account file.
 *
 * @throws Exception
 */
public void Auth() throws Exception {
  String scope = "https://www.googleapis.com/auth/wallet_object.issuer";

  credentials =
      GoogleCredentials.fromStream(new FileInputStream(keyFilePath))
          .createScoped(Arrays.asList(scope));
  credentials.refresh();

  HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();

  service =
      new Walletobjects.Builder(
              httpTransport,
              GsonFactory.getDefaultInstance(),
              new HttpCredentialsAdapter(credentials))
          .setApplicationName("APPLICATION_NAME")
          .build();
}

PHP

/**
 * Create authenticated HTTP client using a service account file.
 */
public function auth()
{
  $scope = 'https://www.googleapis.com/auth/wallet_object.issuer';

  $this->credentials = new ServiceAccountCredentials(
    $scope,
    $this->keyFilePath
  );

  // Initialize Google Wallet API service
  $this->client = new Google_Client();
  $this->client->setApplicationName('APPLICATION_NAME');
  $this->client->setScopes($scope);
  $this->client->setAuthConfig($this->keyFilePath);

  $this->service = new Google_Service_Walletobjects($this->client);
}

Python

def auth(self):
    """Create authenticated HTTP client using a service account file."""
    self.credentials = Credentials.from_service_account_file(
        self.key_file_path,
        scopes=['https://www.googleapis.com/auth/wallet_object.issuer'])

    self.http_client = AuthorizedSession(self.credentials)

C#

/// <summary>
/// Create authenticated service client using a service account file.
/// </summary>
public void Auth()
{
  credentials = (ServiceAccountCredential)GoogleCredential
      .FromFile(keyFilePath)
      .CreateScoped(new[]
      {
        "https://www.googleapis.com/auth/wallet_object.issuer"
      })
      .UnderlyingCredential;

  service = new WalletobjectsService(
    new BaseClientService.Initializer()
    {
      HttpClientInitializer = credentials,
    });
}

Node.js

/**
 * Create authenticated HTTP client using a service account file.
 */
auth() {
  this.credentials = require(this.keyFilePath);

  this.httpClient = new GoogleAuth({
    credentials: this.credentials,
    scopes: 'https://www.googleapis.com/auth/wallet_object.issuer',
  });
}

パス オブジェクトの作成

パス オブジェクトはパスクラスのインスタンスです。パス オブジェクトを作成するには、次の属性を指定する必要があります。

  • classId: パスクラスの ID
  • id: 顧客の一意のロイヤリティ メンバーシップ ID
  • state: 作成中の新しいパスの場合は active

また、次の属性を含めることをおすすめします。

  • accountId
  • accountName

ポイントのパスでこれらの属性がどのように表示されるかについて詳しくは、テンプレートのガイドラインをご覧ください。

パス オブジェクトを作成するコードサンプル:

HTTP

POST /walletobjects/v1/loyaltyObject HTTP/1.1
Host: walletobjects.googleapis.com
Content-Type: application/json
Authorization: Bearer ACCESS_TOKEN;
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

{
  "id": "ISSUER_ID.OBJECT_ID",
  "classId": "ISSUER_ID.CLASS_SUFFIX",
  "state": "ACTIVE",
  "heroImage": {
    "sourceUri": {
      "uri": "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg"
    },
    "contentDescription": {
      "defaultValue": {
        "language": "en-US",
        "value": "Hero image description"
      }
    }
  },
  "textModulesData": [
    {
      "header": "Text module header",
      "body": "Text module body",
      "id": "TEXT_MODULE_ID"
    }
  ],
  "linksModuleData": {
    "uris": [
      {
        "uri": "http://maps.google.com/",
        "description": "Link module URI description",
        "id": "LINK_MODULE_URI_ID"
      },
      {
        "uri": "tel:6505555555",
        "description": "Link module tel description",
        "id": "LINK_MODULE_TEL_ID"
      }
    ]
  },
  "imageModulesData": [
    {
      "mainImage": {
        "sourceUri": {
          "uri": "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg"
        },
        "contentDescription": {
          "defaultValue": {
            "language": "en-US",
            "value": "Image module description"
          }
        }
      },
      "id": "IMAGE_MODULE_ID"
    }
  ],
  "barcode": {
    "type": "QR_CODE",
    "value": "QR code"
  },
  "locations": [
    {
      "latitude": 37.424015499999996,
      "longitude": -122.09259560000001
    }
  ],
  "accountId": "Account id",
  "accountName": "Account name",
  "loyaltyPoints": {
    "label": "Points",
    "balance": {
      "int": 800
    }
  }
}

Java

/**
 * Create an object via the API.
 *
 * @param issuerId The issuer ID being used for this request.
 * @param classSuffix Developer-defined unique ID for this pass class.
 * @param userId Developer-defined user ID for this object.
 * @return The pass object ID: "{issuerId}.{userId}"
 * @throws IOException
 */
public String CreateLoyaltyObject(String issuerId, String classSuffix, String userId)
    throws IOException {
  // Generate the object ID
  // Should only include alphanumeric characters, '.', '_', or '-'
  String newUserId = userId.replaceAll("[^\\w.-]", "_");
  String objectId = String.format("%s.%s", issuerId, newUserId);

  try {
    // Check if the object exists
    LoyaltyObject response = service.loyaltyobject().get(objectId).execute();

    System.out.println("Object get response");
    System.out.println(response.toPrettyString());

    return response.getId();
  } catch (GoogleJsonResponseException ex) {
    if (ex.getStatusCode() != 404) {
      // Something else went wrong
      ex.printStackTrace();
      return ex.getMessage();
    }
  }

  // Object doesn't exist, create it now
  // See link below for more information on required properties
  // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject
  LoyaltyObject loyaltyObject =
      new LoyaltyObject()
          .setId(objectId)
          .setClassId(String.format("%s.%s", issuerId, classSuffix))
          .setState("ACTIVE")
          .setHeroImage(
              new Image()
                  .setSourceUri(
                      new ImageUri()
                          .setUri(
                              "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg"))
                  .setContentDescription(
                      new LocalizedString()
                          .setDefaultValue(
                              new TranslatedString()
                                  .setLanguage("en-US")
                                  .setValue("Hero image description"))))
          .setTextModulesData(
              Arrays.asList(
                  new TextModuleData()
                      .setHeader("Text module header")
                      .setBody("Text module body")
                      .setId("TEXT_MODULE_ID")))
          .setLinksModuleData(
              new LinksModuleData()
                  .setUris(
                      Arrays.asList(
                          new Uri()
                              .setUri("http://maps.google.com/")
                              .setDescription("Link module URI description")
                              .setId("LINK_MODULE_URI_ID"),
                          new Uri()
                              .setUri("tel:6505555555")
                              .setDescription("Link module tel description")
                              .setId("LINK_MODULE_TEL_ID"))))
          .setImageModulesData(
              Arrays.asList(
                  new ImageModuleData()
                      .setMainImage(
                          new Image()
                              .setSourceUri(
                                  new ImageUri()
                                      .setUri(
                                          "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg"))
                              .setContentDescription(
                                  new LocalizedString()
                                      .setDefaultValue(
                                          new TranslatedString()
                                              .setLanguage("en-US")
                                              .setValue("Image module description"))))
                      .setId("IMAGE_MODULE_ID")))
          .setBarcode(new Barcode().setType("QR_CODE").setValue("QR code value"))
          .setLocations(
              Arrays.asList(
                  new LatLongPoint()
                      .setLatitude(37.424015499999996)
                      .setLongitude(-122.09259560000001)))
          .setAccountId("Account ID")
          .setAccountName("Account name")
          .setLoyaltyPoints(
              new LoyaltyPoints()
                  .setLabel("Points")
                  .setBalance(new LoyaltyPointsBalance().setInt(800)));

  LoyaltyObject response = service.loyaltyobject().insert(loyaltyObject).execute();

  System.out.println("Object insert response");
  System.out.println(response.toPrettyString());

  return response.getId();
}

PHP

/**
 * Create an object via the API.
 *
 * @param string $issuerId The issuer ID being used for this request.
 * @param string $classSuffix Developer-defined unique ID for this pass class.
 * @param string $userId Developer-defined user ID for this pass object.
 *
 * @return string The pass object ID: "{$issuerId}.{$userId}"
 */
public function createLoyaltyObject(string $issuerId, string $classSuffix, string $userId)
{
  // Generate the object ID
  // Should only include alphanumeric characters, '.', '_', or '-'
  $newUserId = preg_replace('/[^\w.-]/i', '_', $userId);
  $objectId = "{$issuerId}.{$newUserId}";

  // See link below for more information on required properties
  // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject
  $loyaltyObject = new Google_Service_Walletobjects_LoyaltyObject([
    'id' => "{$objectId}",
    'classId' => "{$issuerId}.{$classSuffix}",
    'state' => 'ACTIVE',
    'heroImage' => new Google_Service_Walletobjects_Image([
      'sourceUri' => new Google_Service_Walletobjects_ImageUri([
        'uri' => 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg',
      ]),
      'contentDescription' => new Google_Service_Walletobjects_LocalizedString([
        'defaultValue' => new Google_Service_Walletobjects_TranslatedString([
          'language' => 'en-US',
          'value' => 'Hero image description',
        ]),
      ]),
    ]),
    'textModulesData' => [
      new Google_Service_Walletobjects_TextModuleData([
        'header' => 'Text module header',
        'body' => 'Text module body',
        'id' => 'TEXT_MODULE_ID',
      ]),
    ],
    'linksModuleData' => new Google_Service_Walletobjects_LinksModuleData([
      'uris' => [
        new Google_Service_Walletobjects_Uri([
          'uri' => 'http://maps.google.com/',
          'description' => 'Link module URI description',
          'id' => 'LINK_MODULE_URI_ID',
        ]),
        new Google_Service_Walletobjects_Uri([
          'uri' => 'tel:6505555555',
          'description' => 'Link module tel description',
          'id' => 'LINK_MODULE_TEL_ID',
        ]),
      ],
    ]),
    'imageModulesData' => [
      new Google_Service_Walletobjects_ImageModuleData([
        'mainImage' => new Google_Service_Walletobjects_Image([
          'sourceUri' => new Google_Service_Walletobjects_ImageUri([
            'uri' => 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg',
          ]),
          'contentDescription' => new Google_Service_Walletobjects_LocalizedString([
            'defaultValue' => new Google_Service_Walletobjects_TranslatedString([
              'language' => 'en-US',
              'value' => 'Image module description',
            ]),
          ]),
        ]),
        'id' => 'IMAGE_MODULE_ID',
      ])
    ],
    'barcode' => new Google_Service_Walletobjects_Barcode([
      'type' => 'QR_CODE',
      'value' => 'QR code value',
    ]),
    'locations' => [
      new Google_Service_Walletobjects_LatLongPoint([
        'latitude' => 37.424015499999996,
        'longitude' =>  -122.09259560000001,
      ]),
    ],
    'accountId' => 'Account ID',
    'accountName' => 'Account name',
    'loyaltyPoints' => new Google_Service_Walletobjects_LoyaltyPoints([
      'balance' => new Google_Service_Walletobjects_LoyaltyPointsBalance([
        'int' => 800,
      ]),
    ]),
  ]);

  try {
    $response = $this->service->loyaltyobject->insert($loyaltyObject);

    print "Object insert response\n";
    print_r($response);

    return $response->id;
  } catch (Google\Service\Exception $ex) {
    if ($ex->getCode() == 409) {
      print "Object {$objectId} already exists";
      return;
    }

    // Something else went wrong
    print $ex->getTraceAsString();
  }
}

Python

def create_loyalty_object(self, issuer_id: str, class_suffix: str,
                          user_id: str) -> str:
    """Create an object via the API.

    Args:
        issuer_id (str): The issuer ID being used for this request.
        class_suffix (str): Developer-defined unique ID for this pass class.
        user_id (str): Developer-defined user ID for this pass object.

    Returns:
        The pass object ID: f"{issuer_id}.{user_id}"
    """
    object_url = f'{self.base_url}/loyaltyObject'

    # Generate the object ID
    # Should only include alphanumeric characters, '.', '_', or '-'
    new_user_id = re.sub(r'[^\w.-]', '_', user_id)
    object_id = f'{issuer_id}.{new_user_id}'

    # See below for more information on required properties
    # https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject
    loyalty_object = {
        'id': f'{object_id}',
        'classId': f'{issuer_id}.{class_suffix}',
        'state': 'ACTIVE',
        'heroImage': {
            'sourceUri': {
                'uri':
                    'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg',
            },
            'contentDescription': {
                'defaultValue': {
                    'language': 'en-US',
                    'value': 'Hero image description',
                },
            },
        },
        'textModulesData': [{
            'header': 'Text module header',
            'body': 'Text module body',
            'id': 'TEXT_MODULE_ID',
        },],
        'linksModuleData': {
            'uris': [
                {
                    'uri': 'http://maps.google.com/',
                    'description': 'Link module URI description',
                    'id': 'LINK_MODULE_URI_ID',
                },
                {
                    'uri': 'tel:6505555555',
                    'description': 'Link module tel description',
                    'id': 'LINK_MODULE_TEL_ID',
                },
            ],
        },
        'imageModulesData': [{
            'mainImage': {
                'sourceUri': {
                    'uri':
                        'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg',
                },
                'contentDescription': {
                    'defaultValue': {
                        'language': 'en-US',
                        'value': 'Image module description',
                    },
                },
            },
            'id': 'IMAGE_MODULE_ID',
        },],
        'barcode': {
            'type': 'QR_CODE',
            'value': 'QR code',
        },
        'locations': [{
            'latitude': 37.424015499999996,
            'longitude': -122.09259560000001,
        },],
        'accountId': 'Account id',
        'accountName': 'Account name',
        'loyaltyPoints': {
            'label': 'Points',
            'balance': {
                'int': 800,
            },
        },
    }

    response = self.http_client.get(f'{object_url}{object_id}')
    if response.status_code == 404:
        # Object does not yet exist
        # Send POST request to create it
        response = self.http_client.post(
            url=object_url,
            json=loyalty_object,
        )

        print('Object insert response')
        print(response.text)
    else:
        print('Object get response')
        print(response.text)

    return response.json().get('id')

C#

/// <summary>
/// Create an object via the API.
/// </summary>
/// <param name="issuerId">The issuer ID being used for this request.</param>
/// <param name="classSuffix">Developer-defined unique ID for this pass class.</param>
/// <param name="userId">Developer-defined user ID for this object.</param>
/// <returns>The pass object ID: "{issuerId}.{userId}"</returns>
public string CreateLoyaltyObject(string issuerId, string classSuffix, string userId)
{
  // Generate the object ID
  // Should only include alphanumeric characters, '.', '_', or '-'
  string newUserId = new Regex(@"[^\w.-]", RegexOptions.Compiled)
      .Replace(userId, "_");
  string objectId = $"{issuerId}.{newUserId}";

  // Check if the object exists
  Stream responseStream = service.Loyaltyclass
      .Get(objectId)
      .ExecuteAsStream();
  StreamReader responseReader = new StreamReader(responseStream);
  JObject jsonResponse = JObject.Parse(responseReader.ReadToEnd());

  if (jsonResponse.ContainsKey("error"))
  {
    if (jsonResponse["error"].Value<int>("code") == 404)
    {
      // Object does not exist
      // Send insert request to create it
      // See link below for more information on required properties
      // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject
      LoyaltyObject loyaltyObject = new LoyaltyObject
      {
        Id = objectId,
        ClassId = $"{issuerId}.{classSuffix}",
        State = "ACTIVE",
        HeroImage = new Image
        {
          SourceUri = new ImageUri
          {
            Uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg"
          },
          ContentDescription = new LocalizedString
          {
            DefaultValue = new TranslatedString
            {
              Language = "en-US",
              Value = "Hero image description"
            }
          }
        },
        TextModulesData = new List<TextModuleData>
        {
          new TextModuleData
          {
            Header = "Text module header",
            Body = "Text module body",
            Id = "TEXT_MODULE_ID"
          }
        },
        LinksModuleData = new LinksModuleData
        {
          Uris = new List<Google.Apis.Walletobjects.v1.Data.Uri>
          {
            new Google.Apis.Walletobjects.v1.Data.Uri
            {
              UriValue = "http://maps.google.com/",
              Description = "Link module URI description",
              Id = "LINK_MODULE_URI_ID"
            },
            new Google.Apis.Walletobjects.v1.Data.Uri
            {
              UriValue = "tel:6505555555",
              Description = "Link module tel description",
              Id = "LINK_MODULE_TEL_ID"
            }
          }
        },
        ImageModulesData = new List<ImageModuleData>
        {
          new ImageModuleData
          {
            MainImage = new Image
            {
              SourceUri = new ImageUri
              {
                Uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg"
              },
              ContentDescription = new LocalizedString
              {
                DefaultValue = new TranslatedString
                {
                  Language = "en-US",
                  Value = "Image module description"
                }
              }
            },
            Id = "IMAGE_MODULE_ID"
          }
        },
        Barcode = new Barcode
        {
          Type = "QR_CODE",
          Value = "QR code"
        },
        Locations = new List<LatLongPoint>
        {
          new LatLongPoint
          {
            Latitude = 37.424015499999996,
            Longitude = -122.09259560000001
          }
        },
        AccountId = "Account id",
        AccountName = "Account name",
        LoyaltyPoints = new LoyaltyPoints
        {
          Label = "Points",
          Balance = new LoyaltyPointsBalance
          {
            Int__ = 800
          }
        }
      };

      responseStream = service.Loyaltyobject
          .Insert(loyaltyObject)
          .ExecuteAsStream();
      responseReader = new StreamReader(responseStream);
      jsonResponse = JObject.Parse(responseReader.ReadToEnd());

      Console.WriteLine("Object insert response");
      Console.WriteLine(jsonResponse.ToString());

      return jsonResponse.Value<string>("id");
    }
    else
    {
      Console.WriteLine("Something else went wrong");
      Console.WriteLine(jsonResponse.ToString());

      return jsonResponse.ToString();
    }
  }
  else
  {
    Console.WriteLine("Object get response");
    Console.WriteLine(jsonResponse.ToString());

    return jsonResponse.Value<string>("id");
  }
}

Node.js

/**
 * Create an object via the API.
 *
 * @param {string} issuerId The issuer ID being used for this request.
 * @param {string} classSuffix Developer-defined unique ID for this pass class.
 * @param {string} userId Developer-defined user ID for this object.
 *
 * @returns {string} The pass object ID: `${issuerId}.${userId}`
 */
async createLoyaltyObject(issuerId, classSuffix, userId) {
  const loyaltyObjectUrl = `${this.baseUrl}/loyaltyObject`;

  // Generate the object ID
  // Should only include alphanumeric characters, '.', '_', or '-'
  let objectId = `${issuerId}.${userId.replace(/[^\w.-]/g, '_')}`;

  // See link below for more information on required properties
  // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject
  let loyaltyObject = {
    'id': `${objectId}`,
    'classId': `${issuerId}.${classSuffix}`,
    'state': 'ACTIVE',
    'heroImage': {
      'sourceUri': {
        'uri': 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg',
      },
      'contentDescription': {
        'defaultValue': {
          'language': 'en-US',
          'value': 'Hero image description',
        },
      },
    },
    'textModulesData': [
      {
        'header': 'Text module header',
        'body': 'Text module body',
        'id': 'TEXT_MODULE_ID',
      },
    ],
    'linksModuleData': {
      'uris': [
        {
          'uri': 'http://maps.google.com/',
          'description': 'Link module URI description',
          'id': 'LINK_MODULE_URI_ID',
        },
        {
          'uri': 'tel:6505555555',
          'description': 'Link module tel description',
          'id': 'LINK_MODULE_TEL_ID',
        },
      ],
    },
    'imageModulesData': [
      {
        'mainImage': {
          'sourceUri': {
            'uri': 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg',
          },
          'contentDescription': {
            'defaultValue': {
              'language': 'en-US',
              'value': 'Image module description',
            },
          },
        },
        'id': 'IMAGE_MODULE_ID',
      },
    ],
    'barcode': {
      'type': 'QR_CODE',
      'value': 'QR code',
    },
    'locations': [
      {
        'latitude': 37.424015499999996,
        'longitude': -122.09259560000001,
      },
    ],
    'accountId': 'Account id',
    'accountName': 'Account name',
    'loyaltyPoints': {
      'label': 'Points',
      'balance': {
        'int': 800,
      },
    },
  };

  let response;
  try {
    response = await this.httpClient.request({
      url: `${loyaltyObjectUrl}/${objectId}`,
      method: 'GET',
    });

    console.log('Object get response');
    console.log(response);

    return response.data.id;
  } catch (err) {
    if (err.response && err.response.status === 404) {
      // Object does not yet exist
      // Send POST request to create it
      response = await this.httpClient.request({
        url: loyaltyObjectUrl,
        method: 'POST',
        data: loyaltyObject,
      });

      console.log('Object insert response');
      console.log(response);

      return response.data.id;
    } else {
      // Something else went wrong
      console.log(err);
    }
  }
}

完了すると、お客様のオブジェクトがサーバー上に作成されます。ただし、この段階では、パス オブジェクトは Google ユーザーまたはデバイスにリンクされていません。パスを Google ウォレット ユーザーと関連付けるには、まず Google ウォレットにパスを追加する必要があります。

Google ウォレットへの追加

パスを Google ウォレットに追加すると、パスオブジェクトが Google ユーザーにリンクされ、ログインしている Google ID のコンテキストでのみ開始できます。これを行うには、[Google ウォレットに追加] の URL にユーザーを誘導します。

「Google ウォレットに追加」URL は、前の手順で作成したパス オブジェクト ID に関する次の情報を含む動的に生成される URL です。この情報は、JSON Web Token(JWT)としてエンコードされます。

JSON Web Token(JWT)

この JWT には、ユーザーが保存するパス オブジェクトに関する発行元によるクレームが含まれています。JWT は、サービス アカウントの作成手順で取得したサービス アカウント キーの private_key を使用して署名する必要があります。Google では、JWT 署名を検証してこれらのクレームを検証します。

JWT クレームの構造は次のとおりです。

{
  "aud": "google",
  "origins": ["https://example.com"],
  "iss": "my-service-account@my-project-id.iam.gserviceaccount.com",
  "typ": "savetowallet",
  "payload": {
    "loyaltyObjects": [
      {
        "id": "PASSES_OBJECT_ID_1234567890"
      }
    ]
  }
}

JWT claims を作成し、サービス アカウント キー private_key を使用してクレームに署名することで token を取得します。

Java

/**
 * Generate a signed JWT that creates a new pass class and object.
 *
 * <p>When the user opens the "Add to Google Wallet" URL and saves the pass to their wallet, the
 * pass class and object defined in the JWT are created. This allows you to create multiple pass
 * classes and objects in one API call when the user saves the pass to their wallet.
 *
 * @param issuerId The issuer ID being used for this request.
 * @param classSuffix Developer-defined unique ID for this pass class.
 * @param userId Developer-defined user ID for this object.
 * @return An "Add to Google Wallet" link.
 */
public String CreateJWTSaveURL(String issuerId, String classSuffix, String userId) {
  // Generate the object ID
  // Should only include alphanumeric characters, '.', '_', or '-'
  String newUserId = userId.replaceAll("[^\\w.-]", "_");
  String objectId = String.format("%s.%s", issuerId, newUserId);

  // See link below for more information on required properties
  // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyclass
  LoyaltyClass loyaltyClass =
      new LoyaltyClass()
          .setId(String.format("%s.%s", issuerId, classSuffix))
          .setIssuerName("Issuer name")
          .setReviewStatus("UNDER_REVIEW")
          .setProgramName("Program name")
          .setProgramLogo(
              new Image()
                  .setSourceUri(
                      new ImageUri()
                          .setUri(
                              "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg"))
                  .setContentDescription(
                      new LocalizedString()
                          .setDefaultValue(
                              new TranslatedString()
                                  .setLanguage("en-US")
                                  .setValue("Logo description"))));

  // See link below for more information on required properties
  // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject
  LoyaltyObject loyaltyObject =
      new LoyaltyObject()
          .setId(objectId)
          .setClassId(String.format("%s.%s", issuerId, classSuffix))
          .setState("ACTIVE")
          .setHeroImage(
              new Image()
                  .setSourceUri(
                      new ImageUri()
                          .setUri(
                              "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg"))
                  .setContentDescription(
                      new LocalizedString()
                          .setDefaultValue(
                              new TranslatedString()
                                  .setLanguage("en-US")
                                  .setValue("Hero image description"))))
          .setTextModulesData(
              Arrays.asList(
                  new TextModuleData()
                      .setHeader("Text module header")
                      .setBody("Text module body")
                      .setId("TEXT_MODULE_ID")))
          .setLinksModuleData(
              new LinksModuleData()
                  .setUris(
                      Arrays.asList(
                          new Uri()
                              .setUri("http://maps.google.com/")
                              .setDescription("Link module URI description")
                              .setId("LINK_MODULE_URI_ID"),
                          new Uri()
                              .setUri("tel:6505555555")
                              .setDescription("Link module tel description")
                              .setId("LINK_MODULE_TEL_ID"))))
          .setImageModulesData(
              Arrays.asList(
                  new ImageModuleData()
                      .setMainImage(
                          new Image()
                              .setSourceUri(
                                  new ImageUri()
                                      .setUri(
                                          "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg"))
                              .setContentDescription(
                                  new LocalizedString()
                                      .setDefaultValue(
                                          new TranslatedString()
                                              .setLanguage("en-US")
                                              .setValue("Image module description"))))
                      .setId("IMAGE_MODULE_ID")))
          .setBarcode(new Barcode().setType("QR_CODE").setValue("QR code value"))
          .setLocations(
              Arrays.asList(
                  new LatLongPoint()
                      .setLatitude(37.424015499999996)
                      .setLongitude(-122.09259560000001)))
          .setAccountId("Account ID")
          .setAccountName("Account name")
          .setLoyaltyPoints(
              new LoyaltyPoints()
                  .setLabel("Points")
                  .setBalance(new LoyaltyPointsBalance().setInt(800)));

  // Create the JWT as a HashMap object
  HashMap<String, Object> claims = new HashMap<String, Object>();
  claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail());
  claims.put("aud", "google");
  claims.put("origins", Arrays.asList("www.example.com"));
  claims.put("typ", "savetowallet");

  // Create the Google Wallet payload and add to the JWT
  HashMap<String, Object> payload = new HashMap<String, Object>();
  payload.put("loyaltyClasses", Arrays.asList(loyaltyClass));
  payload.put("loyaltyObjects", Arrays.asList(loyaltyObject));
  claims.put("payload", payload);

  // The service account credentials are used to sign the JWT
  Algorithm algorithm =
      Algorithm.RSA256(
          null, (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey());
  String token = JWT.create().withPayload(claims).sign(algorithm);

  System.out.println("Add to Google Wallet link");
  System.out.println(String.format("https://pay.google.com/gp/v/save/%s", token));

  return String.format("https://pay.google.com/gp/v/save/%s", token);
}

PHP

/**
 * Generate a signed JWT that creates a new pass class and object.
 *
 * When the user opens the "Add to Google Wallet" URL and saves the pass to
 * their wallet, the pass class and object defined in the JWT are
 * created.This allows you to create multiple pass classes and objects in
 * one API call when the user saves the pass to their wallet.
 *
 * @param string $issuerId The issuer ID being used for this request.
 * @param string $classSuffix Developer-defined class ID for this class.
 * @param string $userId Developer-defined user ID for this object.
 *
 * @return string An "Add to Google Wallet" link.
 */
public function createJwtSaveUrl(string $issuerId, string $classSuffix, string $userId)
{
  // Generate the object ID
  // Should only include alphanumeric characters, '.', '_', or '-'
  $newUserId = preg_replace('/[^\w.-]/i', '_', $userId);
  $objectId = "{$issuerId}.{$newUserId}";

  // See link below for more information on required properties
  // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyclass
  $loyaltyClass = new Google_Service_Walletobjects_LoyaltyClass([
    'id' => "{$issuerId}.{$classSuffix}",
    'issuerName' => 'Issuer name',
    'reviewStatus' => 'UNDER_REVIEW',
    'programName' => 'Program name',
    'programLogo' => new Google_Service_Walletobjects_Image([
      'sourceUri' => new Google_Service_Walletobjects_ImageUri([
        'uri' => 'http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg',
      ]),
      'contentDescription' => new Google_Service_Walletobjects_LocalizedString([
        'defaultValue' => new Google_Service_Walletobjects_TranslatedString([
          'language' => 'en-US',
          'value' => 'Logo description',
        ]),
      ]),
    ]),
  ]);

  // See link below for more information on required properties
  // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject
  $loyaltyObject = new Google_Service_Walletobjects_LoyaltyObject([
    'id' => "{$objectId}",
    'classId' => "{$issuerId}.{$classSuffix}",
    'state' => 'ACTIVE',
    'heroImage' => new Google_Service_Walletobjects_Image([
      'sourceUri' => new Google_Service_Walletobjects_ImageUri([
        'uri' => 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg',
      ]),
      'contentDescription' => new Google_Service_Walletobjects_LocalizedString([
        'defaultValue' => new Google_Service_Walletobjects_TranslatedString([
          'language' => 'en-US',
          'value' => 'Hero image description',
        ]),
      ]),
    ]),
    'textModulesData' => [
      new Google_Service_Walletobjects_TextModuleData([
        'header' => 'Text module header',
        'body' => 'Text module body',
        'id' => 'TEXT_MODULE_ID',
      ]),
    ],
    'linksModuleData' => new Google_Service_Walletobjects_LinksModuleData([
      'uris' => [
        new Google_Service_Walletobjects_Uri([
          'uri' => 'http://maps.google.com/',
          'description' => 'Link module URI description',
          'id' => 'LINK_MODULE_URI_ID',
        ]),
        new Google_Service_Walletobjects_Uri([
          'uri' => 'tel:6505555555',
          'description' => 'Link module tel description',
          'id' => 'LINK_MODULE_TEL_ID',
        ]),
      ],
    ]),
    'imageModulesData' => [
      new Google_Service_Walletobjects_ImageModuleData([
        'mainImage' => new Google_Service_Walletobjects_Image([
          'sourceUri' => new Google_Service_Walletobjects_ImageUri([
            'uri' => 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg',
          ]),
          'contentDescription' => new Google_Service_Walletobjects_LocalizedString([
            'defaultValue' => new Google_Service_Walletobjects_TranslatedString([
              'language' => 'en-US',
              'value' => 'Image module description',
            ]),
          ]),
        ]),
        'id' => 'IMAGE_MODULE_ID',
      ])
    ],
    'barcode' => new Google_Service_Walletobjects_Barcode([
      'type' => 'QR_CODE',
      'value' => 'QR code value',
    ]),
    'locations' => [
      new Google_Service_Walletobjects_LatLongPoint([
        'latitude' => 37.424015499999996,
        'longitude' =>  -122.09259560000001,
      ]),
    ],
    'accountId' => 'Account ID',
    'accountName' => 'Account name',
    'loyaltyPoints' => new Google_Service_Walletobjects_LoyaltyPoints([
      'balance' => new Google_Service_Walletobjects_LoyaltyPointsBalance([
        'int' => 800,
      ]),
    ]),
  ]);

  // Create the JWT as an array of key/value pairs
  $serviceAccount = json_decode(file_get_contents($this->keyFilePath), true);
  $claims = [
    'iss' => $serviceAccount['client_email'],
    'aud' => 'google',
    'origins' => ['www.example.com'],
    'typ' => 'savetowallet',
    'payload' => [
      'loyaltyClasses' => [
        $loyaltyClass,
      ],
      'loyaltyObjects' => [
        $loyaltyObject,
      ],
    ],
  ];

  // The service account credentials are used to sign the JWT
  $token = JWT::encode(
    $claims,
    $serviceAccount['private_key'],
    'RS256'
  );

  print "Add to Google Wallet link\n";
  print "https://pay.google.com/gp/v/save/{$token}";

  return "https://pay.google.com/gp/v/save/{$token}";
}

Python

def create_jwt_save_url(self, issuer_id: str, class_suffix: str,
                        user_id: str) -> str:
    """Generate a signed JWT that creates a new pass class and object.

    When the user opens the "Add to Google Wallet" URL and saves the pass to
    their wallet, the pass class and object defined in the JWT are
    created. This allows you to create multiple pass classes and objects in
    one API call when the user saves the pass to their wallet.

    Args:
        issuer_id (str): The issuer ID being used for this request.
        class_suffix (str): Developer-defined unique ID for this pass class.
        user_id (str): Developer-defined user ID for this pass object.

    Returns:
        An "Add to Google Wallet" link
    """

    # Generate the object ID
    # Should only include alphanumeric characters, '.', '_', or '-'
    new_user_id = re.sub(r'[^\w.-]', '_', user_id)
    object_id = f'{issuer_id}.{new_user_id}'

    # See below for more information on required properties
    # https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyclass
    loyalty_class = {
        'id': f'{issuer_id}.{class_suffix}',
        'issuerName': 'Issuer name',
        'reviewStatus': 'UNDER_REVIEW',
        'programName': 'Program name',
        'programLogo': {
            'sourceUri': {
                'uri':
                    'http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg',
            },
            'contentDescription': {
                'defaultValue': {
                    'language': 'en-US',
                    'value': 'Logo description',
                },
            },
        },
    }

    # See below for more information on required properties
    # https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject
    loyalty_object = {
        'id': f'{object_id}',
        'classId': f'{issuer_id}.{class_suffix}',
        'state': 'ACTIVE',
        'heroImage': {
            'sourceUri': {
                'uri':
                    'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg',
            },
            'contentDescription': {
                'defaultValue': {
                    'language': 'en-US',
                    'value': 'Hero image description',
                },
            },
        },
        'textModulesData': [{
            'header': 'Text module header',
            'body': 'Text module body',
            'id': 'TEXT_MODULE_ID',
        },],
        'linksModuleData': {
            'uris': [
                {
                    'uri': 'http://maps.google.com/',
                    'description': 'Link module URI description',
                    'id': 'LINK_MODULE_URI_ID',
                },
                {
                    'uri': 'tel:6505555555',
                    'description': 'Link module tel description',
                    'id': 'LINK_MODULE_TEL_ID',
                },
            ],
        },
        'imageModulesData': [{
            'mainImage': {
                'sourceUri': {
                    'uri':
                        'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg',
                },
                'contentDescription': {
                    'defaultValue': {
                        'language': 'en-US',
                        'value': 'Image module description',
                    },
                },
            },
            'id': 'IMAGE_MODULE_ID',
        },],
        'barcode': {
            'type': 'QR_CODE',
            'value': 'QR code',
        },
        'locations': [{
            'latitude': 37.424015499999996,
            'longitude': -122.09259560000001,
        },],
        'accountId': 'Account id',
        'accountName': 'Account name',
        'loyaltyPoints': {
            'label': 'Points',
            'balance': {
                'int': 800,
            },
        },
    }

    # Create the JWT claims
    claims = {
        'iss': self.credentials.service_account_email,
        'aud': 'google',
        'origins': ['www.example.com'],
        'typ': 'savetowallet',
        'payload': {
            # The listed classes and objects will be created
            'loyaltyClasses': [loyalty_class,],
            'loyaltyObjects': [loyalty_object,],
        },
    }

    # The service account credentials are used to sign the JWT
    signer = crypt.RSASigner.from_service_account_file(self.key_file_path)
    token = jwt.encode(signer, claims).decode('utf-8')

    print('Add to Google Wallet link')
    print(f'https://pay.google.com/gp/v/save/{token}')

    return f'https://pay.google.com/gp/v/save/{token}'

C#

/// <summary>
/// Generate a signed JWT that creates a new pass class and object.
///
/// When the user opens the "Add to Google Wallet" URL and saves the pass to
/// their wallet, the pass class and object defined in the JWT are created.
/// This allows you to create multiple pass classes and objects in
/// one API call when the user saves the pass to their wallet.
///
/// The Google Wallet C# library uses Newtonsoft.Json.JsonPropertyAttribute
/// to specify the property names when converting objects to JSON. The
/// Newtonsoft.Json.JsonConvert.SerializeObject method will automatically
/// serialize the object with the right property names.
///
/// </summary>
/// <param name="issuerId">The issuer ID being used for this request.</param>
/// <param name="classSuffix">Developer-defined unique ID for this pass class.</param>
/// <param name="userId">Developer-defined user ID for this object.</param>
/// <returns>An "Add to Google Wallet" link.</returns>
public string CreateJWTSaveURL(string issuerId, string classSuffix, string userId)
{
  // Ignore null values when serializing to/from JSON
  JsonSerializerSettings excludeNulls = new JsonSerializerSettings()
  {
    NullValueHandling = NullValueHandling.Ignore
  };

  // Generate the object ID
  // Should only include alphanumeric characters, '.', '_', or '-'
  string newUserId = new Regex(@"[^\w.-]", RegexOptions.Compiled)
      .Replace(userId, "_");
  string objectId = $"{issuerId}.{newUserId}";

  // See link below for more information on required properties
  // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyclass
  LoyaltyClass loyaltyClass = new LoyaltyClass
  {
    Id = $"{issuerId}.{classSuffix}",
    IssuerName = "Issuer name",
    ReviewStatus = "UNDER_REVIEW",
    ProgramName = "Program name",
    ProgramLogo = new Image
    {
      SourceUri = new ImageUri
      {
        Uri = "http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg"
      },
      ContentDescription = new LocalizedString
      {
        DefaultValue = new TranslatedString
        {
          Language = "en-US",
          Value = "Logo description"
        }
      }
    }
  };

  // Create a JSON representation of the class
  JObject serializedClass = JObject.Parse(
      JsonConvert.SerializeObject(loyaltyClass, excludeNulls));

  // See link below for more information on required properties
  // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject
  LoyaltyObject loyaltyObject = new LoyaltyObject
  {
    Id = objectId,
    ClassId = $"{issuerId}.{classSuffix}",
    State = "ACTIVE",
    HeroImage = new Image
    {
      SourceUri = new ImageUri
      {
        Uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg"
      },
      ContentDescription = new LocalizedString
      {
        DefaultValue = new TranslatedString
        {
          Language = "en-US",
          Value = "Hero image description"
        }
      }
    },
    TextModulesData = new List<TextModuleData>
    {
      new TextModuleData
      {
        Header = "Text module header",
        Body = "Text module body",
        Id = "TEXT_MODULE_ID"
      }
    },
    LinksModuleData = new LinksModuleData
    {
      Uris = new List<Google.Apis.Walletobjects.v1.Data.Uri>
        {
          new Google.Apis.Walletobjects.v1.Data.Uri
          {
            UriValue = "http://maps.google.com/",
            Description = "Link module URI description",
            Id = "LINK_MODULE_URI_ID"
          },
          new Google.Apis.Walletobjects.v1.Data.Uri
          {
            UriValue = "tel:6505555555",
            Description = "Link module tel description",
            Id = "LINK_MODULE_TEL_ID"
          }
        }
    },
    ImageModulesData = new List<ImageModuleData>
    {
      new ImageModuleData
      {
        MainImage = new Image
        {
          SourceUri = new ImageUri
          {
            Uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg"
          },
          ContentDescription = new LocalizedString
          {
            DefaultValue = new TranslatedString
            {
              Language = "en-US",
              Value = "Image module description"
            }
          }
        },
        Id = "IMAGE_MODULE_ID"
      }
    },
    Barcode = new Barcode
    {
      Type = "QR_CODE",
      Value = "QR code"
    },
    Locations = new List<LatLongPoint>
    {
      new LatLongPoint
      {
        Latitude = 37.424015499999996,
        Longitude = -122.09259560000001
      }
    },
    AccountId = "Account id",
    AccountName = "Account name",
    LoyaltyPoints = new LoyaltyPoints
    {
      Label = "Points",
      Balance = new LoyaltyPointsBalance
      {
        Int__ = 800
      }
    }
  };

  // Create a JSON representation of the pass
  JObject serializedObject = JObject.Parse(
      JsonConvert.SerializeObject(loyaltyObject, excludeNulls));

  // Create the JWT as a JSON object
  JObject jwtPayload = JObject.Parse(JsonConvert.SerializeObject(new
  {
    iss = credentials.Id,
    aud = "google",
    origins = new string[]
    {
      "www.example.com"
    },
    typ = "savetowallet",
    payload = JObject.Parse(JsonConvert.SerializeObject(new
    {
      // The listed classes and objects will be created
      // when the user saves the pass to their wallet
      loyaltyClasses = new JObject[]
      {
        serializedClass
      },
      loyaltyObjects = new JObject[]
      {
        serializedObject
      }
    })),
  }));

  // Deserialize into a JwtPayload
  JwtPayload claims = JwtPayload.Deserialize(jwtPayload.ToString());

  // The service account credentials are used to sign the JWT
  RsaSecurityKey key = new RsaSecurityKey(credentials.Key);
  SigningCredentials signingCredentials = new SigningCredentials(
      key, SecurityAlgorithms.RsaSha256);
  JwtSecurityToken jwt = new JwtSecurityToken(
      new JwtHeader(signingCredentials), claims);
  string token = new JwtSecurityTokenHandler().WriteToken(jwt);

  Console.WriteLine("Add to Google Wallet link");
  Console.WriteLine($"https://pay.google.com/gp/v/save/{token}");

  return $"https://pay.google.com/gp/v/save/{token}";
}

Node.js

/**
 * Generate a signed JWT that creates a new pass class and object.
 *
 * When the user opens the "Add to Google Wallet" URL and saves the pass to
 * their wallet, the pass class and object defined in the JWT are
 * created. This allows you to create multiple pass classes and objects in
 * one API call when the user saves the pass to their wallet.
 *
 * @param {string} issuerId The issuer ID being used for this request.
 * @param {string} classSuffix Developer-defined unique ID for this pass class.
 * @param {string} userId Developer-defined user ID for this object.
 *
 * @returns {string} An "Add to Google Wallet" link.
 */
createJwtSaveUrl(issuerId, classSuffix, userId) {
  // Generate the object ID
  // Should only include alphanumeric characters, '.', '_', or '-'
  let objectId = `${issuerId}.${userId.replace(/[^\w.-]/g, '_')}`;

  // See link below for more information on required properties
  // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyclass
  let loyaltyClass = {
    'id': `${issuerId}.${classSuffix}`,
    'issuerName': 'Issuer name',
    'reviewStatus': 'UNDER_REVIEW',
    'programName': 'Program name',
    'programLogo': {
      'sourceUri': {
        'uri': 'http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg',
      },
      'contentDescription': {
        'defaultValue': {
          'language': 'en-US',
          'value': 'Logo description',
        },
      },
    },
  };

  // See link below for more information on required properties
  // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject
  let loyaltyObject = {
    'id': `${objectId}`,
    'classId': `${issuerId}.${classSuffix}`,
    'state': 'ACTIVE',
    'heroImage': {
      'sourceUri': {
        'uri': 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg',
      },
      'contentDescription': {
        'defaultValue': {
          'language': 'en-US',
          'value': 'Hero image description',
        },
      },
    },
    'textModulesData': [
      {
        'header': 'Text module header',
        'body': 'Text module body',
        'id': 'TEXT_MODULE_ID',
      },
    ],
    'linksModuleData': {
      'uris': [
        {
          'uri': 'http://maps.google.com/',
          'description': 'Link module URI description',
          'id': 'LINK_MODULE_URI_ID',
        },
        {
          'uri': 'tel:6505555555',
          'description': 'Link module tel description',
          'id': 'LINK_MODULE_TEL_ID',
        },
      ],
    },
    'imageModulesData': [
      {
        'mainImage': {
          'sourceUri': {
            'uri': 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg',
          },
          'contentDescription': {
            'defaultValue': {
              'language': 'en-US',
              'value': 'Image module description',
            },
          },
        },
        'id': 'IMAGE_MODULE_ID',
      },
    ],
    'barcode': {
      'type': 'QR_CODE',
      'value': 'QR code',
    },
    'locations': [
      {
        'latitude': 37.424015499999996,
        'longitude': -122.09259560000001,
      },
    ],
    'accountId': 'Account id',
    'accountName': 'Account name',
    'loyaltyPoints': {
      'label': 'Points',
      'balance': {
        'int': 800,
      },
    },
  };

  // Create the JWT claims
  let claims = {
    iss: this.credentials.client_email,
    aud: 'google',
    origins: ['www.example.com'],
    typ: 'savetowallet',
    payload: {
      // The listed classes and objects will be created
      loyaltyClasses: [loyaltyClass,],
      loyaltyObjects: [loyaltyObject,],
    },
  };

  // The service account credentials are used to sign the JWT
  let token = jwt.sign(claims, this.credentials.private_key, { algorithm: 'RS256' });

  console.log('Add to Google Wallet link');
  console.log(`https://pay.google.com/gp/v/save/${token}`);

  return `https://pay.google.com/gp/v/save/${token}`;
}

署名付き JWT を取得したら、この情報を使用して [Google ウォレットに追加] リンクを作成できます。

[Google ウォレットに追加] リンクの形式は次のとおりです。

https://pay.google.com/gp/v/save/{token}

このリンクは、ハイパーリンクとしてウェブページまたはメールに埋め込むことができます。チャットや SMS などの他のチャネルを使用して、お客様に送信することもできます。

エンコードされた JWT の安全な長さは 1,800 文字までです。JWT がこの制限を下回っている場合、オブジェクト全体を署名付き JWT に含めることができます。この制限を超えないようにしてください。1, 800 文字を超えると、ウェブブラウザによる切り捨てが発生し、「Google ウォレットに追加」機能が動作しないことがあります。

[Google ウォレットに追加] ボタン

ウェブページ、メール、Android アプリで Google ウォレット ボタンのアセットを使用すると、最適な結果が得られます。

Google ウォレット ボタンは次の 2 つの方法でレンダリングできます。

  • ウェブサイト用の JavaScript ウェブボタン
  • メール、SMS、アプリ、ウェブサイトのボタンがある JWT リンク。

次のステップ

  • ポイントカードのユースケースを評価し、ビジネスニーズに合わせて任意のものを実装する
  • ブランド ガイドラインに沿ってポイントカードの外観をカスタマイズする
  • ご不明な点がありましたら、よくある質問をご確認ください。