將票證儲存至 Google Pay

各票證類別皆有常見應用實例。舉例來說,您可以透過下列方式將所有會員卡、儲值卡、優惠、活動票券、登機證和大眾運輸票證新增至 Google Pay 應用程式:

新增網站按鈕

將 [儲存至 Google Pay] 按鈕新增至您的網站,讓使用者能夠將任何會員卡、儲值卡、優惠、活動票券、登機證和大眾運輸票證儲存至 Google Pay 應用程式。

使用者只要按一下按鈕,系統就會將代表使用者票證的 JSON Web Token (JWT) 傳送至 Google 伺服器。Google 伺服器便會根據 JWT 建立對應的 Object 資源,並將該資源連結至使用者的帳戶。

以下是將 [儲存至 Google Pay] 按鈕整合至網站的三個步驟:

  1. 定義物件要擴充的 Class
  2. 產生一個代表 Object 的 JWT。
  3. 將 [儲存至 Google Pay] 按鈕新增至你的網頁。

下列步驟以會員票證為例,但所有票證皆適用相同的程序。

1. 定義物件要擴充的類別

首先,請定義 LoyaltyClass。如要插入 LoyaltyClass,請發送 POST 要求至下列 REST URI:

https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass

如果要啟用嚴格錯誤剖析,並找出如 ID 欄位重複等其他錯誤,請依照下列範例 URI 所示,將 strict=true 參數新增至 REST URI:

https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass?strict=true

下列範例顯示代表 LoyaltyClass 的 JSON 資源。JSON 必須在 POST 要求的內容中傳送。下列程式碼範例具體示範如何定義和插入 LoyaltyClass

資源

{
  "accountIdLabel": "Member Id",
  "accountNameLabel": "Member Name",
  "id": "2945482443380251551.ExampleClass1",
  "issuerName": "Baconrista",
  "kind": "walletobjects#loyaltyClass",
  "textModulesData": [
    {
      "header": "Rewards details",
      "body": "Welcome to Baconrista rewards.  Enjoy your rewards for being a loyal customer. " +
               "10 points for every dollar spent.  Redeem your points for free coffee, bacon and more!"
    }
  ],
  "linksModuleData": {
    "uris": [
      {
        "kind": "walletobjects#uri",
        "uri": "https://maps.google.com/map?q=google",
        "description": "Nearby Locations"
      },
      {
        "kind": "walletobjects#uri",
        "uri": "tel:6505555555",
        "description": "Call Customer Service"
      }
    ]
  },
  "imageModulesData": [
    {
      "mainImage": {
        "kind": "walletobjects#image",
        "sourceUri": {
          "kind": "walletobjects#uri",
          "uri": "https://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg",
          "description": "Coffee beans"
        }
      }
    }
  ],
  "messages": [{
    "header": "Welcome to Banconrista Rewards!",
    "body": "Featuring our new bacon donuts.",
    "kind": "walletobjects#walletObjectMessage"
  }],
  "locations": [{
    "kind": "walletobjects#latLongPoint",
    "latitude": 37.424015499999996,
    "longitude": -122.09259560000001
    },{
    "kind": "walletobjects#latLongPoint",
    "latitude": 37.424354,
    "longitude": -122.09508869999999
    },{
    "kind": "walletobjects#latLongPoint",
    "latitude": 37.7901435,
    "longitude": -122.39026709999997
    },{
    "kind": "walletobjects#latLongPoint",
    "latitude": 40.7406578,
    "longitude": -74.00208940000002
  }],
  "programLogo": {
    "kind": "walletobjects#image",
    "sourceUri": {
      "kind": "walletobjects#uri",
      "uri": "https://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg"
    }
  },
  "programName": "Baconrista Rewards",
  "rewardsTier": "Gold",
  "rewardsTierLabel": "Tier",
  "reviewStatus": "underReview",
  "hexBackgroundColor": "#ffffff",
  "heroImage": {
   "kind": "walletobjects#image",
   "sourceUri": {
     "kind": "walletobjects#uri",
     "uri": "https://farm8.staticflickr.com/7302/11177240353_115daa5729_o.jpg"
   }
  }
}

Java

// Define the Image Module Data
List<ImageModuleData> imageModuleData = new ArrayList<ImageModuleData>();

ImageModuleData image = new ImageModuleData().setMainImage(
    new Image().setSourceUri(
        new ImageUri().setUri("http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg")));

imageModuleData.add(image);

// Define Text Module Data
List<TextModuleData> textModulesData = new ArrayList<TextModuleData>();

TextModuleData textModuleData = new TextModuleData().setHeader("Rewards details")
    .setBody(
        "Welcome to Baconrista rewards.  Enjoy your rewards for being a loyal customer.  10 points for ever dollar spent.  Redeem your points for free coffee, bacon and more!");
textModulesData.add(textModuleData);

// Define Links Module Data
List<Uri> uris = new ArrayList<Uri>();
Uri uri1 = new Uri().setDescription("Nearby Locations").setUri("http://maps.google.com/?q=google");
Uri uri2 = new Uri().setDescription("Call Customer Service").setUri("tel:6505555555");

uris.add(uri1);
uris.add(uri2);

LinksModuleData linksModuleData = new LinksModuleData().setUris(uris);

// Define general messages
List<Message> messages = new ArrayList<Message>();
Message message = new Message()
    .setHeader("Welcome to Baconrista")
    .setBody("Featuring our new bacon donuts.");
messages.add(message);

// Define Geofence locations
List<LatLongPoint> locations = new ArrayList<LatLongPoint>();
locations.add(new LatLongPoint().setLatitude(37.422601).setLongitude(
    -122.085286));
locations.add(new LatLongPoint().setLatitude(37.424354).setLongitude(
    -122.09508869999999));
locations.add(new LatLongPoint().setLatitude(40.7406578).setLongitude(
    -74.00208940000002));

// Create class
LoyaltyClass wobClass = new LoyaltyClass()
    .setId('2945482443380251551.ExampleClass1')
    .setIssuerName("Baconrista")
    .setProgramName("Baconrista Rewards")
    .setProgramLogo(
        new Image().setSourceUri(new ImageUri()
            .setUri("http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg")))
    .setRewardsTierLabel("Tier").setRewardsTier("Gold")
    .setImageModulesData(imageModuleData)
    .setTextModulesData(textModulesData)
    .setLinksModuleData(linksModuleData)
    .setAccountNameLabel("Member Name").setAccountIdLabel("Member Id")
    .setMessages(messages)
    .setReviewStatus("underReview").setMultipleDevicesAndHoldersAllowedStatus("multipleHolders")
    .setLocations(locations);

LoyaltyClass response = client.loyaltyclass().insert(wobClass).execute();

PHP

// Define text module data.
$textModulesData = array(
    array(
        'header' => 'Rewards details',
        'body' => 'Welcome to Baconrista rewards.  Enjoy your rewards for being a loyal customer. ' .
            '10 points for every dollar spent.  Redeem your points for free coffee, bacon and more!'
    )
);
// Define links module data.
$linksModuleData = new Google_Service_Walletobjects_LinksModuleData();
$uris = array (
    array(
        'uri' => 'http://maps.google.com/map?q=google',
        'kind' => 'walletobjecs#uri',
        'description' => 'Nearby Locations'
    ),
    array(
        'uri' => 'tel:6505555555',
        'kind' => 'walletobjecs#uri',
        'description' => 'Call Customer Service'
    )
);
$linksModuleData->setUris($uris);

$uriModuleImageInstance = new Google_Service_Walletobjects_ImageUri();
$uriModuleImageInstance->setUri(
    'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg'
);
$uriModuleImageInstance->setDescription('Coffee beans');
$imageModuleImageInstance = new Google_Service_Walletobjects_Image();
$imageModuleImageInstance->setSourceUri($uriModuleImageInstance);
$imagesModuleData = new Google_Service_Walletobjects_ImageModuleData();
$imagesModuleData->setMainImage($imageModuleImageInstance);
$imagesModuleDataArr = array ($imagesModuleData);

