Google Wallet API を使用してウェブでパスを作成する

1. はじめに

概要

Google Wallet API を使用すると、ポイントカード、クーポン、ギフトカード、イベント チケット、乗車券、搭乗券など、さまざまなタイプのパスを通じてユーザーに働きかけることができます。それぞれのパスタイプ(パスクラス)には、ユースケース別のフィールドや機能が含まれており、ユーザー エクスペリエンスを向上させることができます。

ただし、すべてのユースケースに適合するとは限りません。よりカスタマイズされたエクスペリエンスを作成するには、汎用パスタイプを使用します。汎用パスタイプのユースケースの例を次に示します。

  • 駐車パス
  • 図書館カード
  • ストアドバリュー型クーポン
  • ジムの会員カード
  • 予約

汎用パスは、次の要素で表示できるユースケースで使用できます。

  • 最大 3 行の情報
  • バーコード グラフィック(省略可)
  • 詳細セクション(省略可)

会議イベントの Google ウォレット パスの例

Google Wallet API の詳細、またはウェブページに [Google ウォレットに追加] ボタンを追加する方法について詳しくは、Google ウォレットのデベロッパー向けドキュメントをご覧ください。

パスクラスとオブジェクト

Google Wallet API は、次のものを作成するメソッドを公開しています。

タイプ

説明

パスクラス

個々のパス オブジェクトのテンプレート。このクラスに属するすべてのパス オブジェクトに共通の情報が含まれています。

パス オブジェクト

ユーザー ID に固有のパスクラスのインスタンス。

この Codelab について

この Codelab では、次のタスクを行います。

  1. デモモードで新しい発行者アカウントを作成する
  2. パスを発行するためのサービス アカウントを作成する
  3. 新しい汎用パスクラスを作成する
  4. 新しいパス オブジェクトを作成する
  5. パスを保存するための [Google ウォレットに追加] ボタンを作成する
  6. ウェブページにボタンを表示する
  7. パスの保存結果を処理する

前提条件

目標

この Codelab を完了すると、次のことができるようになります。

  • Google ウォレットを使用してパス オブジェクトを作成する
  • [Google ウォレットに追加] ボタンを作成する

サポート

Codelab の途中で不明な点がある場合は、google-pay/wallet-web-codelab GitHub リポジトリに完全なソリューションが用意されていますので、そちらをご覧ください。

2. セットアップ

このステップでは、デモモードで発行者アカウントを作成します。これにより、ユーザーのウォレットに追加できるパスクラスとオブジェクトを作成できます。次に、Google Cloud プロジェクトとサービス アカウントを作成します。これらは、バックエンド サーバーと同じ方法で、パスクラスとオブジェクトをプログラムで作成するために使用されます。最後に、Google Cloud サービス アカウントに、Google ウォレット発行者アカウントのパスを管理する権限を付与します。

Google ウォレット発行者アカウントを登録する

Google ウォレットのパスを作成して配布するには、発行者アカウントが必要です。Google Pay & ウォレット コンソールを使用して登録できます。最初は、デモモードでパスを作成できます。つまり、作成したパスを追加できるのは、特定のテストユーザーのみです。テストユーザーは Google Pay &ウォレット コンソールで管理できます。

デモモードについて詳しくは、汎用パスの前提条件をご覧ください。

  1. Google Pay & ウォレット コンソール を開く
  2. 画面上の手順に沿って発行者アカウントを作成する
  3. [Google Wallet API] を選択する
  4. 利用規約とプライバシー ポリシーに同意する
  5. [発行者 ID] の値をテキスト エディタまたは別の場所にコピーする
  6. [管理] タブで [テスト アカウントを設定] を選択する
  7. この Codelab で使用するメールアドレスを追加する

Google Wallet API を有効にする

  1. Google Cloud コンソールにログインする
  2. Google Cloud プロジェクトがない場合は、ここで作成します(詳しくは、プロジェクトの作成と管理をご覧ください)
  3. プロジェクトで Google Wallet API(Google Pay for Passes API とも呼ばれます)を有効にする

サービス アカウントとサービス アカウント キーを作成する