// Messages to be displayed to all users of Wallet Objects.
$messages = array(array(
    'header' => 'Welcome to Banconrista Rewards!',
    'body' => 'Featuring our new bacon donuts.',
    'kind' => 'walletobjects#walletObjectMessage'
));
$locations = array(
    array(
        'kind' => 'walletobjects#latLongPoint',
        'latitude' => 37.424015499999996,
        'longitude' => -122.09259560000001
    ),
    array(
        'kind' => 'walletobjects#latLongPoint',
        'latitude' => 37.424354,
        'longitude' => -122.09508869999999
    ),
    array(
        'kind' => 'walletobjects#latLongPoint',
        'latitude' => 37.7901435,
        'longitude' => -122.39026709999997
    ),
    array(
        'kind' => 'walletobjects#latLongPoint',
        'latitude' => 40.7406578,
        'longitude' => -74.00208940000002
    )
);
// Source uri of program logo.
$uriInstance = new Google_Service_Walletobjects_ImageUri();
$imageInstance = new Google_Service_Walletobjects_Image();
$uriInstance->setUri(
    'http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg'
);
$imageInstance->setSourceUri($uriInstance);
// Create wallet class.
$wobClass = new Google_Service_Walletobjects_LoyaltyClass();
$wobClass->setId('2945482443380251551.ExampleClass1');
$wobClass->setIssuerName('Baconrista');
$wobClass->setProgramName('Baconrista Rewards');
$wobClass->setProgramLogo($imageInstance);
$wobClass->setRewardsTierLabel('Tier');
$wobClass->setRewardsTier('Gold');
$wobClass->setAccountNameLabel('Member Name');
$wobClass->setAccountIdLabel('Member Id');
$wobClass->setLinksModuleData($linksModuleData);
$wobClass->setTextModulesData($textModulesData);
$wobClass->setImageModulesData($imagesModuleDataArr);
$wobClass->setMessages($messages);
$wobClass->setReviewStatus('underReview');
$wobClass->setMultipleDevicesAndHoldersAllowedStatus('multipleHolders');
$wobClass->setLocations($locations);

$service->loyaltyclass->insert($wobClass);

Python

loyalty_class = {
  'accountIdLabel': 'Member Id',
  'accountNameLabel': 'Member Name',
  'multipleDevicesAndHoldersAllowedStatus': 'multipleHolders',
  'id': '2945482443380251551.ExampleClass1',
  'issuerName': 'Baconrista',
  'kind': 'walletobjects#loyaltyClass',
  'locations': [{
      'kind': 'walletobjects#latLongPoint',
      'latitude': 37.424015499999996,
      'longitude': -122.09259560000001
      },{
      'kind': 'walletobjects#latLongPoint',
      'latitude': 37.424354,
      'longitude': -122.09508869999999
      },{
      'kind': 'walletobjects#latLongPoint',
      'latitude': 37.7901435,
      'longitude': -122.39026709999997
      },{
      'kind': 'walletobjects#latLongPoint',
      'latitude': 40.7406578,
      'longitude': -74.00208940000002
  }],
  'textModulesData': [{
    'header': 'Rewards details',
    'body': 'Welcome to Baconrista rewards.  Enjoy your rewards for being a loyal customer. ' +
            '10 points for ever dollar spent.  Redeem your points for free coffee, bacon and more! '
  }],
  'linksModuleData': {
    'uris': [
      {
        'kind': 'walletobjects#uri',
        'uri': 'http://maps.google.com/map?q=google',
        'description': 'Nearby Locations'
      },{
        'kind': 'walletobjects#uri',
        'uri': 'tel:6505555555',
        'description': 'Call Customer Service'
      }]
  },
  'imageModulesData': [
    {
      'mainImage': {
        'kind': 'walletobjects#image',
        'sourceUri': {
          'kind': 'walletobjects#uri',
          'uri':  'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg',
          'description': 'Coffee beans'
        }
      }
    }
  ],
  'messages': [{
      'header': 'Welcome to Banconrista Rewards!',
      'body': 'Featuring our new bacon donuts.',
      'kind': 'walletobjects#walletObjectMessage'
  }],
  'programLogo': {
      'kind': 'walletobjects#image',
      'sourceUri': {
          'kind': 'walletobjects#uri',
          'uri': 'http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg'
      }
  },
  'programName': 'Baconrista Rewards',
  'rewardsTier': 'Gold',
  'rewardsTierLabel': 'Tier',
  'reviewStatus': 'underReview',
}

api_request = service.loyaltyclass().insert(body=loyalty_class)
api_response = api_request.execute()

如需所有 LoyaltyClass 欄位的完整清單,請參閱 LoyaltyClass 參考資料

2. 產生一個代表物件的 JWT

首先,按照下列程式碼片段所示定義 LoyaltyObject

資源

{
  "classId": "2945482443380251551.ExampleClass1",
  "id": "2945482443380251551.ExampleObject1",
  "accountId": "1234567890",
  "accountName": "Jane Doe",
  "barcode": {
    "alternateText": "12345",
    "type": "qrCode",
    "value": "28343E3"
  },
  "textModulesData": [{
    "header": "Jane's Baconrista Rewards",
    "body": "Save more at your local Mountain View store Jane. " +
              "You get 1 bacon fat latte for every 5 coffees purchased.  " +
              "Also just for you, 10% off all pastries in the Mountain View store."
  }],
  "linksModuleData": {
    "uris": [
      {
        "kind": "walletobjects#uri",
        "uri": "https://www.baconrista.com/myaccount?id=1234567890",
        "description": "My Baconrista Account"
      }]
  },
  "infoModuleData": {
    "labelValueRows": [{
      "columns": [{
        "label": "Next Reward in",
        "value": "2 coffees"
      }, {
        "label": "Member Since",
        "value": "01/15/2013"
      }]
    }, {
      "columns": [{
        "label": "Local Store",
        "value": "Mountain View"
      }]
    }],
    "showLastUpdateTime": "true"
  },
  "loyaltyPoints": {
    "balance": {
      "string": "5000"
    },
    "label": "Points",
      "pointsType": "points"
  },
  "messages": [{
    "header": "Jane, welcome to Banconrista Rewards!",
    "body": "Thanks for joining our program. Show this message to " +
              "our barista for your first free coffee on us!"
  }],
  "state": "active"
}

Java

// Define Barcode
Barcode barcode = new Barcode().setType("qrCode")
    .setValue("28343E3")
    .setAlternateText("12345");

// Define Points
LoyaltyPoints points = new LoyaltyPoints()
    .setLabel("Points")
    .setPointsType("points")
    .setBalance(new LoyaltyPointsBalance().setString("500"));

// Define Text Module Data
List<TextModuleData> textModulesData = new ArrayList<TextModuleData>();
TextModuleData textModuleData = new TextModuleData()
    .setHeader("Jane's Baconrista Rewards")
    .setBody(
        "Save more at your local Mountain View store Jane.  You get 1 bacon fat latte for every 5 coffees purchased.  Also just for you, 10% off all pastries in the Mountain View store.");
textModulesData.add(textModuleData);

// Define Links Module Data
List<Uri> uris = new ArrayList<Uri>();
Uri uri1 = new Uri().setDescription("My Baconrista Account")
    .setUri("http://www.baconrista.com/myaccount?id=1234567890");
uris.add(uri1);
LinksModuleData linksModuleData = new LinksModuleData().setUris(uris);

// Define Info Module
List<LabelValue> row0cols = new ArrayList<LabelValue>();
LabelValue row0col0 = new LabelValue().setLabel("Next Reward in")
    .setValue("2 coffees");
LabelValue row0col1 = new LabelValue().setLabel("Member Since")
    .setValue("01/15/2013");
row0cols.add(row0col0);
row0cols.add(row0col1);

List<LabelValue> row1cols = new ArrayList<LabelValue>();
LabelValue row1col0 = new LabelValue().setLabel("Local Store")
    .setValue("Mountain View");
row1cols.add(row1col0);

List<LabelValueRow> rows = new ArrayList<LabelValueRow>();
LabelValueRow row0 = new LabelValueRow().setColumns(row0cols);
LabelValueRow row1 = new LabelValueRow().setColumns(row1cols);

rows.add(row0);
rows.add(row1);

InfoModuleData infoModuleData = new InfoModuleData()
    .setShowLastUpdateTime(true)
    .setLabelValueRows(rows);

// Define general messages
List<Message> messages = new ArrayList<Message>();
Message message = new Message()
    .setHeader("Hi Jane!")
    .setBody("Thanks for joining our program. Show this message to " +
        "our barista for your first free coffee on us!");
messages.add(message);

// Define Wallet Instance
LoyaltyObject object = new LoyaltyObject()
    .setClassId('2945482443380251551.ExampleClass1').setId('2945482443380251551.ExampleObject1')
    .setState("active").setBarcode(barcode).setInfoModuleData(infoModuleData)
    .setAccountName("Jane Doe").setTextModulesData(textModulesData)
    .setMessages(messages).setLinksModuleData(linksModuleData)
    .setAccountId("1234567890").setLoyaltyPoints(points);

PHP

$barcode = new Google_Service_Walletobjects_Barcode();
$barcode->setAlternateText('12345');
$barcode->setType('qrCode');
$barcode->setValue('28343E3');
// Define text module data.
$textModulesData = array(
    array(
        'header' => 'Janes Baconrista Rewards',
        'body' => 'Save more at your local Mountain View store Jane. ' .
                  'You get 1 bacon fat latte for every 5 coffees purchased. ' .
                  'Also just for you, 10% off all pastries in the Mountain View store.'
    )
);
// Define links module data.
$linksModuleData = new Google_Service_Walletobjects_LinksModuleData();
$uris = array (
    array(
        'uri' => 'http://www.baconrista.com/myaccount?id=1234567890',
        'kind' => 'walletobjecs#uri',
        'description' => 'My Baconrista Account'
    )
);
$linksModuleData->setUris($uris);
// Define label values.
$labelValueRows = array(
    array(
        'columns' => array(
            array(
                'label' => 'Next Reward in',
                'value' => '2 coffees'
            ), array(
                'label' => 'Member Since',
                'value' => '01/15/2013'
            )
        )
    ),
    array(
        'columns' => array(
            array(
                'label' => 'Local Store',
                'value' => 'Mountain View'
            )
        )
    )
);
// Define info module data.
$infoModuleData = new Google_Service_Walletobjects_InfoModuleData();
$infoModuleData->setShowLastUpdateTime(true);
$infoModuleData->setLabelValueRows($labelValueRows);
// Messages to be displayed.
$messages = array(array(
    'header' => 'Jane, welcome to Banconrista Rewards!',
    'body' => 'Thanks for joining our program. Show this message to '.
              'our barista for your first free coffee on us!',
    'kind' => 'walletobjects#walletObjectMessage'
));
// Reward points a user has.
$points = new Google_Service_Walletobjects_LoyaltyPoints();
$balance = new Google_Service_Walletobjects_LoyaltyPointsBalance();
$balance->setString('500');
$points->setBalance($balance);
$points->setLabel('Points');
$points->setPointsType('points');
// Create wallet object.
$wobObject = new Google_Service_Walletobjects_LoyaltyObject();
$wobObject->setClassId('2945482443380251551.ExampleClass1');
$wobObject->setId('2945482443380251551.ExampleObject1');
$wobObject->setState('active');
$wobObject->setBarcode($barcode);
$wobObject->setInfoModuleData($infoModuleData);
$wobObject->setLinksModuleData($linksModuleData);
$wobObject->setTextModulesData($textModulesData);
$wobObject->setAccountName('Jane Doe');
$wobObject->setAccountId('1234567890');
$wobObject->setLoyaltyPoints($points);
$wobObject->setMessages($messages);

Python

loyalty_object = {
  'classId' : '2945482443380251551.ExampleClass1',
  'id' : '2945482443380251551.ExampleObject1',
  'accountId': '1234567890',
  'accountName': 'Jane Doe',
  'barcode': {
      'alternateText' : '12345',
      'type' : 'qrCode',
      'value' : '28343E3'
  },
  'textModulesData': [{
    'header': 'Jane\'s Baconrista Rewards',
    'body': 'Save more at your local Mountain View store Jane. ' +
            ' You get 1 bacon fat latte for every 5 coffees purchased.  ' +
            'Also just for you, 10% off all pastries in the Mountain View store.'
  }],
  'linksModuleData': {
    'uris': [
      {
        'kind': 'walletobjects#uri',
        'uri': 'http://www.baconrista.com/myaccount?id=1234567890',
        'description': 'My Baconrista Account'
      }]
  },
  'infoModuleData': {
    'labelValueRows': [{
        'columns': [{
          'label': 'Next Reward in',
          'value': '2 coffees'
        }, {
          'label': 'Member Since',
          'value': '01/15/2013'
        }]
      },{
        'columns': [{
          'label': 'Local Store',
          'value': 'Mountain View'
        }]
    }],
    'showLastUpdateTime': 'true'
  },
  'messages': [{
      'header': 'Jane, welcome to Banconrista Rewards',
      'body': 'Thanks for joining our program. Show this message to ' +
              'our barista for your first free coffee on us!',
      'kind': 'walletobjects#walletObjectMessage'
  }],
  'loyaltyPoints': {
      'balance': {
          'string': '500'
      },
      'label': 'Points',
      'pointsType': 'points'
  },
  'state': 'active'
}

使用 OAuth 2.0 服務帳戶私密金鑰,透過編碼將 LoyaltyObject 編入 JWT 中。下列程式碼片段顯示如何以各種語言將 JWT 編碼。「通訊協定」分頁顯示未編碼的 JWT。如需 JWT 中各欄位的說明,請參閱「Google Pay API for Passes JWT」。

通訊協定

{
  "iss": "example_service_account@developer.gserviceaccount.com",
  "aud": "google",
  "typ": "savetoandroidpay",
  "iat": 1368029586,
  "payload": {
    "eventTicketClasses": [{
      ... //Event ticket Class JSON
    }],
    "eventTicketObjects": [{
      ... //Event ticket Object JSON
    }],
    "flightClasses": [{
      ... //Flight Class JSON
    }],
    "flightObjects": [{
      ... //Flight Object JSON
    }],
    "giftCardClasses": [{
      ... //Gift card Class JSON
    }],
    "giftCardObjects": [{
      ... //Gift card Object JSON
    }],
    "loyaltyClasses": [{
      ... //Loyalty Class JSON
    }],
    "loyaltyObjects": [{
      ... //Loyalty Object JSON
    }],
    "offerClasses": [{
      ... //Offer Class JSON
    }],
    "offerObjects": [{
      ... //Offer Object JSON
    }],
    "transitClasses": [{
      ... //Transit Class JSON
    }],
    "transitObjects": [{
      ... //Transit Object JSON
    }]
  },
  "origins": ["http://baconrista.com", "https://baconrista.com"]
}

Java

WobCredentials credentials = null;
WobUtils utils = null;

// Instantiate the WobUtils class which contains handy functions
// Wob utils can be found in the quickstart sample
try {
  credentials = new WobCredentials(
    ServiceAccountEmailAddress,
    ServiceAccountPrivateKeyPath,
    ApplicationName,
    IssuerId);
  utils = new WobUtils(credentials);
} catch (GeneralSecurityException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}

// Add valid domains for the Save to Wallet button
List<String> origins = new ArrayList<String>();
origins.add("http://baconrista.com");
origins.add("https://baconrista.com");
origins.add(req.getScheme() + "://" + req.getServerName() + ":" + req.getLocalPort());

//Generate Objects and Classes here
//........

WobPayload payload = new WobPayload();
payload.addObject({WalletObject/WalletClass});

// Convert the object into a Save to Android Pay Jwt
String jwt = null;
try {
  jwt = utils.generateSaveJwt(payload, origins);
} catch (SignatureException e) {
  e.printStackTrace();
}

PHP

$requestBody = [
  "iss"=> SERVICE_ACCOUNT_EMAIL_ADDRESS,
  "aud" => "google",
  "typ" => "savetoandroidpay",
  "iat"=> time(),
  "payload" => {
    "eventTicketClasses" => [ ], # Event ticket classes
    "eventTicketObjects" => [ ], # Event ticket objects
    "flightClasses" => [ ],      # Flight classes
    "flightObjects" => [ ],      # Flight objects
    "giftCardClasses" => [ ],    # Gift card classes
    "giftCardObjects" => [ ],    # Gift card objects
    "loyaltyClasses" => [ ],     # Loyalty classes
    "loyaltyObjects" => [ ],     # Loyalty objects
    "offerClasses" => [ ],       # Offer classes
    "offerObjects" => [ ],       # Offer objects
    "transitClasses" => [ ],     # Transit classes
    "transitObjects" => [ ]      # Transit objects
  },
  "origins" => ["http://baconrista.com", "https://baconrista.com"]
]
// Generate the Save to Android Pay Jwt
echo $jwt = $assertObj->makeSignedJwt($requestBody, $client);