Google Wallet API を呼び出すには、サービス アカウントとサービス アカウント キーが必要です。サービス アカウントは、Google Wallet API を呼び出す ID です。サービス アカウント キーには、アプリケーションをサービス アカウントとして識別するための秘密鍵が含まれています。この鍵は機密情報であるため、機密保持してください。

サービス アカウントを作成する

  1. Google Cloud コンソールで [サービス アカウント] を開く
  2. サービス アカウントの名前、ID、説明を入力する
  3. [作成して続行] を選択する
  4. [完了] を選択する

サービス アカウント キーを作成する

  1. サービス アカウントを選択する
  2. [] メニューを選択する
  3. [鍵を追加]、[新しい鍵を作成] を選択する
  4. [JSON] 鍵タイプを選択する
  5. [作成] を選択する

鍵ファイルをローカル ワークステーションに保存するよう求められます。保存場所を覚えておいてください。

GOOGLE_APPLICATION_CREDENTIALS 環境変数を設定する

GOOGLE_APPLICATION_CREDENTIALS 環境変数は、Google SDK がサービス アカウントとして認証し、Google Cloud プロジェクトのさまざまな API にアクセスするために使用されます。

  1. Google Cloud サービス アカウント キーのドキュメントの手順に沿って、GOOGLE_APPLICATION_CREDENTIALS 環境変数を設定する
  2. 新しいターミナル(MacOS/Linux)またはコマンドライン(Windows)セッションで環境変数が設定されていることを確認する(すでにセッションが開いている場合は、新しいセッションを開始する必要がある場合があります)
    echo $GOOGLE_APPLICATION_CREDENTIALS
    

サービス アカウントを承認する