Python

jwt = {
  'iss': config.SERVICE_ACCOUNT_EMAIL_ADDRESS,
  'aud': 'google',
  'typ': 'savetoandroidpay',
  'iat':  int(time.time()),
  'payload': {
    'webserviceResponse': {
      'result': 'approved',
      'message': 'Success.'
    },
    'eventTicketClasses': [], # Event ticket classes
    'eventTicketObjects': [], # Event ticket objects
    'flightClasses': [],      # Flight classes
    'flightObjects': [],      # Flight objects
    'giftCardClasses': [],    # Gift card classes
    'giftCardObjects': [],    # Gift card objects
    'loyaltyClasses': [],     # Loyalty classes
    'loyaltyObjects': [],     # Loyalty objects
    'offerClasses': [],       # Offer classes
    'offerObjects': [],       # Offer objects
    'transitClasses': [],     # Transit classes
    'transitObjects': []      # Transit objects
  },
  'origins' : ['http://baconrista.com', 'https://baconrista.com']
}

// Generate the Save to Android Pay Jwt
signer = crypt.Signer.from_string(app_key)
signed_jwt = crypt.make_signed_jwt(signer, jwt)
response = webapp2.Response(signed_jwt)

經過編碼的 JWT 長度上限為 1800 個字元。您的 JWT 不應超過此限制。如果長度超過 1800 個字元,可能會遭網路瀏覽器截斷,而導致 JWT 無法儲存。透過編碼編入 JWT 中的物件應精簡,且僅包含與使用者相關的資料。請試著將大部分資料存放在物件的類別中,並在建立 JWT 前先建立類別。對於超出限制的大型物件,請考慮使用 REST API 來建立物件,且在 JWT 中只傳送物件 ID。

3. 新增 [儲存至 Google Pay] 按鈕

在您想要放置 [儲存至 Google Pay] 按鈕的頁面上,加入下列指令碼:

<script src="https://apis.google.com/js/platform.js" type="text/javascript"></script>

接著,請插入 g:savetoandroidpay 命名空間標記,藉此定義 [儲存至 Google Pay] 按鈕的位置和屬性。加入先前產生的 JWT。

<g:savetoandroidpay jwt="{jwt_generated}" onsuccess="successHandler"
onfailure="failureHandler" size="small" theme="light" ></g:savetoandroidpay>

現在,你應該能在網頁中看見 [儲存至 Google Pay] 按鈕。

如要進一步瞭解 JavaScript 網站按鈕,請參閱 Google Pay API for Passes 的 Web API 參考資料說明文件。

如果要透過電子郵件將票證儲存至 Google Pay,請使用深層連結將按鈕加入電子郵件。

以下是將 [儲存至 Google Pay] 按鈕整合至電子郵件或簡訊的三個步驟:

  1. 定義物件要擴充的 Class
  2. 產生一個代表 Object 的 JWT
  3. 將 [儲存至 Google Pay] 按鈕新增至電子郵件或簡訊

下列步驟以會員票證為例,但所有票證皆適用相同的程序。

1. 定義物件要擴充的類別

首先,請定義 LoyaltyClass。如要插入 LoyaltyClass,請發送 POST 要求至下列 REST URI:

https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass

如果要啟用嚴格錯誤剖析,並找出如 ID 欄位重複等其他錯誤,請依照下列範例 URI 所示,將 strict=true 參數新增至 REST URI:

https://walletobjects.googleapis.com/walletobjects/v1/loyaltyClass?strict=true

下列範例顯示代表 LoyaltyClass 的 JSON 資源。JSON 必須在 POST 要求的內容中傳送。下列程式碼範例具體示範如何定義和插入 LoyaltyClass

資源

{
  "accountIdLabel": "Member Id",
  "accountNameLabel": "Member Name",
  "id": "2945482443380251551.ExampleClass1",
  "issuerName": "Baconrista",
  "kind": "walletobjects#loyaltyClass",
  "textModulesData": [
    {
      "header": "Rewards details",
      "body": "Welcome to Baconrista rewards.  Enjoy your rewards for being a loyal customer. " +
               "10 points for every dollar spent.  Redeem your points for free coffee, bacon and more!"
    }
  ],
  "linksModuleData": {
    "uris": [
      {
        "kind": "walletobjects#uri",
        "uri": "https://maps.google.com/map?q=google",
        "description": "Nearby Locations"
      },
      {
        "kind": "walletobjects#uri",
        "uri": "tel:6505555555",
        "description": "Call Customer Service"
      }
    ]
  },
  "imageModulesData": [
    {
      "mainImage": {
        "kind": "walletobjects#image",
        "sourceUri": {
          "kind": "walletobjects#uri",
          "uri": "https://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg",
          "description": "Coffee beans"
        }
      }
    }
  ],
  "messages": [{
    "header": "Welcome to Banconrista Rewards!",
    "body": "Featuring our new bacon donuts.",
    "kind": "walletobjects#walletObjectMessage"
  }],
  "locations": [{
    "kind": "walletobjects#latLongPoint",
    "latitude": 37.424015499999996,
    "longitude": -122.09259560000001
    },{
    "kind": "walletobjects#latLongPoint",
    "latitude": 37.424354,
    "longitude": -122.09508869999999
    },{
    "kind": "walletobjects#latLongPoint",
    "latitude": 37.7901435,
    "longitude": -122.39026709999997
    },{
    "kind": "walletobjects#latLongPoint",
    "latitude": 40.7406578,
    "longitude": -74.00208940000002
  }],
  "programLogo": {
    "kind": "walletobjects#image",
    "sourceUri": {
      "kind": "walletobjects#uri",
      "uri": "https://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg"
    }
  },
  "programName": "Baconrista Rewards",
  "rewardsTier": "Gold",
  "rewardsTierLabel": "Tier",
  "reviewStatus": "underReview",
  "hexBackgroundColor": "#ffffff",
  "heroImage": {
   "kind": "walletobjects#image",
   "sourceUri": {
     "kind": "walletobjects#uri",
     "uri": "https://farm8.staticflickr.com/7302/11177240353_115daa5729_o.jpg"
   }
  }
}

Java

// Define the Image Module Data
List<ImageModuleData> imageModuleData = new ArrayList<ImageModuleData>();

ImageModuleData image = new ImageModuleData().setMainImage(
    new Image().setSourceUri(
        new ImageUri().setUri("http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg")));

imageModuleData.add(image);

// Define Text Module Data
List<TextModuleData> textModulesData = new ArrayList<TextModuleData>();

TextModuleData textModuleData = new TextModuleData().setHeader("Rewards details")
    .setBody(
        "Welcome to Baconrista rewards.  Enjoy your rewards for being a loyal customer.  10 points for ever dollar spent.  Redeem your points for free coffee, bacon and more!");
textModulesData.add(textModuleData);

// Define Links Module Data
List<Uri> uris = new ArrayList<Uri>();
Uri uri1 = new Uri().setDescription("Nearby Locations").setUri("http://maps.google.com/?q=google");
Uri uri2 = new Uri().setDescription("Call Customer Service").setUri("tel:6505555555");

uris.add(uri1);
uris.add(uri2);

LinksModuleData linksModuleData = new LinksModuleData().setUris(uris);

// Define general messages
List<Message> messages = new ArrayList<Message>();
Message message = new Message()
    .setHeader("Welcome to Baconrista")
    .setBody("Featuring our new bacon donuts.");
messages.add(message);

// Define Geofence locations
List<LatLongPoint> locations = new ArrayList<LatLongPoint>();
locations.add(new LatLongPoint().setLatitude(37.422601).setLongitude(
    -122.085286));
locations.add(new LatLongPoint().setLatitude(37.424354).setLongitude(
    -122.09508869999999));
locations.add(new LatLongPoint().setLatitude(40.7406578).setLongitude(
    -74.00208940000002));

// Create class
LoyaltyClass wobClass = new LoyaltyClass()
    .setId('2945482443380251551.ExampleClass1')
    .setIssuerName("Baconrista")
    .setProgramName("Baconrista Rewards")
    .setProgramLogo(
        new Image().setSourceUri(new ImageUri()
            .setUri("http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg")))
    .setRewardsTierLabel("Tier").setRewardsTier("Gold")
    .setImageModulesData(imageModuleData)
    .setTextModulesData(textModulesData)
    .setLinksModuleData(linksModuleData)
    .setAccountNameLabel("Member Name").setAccountIdLabel("Member Id")
    .setMessages(messages)
    .setReviewStatus("underReview").setMultipleDevicesAndHoldersAllowedStatus("multipleHolders")
    .setLocations(locations);

LoyaltyClass response = client.loyaltyclass().insert(wobClass).execute();

PHP

// Define text module data.
$textModulesData = array(
    array(
        'header' => 'Rewards details',
        'body' => 'Welcome to Baconrista rewards.  Enjoy your rewards for being a loyal customer. ' .
            '10 points for every dollar spent.  Redeem your points for free coffee, bacon and more!'
    )
);
// Define links module data.
$linksModuleData = new Google_Service_Walletobjects_LinksModuleData();
$uris = array (
    array(
        'uri' => 'http://maps.google.com/map?q=google',
        'kind' => 'walletobjecs#uri',
        'description' => 'Nearby Locations'
    ),
    array(
        'uri' => 'tel:6505555555',
        'kind' => 'walletobjecs#uri',
        'description' => 'Call Customer Service'
    )
);
$linksModuleData->setUris($uris);

$uriModuleImageInstance = new Google_Service_Walletobjects_ImageUri();
$uriModuleImageInstance->setUri(
    'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg'
);
$uriModuleImageInstance->setDescription('Coffee beans');
$imageModuleImageInstance = new Google_Service_Walletobjects_Image();
$imageModuleImageInstance->setSourceUri($uriModuleImageInstance);
$imagesModuleData = new Google_Service_Walletobjects_ImageModuleData();
$imagesModuleData->setMainImage($imageModuleImageInstance);
$imagesModuleDataArr = array ($imagesModuleData);

// Messages to be displayed to all users of Wallet Objects.
$messages = array(array(
    'header' => 'Welcome to Banconrista Rewards!',
    'body' => 'Featuring our new bacon donuts.',
    'kind' => 'walletobjects#walletObjectMessage'
));
$locations = array(
    array(
        'kind' => 'walletobjects#latLongPoint',
        'latitude' => 37.424015499999996,
        'longitude' => -122.09259560000001
    ),
    array(
        'kind' => 'walletobjects#latLongPoint',
        'latitude' => 37.424354,
        'longitude' => -122.09508869999999
    ),
    array(
        'kind' => 'walletobjects#latLongPoint',
        'latitude' => 37.7901435,
        'longitude' => -122.39026709999997
    ),
    array(
        'kind' => 'walletobjects#latLongPoint',
        'latitude' => 40.7406578,
        'longitude' => -74.00208940000002
    )
);
// Source uri of program logo.
$uriInstance = new Google_Service_Walletobjects_ImageUri();
$imageInstance = new Google_Service_Walletobjects_Image();
$uriInstance->setUri(
    'http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg'
);
$imageInstance->setSourceUri($uriInstance);
// Create wallet class.
$wobClass = new Google_Service_Walletobjects_LoyaltyClass();
$wobClass->setId('2945482443380251551.ExampleClass1');
$wobClass->setIssuerName('Baconrista');
$wobClass->setProgramName('Baconrista Rewards');
$wobClass->setProgramLogo($imageInstance);
$wobClass->setRewardsTierLabel('Tier');
$wobClass->setRewardsTier('Gold');
$wobClass->setAccountNameLabel('Member Name');
$wobClass->setAccountIdLabel('Member Id');
$wobClass->setLinksModuleData($linksModuleData);
$wobClass->setTextModulesData($textModulesData);
$wobClass->setImageModulesData($imagesModuleDataArr);
$wobClass->setMessages($messages);
$wobClass->setReviewStatus('underReview');
$wobClass->setMultipleDevicesAndHoldersAllowedStatus('multipleHolders');
$wobClass->setLocations($locations);

$service->loyaltyclass->insert($wobClass);

Python

loyalty_class = {
  'accountIdLabel': 'Member Id',
  'accountNameLabel': 'Member Name',
  'multipleDevicesAndHoldersAllowedStatus': 'multipleHolders',
  'id': '2945482443380251551.ExampleClass1',
  'issuerName': 'Baconrista',
  'kind': 'walletobjects#loyaltyClass',
  'locations': [{
      'kind': 'walletobjects#latLongPoint',
      'latitude': 37.424015499999996,
      'longitude': -122.09259560000001
      },{
      'kind': 'walletobjects#latLongPoint',
      'latitude': 37.424354,
      'longitude': -122.09508869999999
      },{
      'kind': 'walletobjects#latLongPoint',
      'latitude': 37.7901435,
      'longitude': -122.39026709999997
      },{
      'kind': 'walletobjects#latLongPoint',
      'latitude': 40.7406578,
      'longitude': -74.00208940000002
  }],
  'textModulesData': [{
    'header': 'Rewards details',
    'body': 'Welcome to Baconrista rewards.  Enjoy your rewards for being a loyal customer. ' +
            '10 points for ever dollar spent.  Redeem your points for free coffee, bacon and more! '
  }],
  'linksModuleData': {
    'uris': [
      {
        'kind': 'walletobjects#uri',
        'uri': 'http://maps.google.com/map?q=google',
        'description': 'Nearby Locations'
      },{
        'kind': 'walletobjects#uri',
        'uri': 'tel:6505555555',
        'description': 'Call Customer Service'
      }]
  },
  'imageModulesData': [
    {
      'mainImage': {
        'kind': 'walletobjects#image',
        'sourceUri': {
          'kind': 'walletobjects#uri',
          'uri':  'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg',
          'description': 'Coffee beans'
        }
      }
    }
  ],
  'messages': [{
      'header': 'Welcome to Banconrista Rewards!',
      'body': 'Featuring our new bacon donuts.',
      'kind': 'walletobjects#walletObjectMessage'
  }],
  'programLogo': {
      'kind': 'walletobjects#image',
      'sourceUri': {
          'kind': 'walletobjects#uri',
          'uri': 'http://farm8.staticflickr.com/7340/11177041185_a61a7f2139_o.jpg'
      }
  },
  'programName': 'Baconrista Rewards',
  'rewardsTier': 'Gold',
  'rewardsTierLabel': 'Tier',
  'reviewStatus': 'underReview',
}

api_request = service.loyaltyclass().insert(body=loyalty_class)
api_response = api_request.execute()

如需所有 LoyaltyClass 欄位的完整清單,請參閱 LoyaltyClass 參考資料

2. 產生一個代表物件的 JWT

首先,按照下列程式碼片段所示定義 LoyaltyObject

資源

{
  "classId": "2945482443380251551.ExampleClass1",
  "id": "2945482443380251551.ExampleObject1",
  "accountId": "1234567890",
  "accountName": "Jane Doe",
  "barcode": {
    "alternateText": "12345",
    "type": "qrCode",
    "value": "28343E3"
  },
  "textModulesData": [{
    "header": "Jane's Baconrista Rewards",
    "body": "Save more at your local Mountain View store Jane. " +
              "You get 1 bacon fat latte for every 5 coffees purchased.  " +
              "Also just for you, 10% off all pastries in the Mountain View store."
  }],
  "linksModuleData": {
    "uris": [
      {
        "kind": "walletobjects#uri",
        "uri": "https://www.baconrista.com/myaccount?id=1234567890",
        "description": "My Baconrista Account"
      }]
  },
  "infoModuleData": {
    "labelValueRows": [{
      "columns": [{
        "label": "Next Reward in",
        "value": "2 coffees"
      }, {
        "label": "Member Since",
        "value": "01/15/2013"
      }]
    }, {
      "columns": [{
        "label": "Local Store",
        "value": "Mountain View"
      }]
    }],
    "showLastUpdateTime": "true"
  },
  "loyaltyPoints": {
    "balance": {
      "string": "5000"
    },
    "label": "Points",
      "pointsType": "points"
  },
  "messages": [{
    "header": "Jane, welcome to Banconrista Rewards!",
    "body": "Thanks for joining our program. Show this message to " +
              "our barista for your first free coffee on us!"
  }],
  "state": "active"
}

Java

// Define Barcode
Barcode barcode = new Barcode().setType("qrCode")
    .setValue("28343E3")
    .setAlternateText("12345");

// Define Points
LoyaltyPoints points = new LoyaltyPoints()
    .setLabel("Points")
    .setPointsType("points")
    .setBalance(new LoyaltyPointsBalance().setString("500"));