最後に、サービス アカウントに Google ウォレットのパスを管理する権限を付与する必要があります。

  1. Google Pay & ウォレット コンソール を開く
  2. [ユーザー] を選択する
  3. [ユーザーを招待] を選択する
  4. サービス アカウントのメールアドレスを入力する(例: test-svc@myproject.iam.gserviceaccount.com
  5. [アクセスレベル] プルダウン メニューから [開発元] または [管理者] を選択する
  6. [招待] を選択する

3. サンプルの Node.js アプリを起動する

所要時間: 10:00

このステップでは、ショッピング ウェブサイトとバックエンド サーバーとして機能するサンプルの Node.js アプリケーションを実行します。

サンプル リポジトリのクローンを作成する

google-pay/wallet-web-codelab リポジトリには、Node.js ベースのサンプル プロジェクトと、パスクラスとオブジェクトのプロビジョニングに使用されるバックエンド サーバーを模倣したさまざまなスクリプト ファイルが含まれています。これらを編集して、商品の詳細画面に [Google ウォレットに追加] ボタンを追加します。

  1. リポジトリのクローンをローカル ワークステーションに作成する
    git clone https://github.com/google-pay/wallet-web-codelab.git
    

プロジェクトの依存関係をインストールする

  1. ターミナルまたはコマンドライン プロンプトで、クローン作成したリポジトリを開く
  2. web ディレクトリに移動する(この Codelab の残りの部分で変更するアプリです)
    cd web
    
  3. Node.js 依存関係をインストールする
    npm install .
    
  4. アプリを起動する
    node app.js
    
  5. http://localhost:3000 で実行されているアプリを開く

メールアドレスを入力するフィールドと [パスを作成] ボタンがあるウェブアプリの例

メールアドレスを入力して [パスを作成] を選択しても、何も起こりません。次のステップでは、新しいパスクラスとオブジェクトを作成するようにアプリを構成します。

4. 汎用パスクラスを作成する

このステップでは、パスの基本クラスを作成します。ユーザー用に新しいパスが作成されるたびに、パスクラスで定義されたプロパティが継承されます。

この Codelab で作成するパスクラスでは、汎用パスの柔軟性を活かして、ID バッジとチャレンジ ポイント トラッカーの両方として機能するオブジェクトを作成します。このクラスからパス オブジェクトを作成すると、次の図のようになります。

パスクラスは、Google Pay & ウォレット コンソールで直接作成することも、Google Wallet API を使用して作成することもできます。この Codelab では、API を使用して汎用パスクラスを作成します。これは、プライベート バックエンド サーバーがパスクラスを作成するプロセスに従っています。

  1. web/app.js ファイルを開く
  2. issuerId の値を Google Pay &ウォレット コンソールの発行者 ID に置き換える
    // TODO: Define Issuer ID
    const issuerId = 'ISSUER_ID';
    
  3. createPassClass 関数を見つける
  4. 関数内で、認証済みの HTTP クライアントを作成し、Google Wallet API を使用して新しいパスクラスを作成する
    // TODO: Create a Generic pass class
    let genericClass = {
      'id': `${classId}`,
      'classTemplateInfo': {
        'cardTemplateOverride': {
          'cardRowTemplateInfos': [
            {
              'twoItems': {
                'startItem': {
                  'firstValue': {
                    'fields': [
                      {
                        'fieldPath': "object.textModulesData['points']"
                      }
                    ]
                  }
                },
                'endItem': {
                  'firstValue': {
                    'fields': [
                      {
                        'fieldPath': "object.textModulesData['contacts']"
                      }
                    ]
                  }
                }
              }
            }
          ]
        },
        'detailsTemplateOverride': {
          'detailsItemInfos': [
            {
              'item': {
                'firstValue': {
                  'fields': [
                    {
                      'fieldPath': "class.imageModulesData['event_banner']"
                    }
                  ]
                }
              }
            },
            {
              'item': {
                'firstValue': {
                  'fields': [
                    {
                      'fieldPath': "class.textModulesData['game_overview']"
                    }
                  ]
                }
              }
            },
            {
              'item': {
                'firstValue': {
                  'fields': [
                    {
                      'fieldPath': "class.linksModuleData.uris['official_site']"
                    }
                  ]
                }
              }
            }
          ]
        }
      },
      'imageModulesData': [
        {
          'mainImage': {
            'sourceUri': {
              'uri': 'https://codelabs.developers.google.com/static/add-to-wallet-web/images/google-io-2021-card.png'
            },
            'contentDescription': {
              'defaultValue': {
                'language': 'en-US',
                'value': 'Google I/O 2022 Banner'
              }
            }
          },
          'id': 'event_banner'
        }
      ],
      'textModulesData': [
        {
          'header': 'Gather points meeting new people at Google I/O',
          'body': 'Join the game and accumulate points in this badge by meeting other attendees in the event.',
          'id': 'game_overview'
        }
      ],
      'linksModuleData': {
        'uris': [
          {
            'uri': 'https://io.google/2022/',
            'description': 'Official I/O \'22 Site',
            'id': 'official_site'
          }
        ]
      }
    };
    
    let response;
    try {
      // Check if the class exists already
      response = await httpClient.request({
        url: `${baseUrl}/genericClass/${classId}`,
        method: 'GET'
      });
    
      console.log('Class already exists');
      console.log(response);
    } catch (err) {
      if (err.response && err.response.status === 404) {
        // Class does not exist
        // Create it now
        response = await httpClient.request({
          url: `${baseUrl}/genericClass`,
          method: 'POST',
          data: genericClass
        });
    
        console.log('Class insert response');
        console.log(response);
      } else {
        // Something else went wrong
        console.log(err);
        res.send('Something went wrong...check the console logs!');
      }
    }
    

コードを実行すると、新しいパスクラスが作成され、クラス ID が出力されます。クラス ID は、発行者 ID の後にデベロッパーが定義した接尾辞が続きます。この場合、接尾辞は codelab_class に設定されます(クラス ID は 1234123412341234123.codelab_class のようになります)。出力ログには、Google Wallet API からのレスポンスも含まれます。

5. 汎用パス オブジェクトを作成する

このステップでは、Node.js アプリを構成して、以前に作成したクラスを使用して汎用パス オブジェクトを作成します。ユーザー用のパス オブジェクトを作成するには、2 つのフローがあります。

バックエンド サーバーでパス オブジェクトを作成する

この方法では、パス オブジェクトがバックエンド サーバーで作成され、署名付き JWT としてクライアント アプリに返されます。ユーザーがウォレットに追加しようとする前にオブジェクトが存在することが保証されるため、ユーザーの導入率が高い場合に最適です。

ユーザーがウォレットに追加したときにパス オブジェクトを作成する

この方法では、パス オブジェクトが定義され、バックエンド サーバーで署名付き JWT にエンコードされます。次に、JWT を参照する [Google ウォレットに追加] ボタンがクライアント アプリにレンダリングされます。ユーザーがボタンを選択すると、JWT を使用してパス オブジェクトが作成されます。パス オブジェクトが作成されても使用されないことを防ぐため、ユーザーの導入率が変動する場合や不明な場合に最適です。この Codelab では、この方法を使用します。

  1. web/app.js ファイルを開く
  2. createPassObject 関数を見つける
  3. 関数内で、ユーザー用の新しいパス オブジェクトを定義する
    // TODO: Create a new Generic pass for the user
    let objectSuffix = `${req.body.email.replace(/[^\w.-]/g, '_')}`;
    let objectId = `${issuerId}.${objectSuffix}`;
    
    let genericObject = {
      'id': `${objectId}`,
      'classId': classId,
      'genericType': 'GENERIC_TYPE_UNSPECIFIED',
      'hexBackgroundColor': '#4285f4',
      'logo': {
        'sourceUri': {
          'uri': 'https://developers.google.com/static/wallet/site-assets/images/pass-builder/pass_google_logo.jpg'
        }
      },
      'cardTitle': {
        'defaultValue': {
          'language': 'en',
          'value': 'Google I/O \'22'
        }
      },
      'subheader': {
        'defaultValue': {
          'language': 'en',
          'value': 'Attendee'
        }
      },
      'header': {
        'defaultValue': {
          'language': 'en',
          'value': 'Alex McJacobs'
        }
      },
      'barcode': {
        'type': 'QR_CODE',
        'value': `${objectId}`
      },
      'heroImage': {
        'sourceUri': {
          'uri': 'https://developers.google.com/static/wallet/site-assets/images/pass-builder/google-io-hero-demo-only.jpg'
        }
      },
      'textModulesData': [
        {
          'header': 'POINTS',
          'body': '1234',
          'id': 'points'
        },
        {
          'header': 'CONTACTS',
          'body': '20',
          'id': 'contacts'
        }
      ]
    };
    
    // TODO: Create the signed JWT and link
    res.send("Form submitted!");
    

アプリを再読み込みしてメールアドレスを入力し、フォームを送信しても、出力は表示されません。パス オブジェクトはバックエンド アプリケーションによって定義されていますが、出力は返されません。次に、パスを [Google ウォレットに追加] リンクに変換します。

6. [Google ウォレットに追加] ボタンを作成する

最後のステップでは、署名付き JWT を作成し、[Google ウォレットに追加] ボタンで使用できるリンクを返します。ユーザーがボタンを選択すると、パスをウォレットに保存するよう求められます。

  1. JWT クレームを作成し、サービス アカウントの秘密鍵を使用してエンコードし、埋め込みリンクを含む [Google ウォレットに追加] ボタンを返す
    // TODO: Create the signed JWT and link
    const claims = {
      iss: credentials.client_email,
      aud: 'google',
      origins: [],
      typ: 'savetowallet',
      payload: {
        genericObjects: [
          genericObject
        ]
      }
    };
    
    const token = jwt.sign(claims, credentials.private_key, { algorithm: 'RS256' });
    const saveUrl = `https://pay.google.com/gp/v/save/${token}`;
    
    res.send(`<a href='${saveUrl}'><img src='wallet-button.png'></a>`);
    
  2. ブラウザで実行されているアプリを再読み込みする
  3. フォームにメールアドレスを入力して [パスを作成] を選択する
  4. 表示されたら、[Google ウォレットに追加] ボタンを選択する

[Google ウォレットに追加] ボタンがアプリのフロントエンドで正常にレンダリングされる

7. 完了

汎用パス オブジェクトの例

お疲れさまでした。Google Wallet API のウェブへの統合が完了しました。

詳細

google-pay/wallet-web-codelab GitHub リポジトリで完全な統合をご覧ください。

パスを作成して製品版へのアクセスをリクエストする

本番環境で自分のパスを発行する準備が整ったら、Google Pay & ウォレット コンソールに移動して製品版へのアクセスをリクエストします。

詳しくは、ウェブ API の前提条件をご覧ください。