// Define Text Module Data
List<TextModuleData> textModulesData = new ArrayList<TextModuleData>();
TextModuleData textModuleData = new TextModuleData()
    .setHeader("Jane's Baconrista Rewards")
    .setBody(
        "Save more at your local Mountain View store Jane.  You get 1 bacon fat latte for every 5 coffees purchased.  Also just for you, 10% off all pastries in the Mountain View store.");
textModulesData.add(textModuleData);

// Define Links Module Data
List<Uri> uris = new ArrayList<Uri>();
Uri uri1 = new Uri().setDescription("My Baconrista Account")
    .setUri("http://www.baconrista.com/myaccount?id=1234567890");
uris.add(uri1);
LinksModuleData linksModuleData = new LinksModuleData().setUris(uris);

// Define Info Module
List<LabelValue> row0cols = new ArrayList<LabelValue>();
LabelValue row0col0 = new LabelValue().setLabel("Next Reward in")
    .setValue("2 coffees");
LabelValue row0col1 = new LabelValue().setLabel("Member Since")
    .setValue("01/15/2013");
row0cols.add(row0col0);
row0cols.add(row0col1);

List<LabelValue> row1cols = new ArrayList<LabelValue>();
LabelValue row1col0 = new LabelValue().setLabel("Local Store")
    .setValue("Mountain View");
row1cols.add(row1col0);

List<LabelValueRow> rows = new ArrayList<LabelValueRow>();
LabelValueRow row0 = new LabelValueRow().setColumns(row0cols);
LabelValueRow row1 = new LabelValueRow().setColumns(row1cols);

rows.add(row0);
rows.add(row1);

InfoModuleData infoModuleData = new InfoModuleData()
    .setShowLastUpdateTime(true)
    .setLabelValueRows(rows);

// Define general messages
List<Message> messages = new ArrayList<Message>();
Message message = new Message()
    .setHeader("Hi Jane!")
    .setBody("Thanks for joining our program. Show this message to " +
        "our barista for your first free coffee on us!");
messages.add(message);

// Define Wallet Instance
LoyaltyObject object = new LoyaltyObject()
    .setClassId('2945482443380251551.ExampleClass1').setId('2945482443380251551.ExampleObject1')
    .setState("active").setBarcode(barcode).setInfoModuleData(infoModuleData)
    .setAccountName("Jane Doe").setTextModulesData(textModulesData)
    .setMessages(messages).setLinksModuleData(linksModuleData)
    .setAccountId("1234567890").setLoyaltyPoints(points);

PHP

$barcode = new Google_Service_Walletobjects_Barcode();
$barcode->setAlternateText('12345');
$barcode->setType('qrCode');
$barcode->setValue('28343E3');
// Define text module data.
$textModulesData = array(
    array(
        'header' => 'Janes Baconrista Rewards',
        'body' => 'Save more at your local Mountain View store Jane. ' .
                  'You get 1 bacon fat latte for every 5 coffees purchased. ' .
                  'Also just for you, 10% off all pastries in the Mountain View store.'
    )
);
// Define links module data.
$linksModuleData = new Google_Service_Walletobjects_LinksModuleData();
$uris = array (
    array(
        'uri' => 'http://www.baconrista.com/myaccount?id=1234567890',
        'kind' => 'walletobjecs#uri',
        'description' => 'My Baconrista Account'
    )
);
$linksModuleData->setUris($uris);
// Define label values.
$labelValueRows = array(
    array(
        'columns' => array(
            array(
                'label' => 'Next Reward in',
                'value' => '2 coffees'
            ), array(
                'label' => 'Member Since',
                'value' => '01/15/2013'
            )
        )
    ),
    array(
        'columns' => array(
            array(
                'label' => 'Local Store',
                'value' => 'Mountain View'
            )
        )
    )
);
// Define info module data.
$infoModuleData = new Google_Service_Walletobjects_InfoModuleData();
$infoModuleData->setShowLastUpdateTime(true);
$infoModuleData->setLabelValueRows($labelValueRows);
// Messages to be displayed.
$messages = array(array(
    'header' => 'Jane, welcome to Banconrista Rewards!',
    'body' => 'Thanks for joining our program. Show this message to '.
              'our barista for your first free coffee on us!',
    'kind' => 'walletobjects#walletObjectMessage'
));
// Reward points a user has.
$points = new Google_Service_Walletobjects_LoyaltyPoints();
$balance = new Google_Service_Walletobjects_LoyaltyPointsBalance();
$balance->setString('500');
$points->setBalance($balance);
$points->setLabel('Points');
$points->setPointsType('points');
// Create wallet object.
$wobObject = new Google_Service_Walletobjects_LoyaltyObject();
$wobObject->setClassId('2945482443380251551.ExampleClass1');
$wobObject->setId('2945482443380251551.ExampleObject1');
$wobObject->setState('active');
$wobObject->setBarcode($barcode);
$wobObject->setInfoModuleData($infoModuleData);
$wobObject->setLinksModuleData($linksModuleData);
$wobObject->setTextModulesData($textModulesData);
$wobObject->setAccountName('Jane Doe');
$wobObject->setAccountId('1234567890');
$wobObject->setLoyaltyPoints($points);
$wobObject->setMessages($messages);

Python

loyalty_object = {
  'classId' : '2945482443380251551.ExampleClass1',
  'id' : '2945482443380251551.ExampleObject1',
  'accountId': '1234567890',
  'accountName': 'Jane Doe',
  'barcode': {
      'alternateText' : '12345',
      'type' : 'qrCode',
      'value' : '28343E3'
  },
  'textModulesData': [{
    'header': 'Jane\'s Baconrista Rewards',
    'body': 'Save more at your local Mountain View store Jane. ' +
            ' You get 1 bacon fat latte for every 5 coffees purchased.  ' +
            'Also just for you, 10% off all pastries in the Mountain View store.'
  }],
  'linksModuleData': {
    'uris': [
      {
        'kind': 'walletobjects#uri',
        'uri': 'http://www.baconrista.com/myaccount?id=1234567890',
        'description': 'My Baconrista Account'
      }]
  },
  'infoModuleData': {
    'labelValueRows': [{
        'columns': [{
          'label': 'Next Reward in',
          'value': '2 coffees'
        }, {
          'label': 'Member Since',
          'value': '01/15/2013'
        }]
      },{
        'columns': [{
          'label': 'Local Store',
          'value': 'Mountain View'
        }]
    }],
    'showLastUpdateTime': 'true'
  },
  'messages': [{
      'header': 'Jane, welcome to Banconrista Rewards',
      'body': 'Thanks for joining our program. Show this message to ' +
              'our barista for your first free coffee on us!',
      'kind': 'walletobjects#walletObjectMessage'
  }],
  'loyaltyPoints': {
      'balance': {
          'string': '500'
      },
      'label': 'Points',
      'pointsType': 'points'
  },
  'state': 'active'
}

使用 OAuth 2.0 服務帳戶私密金鑰,透過編碼將 LoyaltyObject 編入 JWT 中。下列程式碼片段顯示如何以各種語言將 JWT 編碼。「通訊協定」分頁顯示未編碼的 JWT。如需 JWT 中各欄位的說明,請參閱「Google Pay API for Passes JWT」。

通訊協定

{
  "iss": "example_service_account@developer.gserviceaccount.com",
  "aud": "google",
  "typ": "savetoandroidpay",
  "iat": 1368029586,
  "payload": {
    "eventTicketClasses": [{
      ... //Event ticket Class JSON
    }],
    "eventTicketObjects": [{
      ... //Event ticket Object JSON
    }],
    "flightClasses": [{
      ... //Flight Class JSON
    }],
    "flightObjects": [{
      ... //Flight Object JSON
    }],
    "giftCardClasses": [{
      ... //Gift card Class JSON
    }],
    "giftCardObjects": [{
      ... //Gift card Object JSON
    }],
    "loyaltyClasses": [{
      ... //Loyalty Class JSON
    }],
    "loyaltyObjects": [{
      ... //Loyalty Object JSON
    }],
    "offerClasses": [{
      ... //Offer Class JSON
    }],
    "offerObjects": [{
      ... //Offer Object JSON
    }],
    "transitClasses": [{
      ... //Transit Class JSON
    }],
    "transitObjects": [{
      ... //Transit Object JSON
    }]
  },
  "origins": ["http://baconrista.com", "https://baconrista.com"]
}

Java

WobCredentials credentials = null;
WobUtils utils = null;

// Instantiate the WobUtils class which contains handy functions
// Wob utils can be found in the quickstart sample
try {
  credentials = new WobCredentials(
    ServiceAccountEmailAddress,
    ServiceAccountPrivateKeyPath,
    ApplicationName,
    IssuerId);
  utils = new WobUtils(credentials);
} catch (GeneralSecurityException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}

// Add valid domains for the Save to Wallet button
List<String> origins = new ArrayList<String>();
origins.add("http://baconrista.com");
origins.add("https://baconrista.com");
origins.add(req.getScheme() + "://" + req.getServerName() + ":" + req.getLocalPort());

//Generate Objects and Classes here
//........

WobPayload payload = new WobPayload();
payload.addObject({WalletObject/WalletClass});

// Convert the object into a Save to Android Pay Jwt
String jwt = null;
try {
  jwt = utils.generateSaveJwt(payload, origins);
} catch (SignatureException e) {
  e.printStackTrace();
}

PHP

$requestBody = [
  "iss"=> SERVICE_ACCOUNT_EMAIL_ADDRESS,
  "aud" => "google",
  "typ" => "savetoandroidpay",
  "iat"=> time(),
  "payload" => {
    "eventTicketClasses" => [ ], # Event ticket classes
    "eventTicketObjects" => [ ], # Event ticket objects
    "flightClasses" => [ ],      # Flight classes
    "flightObjects" => [ ],      # Flight objects
    "giftCardClasses" => [ ],    # Gift card classes
    "giftCardObjects" => [ ],    # Gift card objects
    "loyaltyClasses" => [ ],     # Loyalty classes
    "loyaltyObjects" => [ ],     # Loyalty objects
    "offerClasses" => [ ],       # Offer classes
    "offerObjects" => [ ],       # Offer objects
    "transitClasses" => [ ],     # Transit classes
    "transitObjects" => [ ]      # Transit objects
  },
  "origins" => ["http://baconrista.com", "https://baconrista.com"]
]
// Generate the Save to Android Pay Jwt
echo $jwt = $assertObj->makeSignedJwt($requestBody, $client);

Python

jwt = {
  'iss': config.SERVICE_ACCOUNT_EMAIL_ADDRESS,
  'aud': 'google',
  'typ': 'savetoandroidpay',
  'iat':  int(time.time()),
  'payload': {
    'webserviceResponse': {
      'result': 'approved',
      'message': 'Success.'
    },
    'eventTicketClasses': [], # Event ticket classes
    'eventTicketObjects': [], # Event ticket objects
    'flightClasses': [],      # Flight classes
    'flightObjects': [],      # Flight objects
    'giftCardClasses': [],    # Gift card classes
    'giftCardObjects': [],    # Gift card objects
    'loyaltyClasses': [],     # Loyalty classes
    'loyaltyObjects': [],     # Loyalty objects
    'offerClasses': [],       # Offer classes
    'offerObjects': [],       # Offer objects
    'transitClasses': [],     # Transit classes
    'transitObjects': []      # Transit objects
  },
  'origins' : ['http://baconrista.com', 'https://baconrista.com']
}

// Generate the Save to Android Pay Jwt
signer = crypt.Signer.from_string(app_key)
signed_jwt = crypt.make_signed_jwt(signer, jwt)
response = webapp2.Response(signed_jwt)

經過編碼的 JWT 長度上限為 1800 個字元。您的 JWT 不應超過此限制。如果長度超過 1800 個字元,可能會遭網路瀏覽器截斷,而導致 JWT 無法儲存。透過編碼編入 JWT 中的物件應精簡,且僅包含與使用者相關的資料。請試著將大部分資料存放在物件的類別中,並在建立 JWT 前先建立類別。對於超出限制的大型物件,請考慮使用 REST API 來建立物件,且在 JWT 中只傳送物件 ID。

填入產生的 JWT 和類別 ID:

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

務必在網址中的參數前方加上斜線。

深層連結網址的長度上限為 1800 個字元。您的深層連結不應超過此限制。如果長度超過 1800 個字元,可能會遭網路瀏覽器截斷,而導致連結無法儲存。透過編碼編入 JWT 中的物件應精簡,且僅包含與使用者相關的資料。請試著將大部分資料存放在物件的類別中,並在建立 JWT 前先建立類別。對於超出限制的大型物件,請考慮使用 REST API 來建立物件,且在 JWT 中只傳送物件 ID。

如要下載 [儲存至 Google Pay] 按鈕圖片,以及瞭解如何正確放置按鈕圖片並加上連結,請參閱品牌規範。如要進一步瞭解深層連結與儲存至 Google Pay 功能,請觀看儲存至 Android Pay 深層連結簡介影片。

透過前往動作,您可以在 Gmail 中將頂層按鈕放置於電子郵件的主旨行。舉例來說,您可能想要加入標示為 [儲存至 Google Pay] 的按鈕,此按鈕會顯示在電子郵件的主旨行,讓使用者直接從收件匣儲存優惠。如果要啟用此功能,請使用上方深層連結在電子郵件中加入「檢視動作」。

從原生 Android 應用程式中操作

您可以使用下列方法將 [儲存至 Google Pay] 按鈕新增至原生 Android 應用程式:

利用下列步驟,從應用程式將票證儲存到 Google Pay:

  1. 完成將 [儲存至 Google Pay] 按鈕新增至電子郵件或簡訊一文所述的步驟。
  2. 使用 ACTION_VIEW 意圖,透過 [儲存至 Google Pay] 按鈕開啟深層連結。

    確認觸發意圖的按鈕符合品牌宣傳指南的規定。

以下是流程摘要的範例:

  1. 在儲存票證前的某個時間點,系統會透過 REST API 在後端建立類別。
  2. 使用者提出票證儲存要求時,你的伺服器後端會將代表物件的 JWT 傳送至你的 Android 用戶端應用程式。
  3. 你的 Android 用戶端應用程式包含符合品牌宣傳指南的 [儲存至 Google Pay] 按鈕。使用者按一下按鈕之後,系統會開啟連至 URI 的 ACTION_VIEW 意圖,其路徑中包含該組 JWT。範例如下:
    https://pay.google.com/gp/v/save/{jwt_generated}
    

使用 JWT POST 要求方法

您可以選擇透過 JWT POST 要求方法,為 Android 應用程式建立航班機票或活動票券類別與物件。如果儲存物件前,較難實作建立及插入類別所需的後端工作,這個方法就能派上用場。這個方法非常適合用於活動票券和登機證,因為這類票證會隨著時間經過建立許多類別。流程概述如下:

  1. 使用者進行航班報到或兌換活動票券時,您的伺服器後端會向 Android 用戶端應用程式顯示「同時」包含類別和物件的 JWT。
  2. 你的 Android 用戶端應用程式包含符合品牌宣傳指南的 [儲存至 Google Pay] 按鈕。按一下按鈕時,就會發生下列情況:
    1. 系統以 POST 要求透過 HTTPS 將 JWT 傳送至 Google 端點。
    2. 系統會傳回所產生之 HTTP 回應內容的 URI。接著應使用此 URI 來開啟 ACTION_VIEW 意圖。

JWT POST 要求方法還必須具備 API 金鑰。金鑰會做為查詢參數附加至 REST API 呼叫。

建立類別

只有在收到先前未曾儲存過的 class.id 時,後端才會建立新類別。因此,雖然您可能會透過 JWT 重複將類別詳細資料傳送給 Google,但後端可辨識出該類別已儲存,因此不會在每次儲存登機證時,都建立新的類別。

更新類別

使用者儲存第一張登機證之後,系統就會一併儲存物件和類別。如您所預期,您可以將 class.id 和 REST API 搭配使用,以便執行 ADDMESSAGEGETLISTPATCHUPDATE 作業。

如要變更類別詳細資料,則必須使用 Class Update API。如果您已透過 class.id=XYZ 建立類別和其他一些類別詳細資料,之後卻嘗試透過 class.id=XYZ 建立含有不同類別詳細資料的類別,則系統仍會保留原本的類別,不會套用任何變更。

JWT 格式

我們的 Google Pay API for Passess JWT 參考說明文件詳述您傳送 JWT 時,JWT 採用的格式。以這項 payload 而言,您會傳送一個物件項目 (代表您要建立的物件) 和一個類別項目 (當中包含您建立的類別)。

HTTP 要求

您可以使用 INSERT 方法插入 JWT 中指定的類別和物件,而且必須將 API 金鑰設為查詢參數。

JWT INSERT 方法

在您提供 JWT 後,INSERT 方法會在 JWT 中插入指定的類別和物件。如果插入成功,要求就會傳回 200 HTTP 回應。

HTTP 要求
POST https://walletobjects.googleapis.com/walletobjects/v1/jwt/

授權

這項要求不需經過授權,不過 JWT 必須使用 RSA-SHA256 進行簽署,簽署金鑰為 OAuth 服務帳戶產生的金鑰。

要求內容

在要求內容中,請提供具有以下結構的資料:

{ “jwt” : string }

回應內容

如果要求成功,這個方法就會在回應內容中傳回下列結構:

{
    "saveUri": string,
    "resources": {
      "eventTicketClasses": [ eventTicketClass resource, ... ],
      "eventTicketObjects": [ eventTicketObject resource, ... ],
      "flightClasses": [ flightClass resource, ... ],
      "flightObjects": [ flightObject resource, ... ],
      "giftCardClasses": [ giftCardClass resource, ... ],
      "giftCardObjects": [ giftCardObject resource, ... ],
      "loyaltyClasses": [ loyaltyClass resource, ... ],
      "loyaltyObjects": [ loyaltyObject resource, ... ],
      "offerClasses": [ offerClass resource, ... ],
      "offerObjects": [ offerObject resource, ... ],
      "transitClasses": [ transitClass resource, ... ],
      "transitObjects": [ transitObject resource, ... ]
    }
}

開啟 saveUri 這個 URI 之後,使用者即可將 JWT 中識別的物件儲存至自己的 Google 帳戶中。不過請注意,系統傳回的 URI 效期僅有一週。

詳情請參閱 JWT 端點參考資料

流程圖

如要查看流程圖,請參閱一般 API 流程一文。

使用原生 Android SDK

Android API 可協助您將票證儲存到 Google Pay。只要將 [儲存至 Google Pay] 按鈕整合至您的應用程式,您的客戶便能輕鬆地將票證儲存至 Google Pay。

下列步驟說明如何針對會員票證,新增 [儲存至 Google Pay] 按鈕。

1. 將 [儲存至 Google Pay] 按鈕新增至你的使用者介面

首先請將 [儲存至 Google Pay] 按鈕新增至你的應用程式。Google Pay 提供 Android SDK 按鈕,讓你整合至應用程式。你可在品牌宣傳指南中找到按鈕素材資源。

此工具包中有按鈕的向量圖片。

如果要在應用程式中加入按鈕,請將按鈕圖片從工具包複製到應用程式的 res 資料夾,並新增下列程式碼至您的 Android 版面配置檔案。請注意,除了正確的 src 值以外,每個按鈕都需要專屬的 contentDescription 字串和 minWidth 值。

<ImageButton
             android:layout_width="match_parent"
             android:layout_height="48dp"
             android:minWidth="200dp"
             android:clickable="true"
             android:src="@drawable/s2ap" />

按鈕的 layout_height 應為 48 dp,minWidth 則須為 200 dp。

2. 建立會員類別

您可透過 Google Pay API for Passes Merchant Center 來建立類別。在 Merchant Center 的「類別」頁面中選取 [建立類別],即可建立 loyaltyclass。具有紅色外框的輸入欄位為必填,其餘欄位則為選填。針對所有具有網址的欄位,確認連結可公開存取。建立重要物件時,系統會參考已建立的類別。

3. 建立會員物件

下一步是建立會員物件。以下是使用建構工具模式建立會員物件的範例:

// Define Points
LoyaltyPoints points = LoyaltyPoints.newBuilder()
    .setLabel("Points")
    .setType("points")
    .setBalance(LoyaltyPointsBalance.newBuilder().setString("500").build()).build();

// Define Text Module Data
List textModulesData = new ArrayList();
TextModuleData textModuleData = new TextModuleData("Jane's Baconrista Rewards", "Save more at your local Mountain View store Jane.  You get 1 bacon fat latte for every 5 coffees purchased.  Also just for you, 10% off all pastries in the Mountain View store.");
textModulesData.add(textModuleData);

// Define Links Module Data
List uris = new ArrayList();
UriData uri1 = new UriData("http://www.baconrista.com/myaccount?id=1234567890","My Baconrista Account");
uris.add(uri1);

List imageUris = new ArrayList();
UriData uri2 = new UriData("http://examplesite/images/exampleimage2.jpg", "Image Description");
imageUris.add(uri2);

// Define Info Module
List row0cols = new ArrayList();
LabelValue row0col0 = new LabelValue("Next Reward in","2 coffees");
LabelValue row0col1 = new LabelValue("Member Since", "01/15/2013");
row0cols.add(row0col0);
row0cols.add(row0col1);

List row1cols = new ArrayList();
LabelValue row1col0 = new LabelValue("Local Store", "Mountain View");
row1cols.add(row1col0);

List rows = new ArrayList();
LabelValueRow row0 = LabelValueRow.newBuilder().addColumns(row0cols).build();
LabelValueRow row1 = LabelValueRow.newBuilder().addColumns(row1cols).build();

rows.add(row0);
rows.add(row1);

// Define general messages
List messages = new ArrayList();
WalletObjectMessage message =  WalletObjectMessage.newBuilder()
    .setHeader("Hi Jane!")
    .setBody("Thanks for joining our program. Show this message to " +
        "our barista for your first free coffee on us!")
    .build();
messages.add(message);

// Define Geolocations

LatLng location = new LatLng(37.422601, -122.085286);

List locations = new ArrayList();
locations.add(location);

LoyaltyWalletObject wob = LoyaltyWalletObject
    .newBuilder()
    .setClassId("2967745143867465930.LoyaltyClass")
    .setId("2967745143867465930.LoyaltyObject")
    .setState(WalletObjectsConstants.State.ACTIVE)
    .setAccountId("1234567890")
    .setAccountName("Jane Doe")
    .setIssuerName("Baconrista")
    .setProgramName("Baconrista Rewards")
    .setBarcodeType("qrCode")
    .setBarcodeValue("28343E3")
    .setBarcodeAlternateText("12345")
    .setLoyaltyPoints(points)
    .addTextModulesData(textModulesData)
    .addLinksModuleDataUris(uris)
    .addInfoModuleDataLabelValueRows(rows)
    .addImageModuleDataMainImageUris(imageUris)
    .addMessages(messages)
    .addLocations(locations)
    .build();

此物件是下節所述的 createWalletObject 呼叫所使用的第一個參數。

4. 初始化儲存會員物件的要求

walletObjectsClient 類別會成為電子錢包物件功能的進入點。

下列程式碼片段顯示應用程式如何為用戶端建立例項,以將物件儲存至 Google Pay:

CreateWalletObjectsRequest request = new CreateWalletObjectsRequest(wob);
Wallet.WalletOptions walletOptions = new Wallet.WalletOptions.Builder()
        .setTheme(WalletConstants.THEME_LIGHT)
        .setEnvironment(WalletConstants.ENVIRONMENT_PRODUCTION)
        .build();

walletObjectsClient = Wallet.getWalletObjectsClient(this, walletOptions);
Task task = walletObjectsClient.createWalletObjects(request);
AutoResolveHelper.resolveTask(task, this, SAVE_TO_ANDROID);

您也可使用 GoogleApiClient 來初始化要求:

Wallet.WalletObjects.createWalletObjects(googleApiClient, request, SAVE_TO_ANDROID);

5. 處理 onActivityResult

定義 onActivityResult 來針對作業成功、失敗或被取消的情形做出回應,如下所示:

public void onActivityResult(int requestCode, int resultCode, Intent data){
  EditText textBox = (EditText) findViewById(R.id.s2wResponse);

  switch(requestCode){
    case SAVE_TO_ANDROID:
      switch (resultCode) {
        case Activity.RESULT_OK:
          textBox.setText("saved");
          break;
        case Activity.RESULT_CANCELED:
          textBox.setText("canceled");
          break;
        default:
          int errorCode =
              data.getIntExtra(
                  WalletConstants.EXTRA_ERROR_CODE, -1);
          textBox.setText("failed error code: " + errorCode);
          break;
      }