Save to Google Pay

All Pass verticals have common use cases. For example, all loyalty cards, gift cards, offers, event tickets, boarding passes for flights, and transit passes can be added to the Google Pay App in the following ways:

Add a web button

Add the Save to Google Pay button to your website to allow users to save any loyalty cards, gift cards, offers, event tickets, boarding passes for flights, and transit passes to the Google Pay app.

When a user clicks the button, a JSON Web Token (JWT) that represents their Pass is sent to Google servers. Google servers then create the respective Object resource based on the JWT and connects it to the user's account.

There are three steps to integrating the Save to Google Pay button on your website:

  1. Define a Class that your objects extend.
  2. Generate a JWT that represents the Object.
  3. Add the Save to Google Pay button to your webpage.

The following steps use the Loyalty Pass, but the same process is used for all Passes.

1. Define a class that your objects extend

First, define the LoyaltyClass. To insert the LoyaltyClass, make a POST request to the following REST URI:

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

To enable strict error parsing and catch additional errors such as duplicate ID fields, add the parameter strict=true to the REST URI, as shown in the following example URI:

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

The following example shows a JSON resource that represents a LoyaltyClass. The JSON must be sent in the body of the POST request. Specifically, the following code samples demonstrate how to define and insert the LoyaltyClass.

Resource

{
  "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 Uri().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<WalletObjectMessage> messages = new ArrayList<WalletObjectMessage>();
WalletObjectMessage message = new WalletObjectMessage()
    .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 Uri()
            .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_Uri();
$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_Uri();
$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()

For a complete list of all LoyaltyClass fields, see the LoyaltyClass reference.

2. Generate a JWT that represents the object

First, define the LoyaltyObject as shown in the following snippets:

Resource

    {
  "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<WalletObjectMessage> messages = new ArrayList<WalletObjectMessage>();
WalletObjectMessage message = new WalletObjectMessage()
    .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'
}

Encode the LoyaltyObject into a JWT using your OAuth 2.0 service account private key. The following snippets show how to encode a JWT in various languages. The protocol tab shows an unencoded JWT. For an explanation of the fields in the JWT, see the Google Pay API for Passes JWT.

Protocol


{
  "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)

The safe length of an encoded JWT is 1800 characters. Your JWTs should remain below this limit. If the length is over 1800 characters, the save may not work due to truncation by web browsers. Objects encoded in JWTs should be small, containing only data that is specific to the user. Try to keep most data in the object's class, creating it before making the JWT. For larger objects that don't fit the limit, consider creating the object using the REST API and sending only the object ID in the JWT.

3. Add the Save to Google Pay button

Include the following script on the page where you want to display the Save to Google Pay button:

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

Next, insert the g:savetoandroidpay namespace tag that defines the placement and attributes of the Save to Google Pay button. Include the previously-generated JWT.

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

Now you should see the Save to Google Pay button on your web page.

For more details about the JavaScript web button, see the Google Pay API for Passes for Web API reference documentation.

To save your Pass to Google Pay using an email, include a button in the email with the deep link.

There are three steps to integrating the Save to Google Pay button in an email or SMS:

  1. Define a Class that your objects extend.
  2. Generate a JWT that represents the Object.
  3. Add the Save to Google Pay button to your email or SMS.

The following steps use the Loyalty Pass, but the same process is used for all Passes.

1. Define a class that your objects extend

First, define the LoyaltyClass. To insert the LoyaltyClass, make a POST request to the following REST URI:

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

To enable strict error parsing and catch additional errors such as duplicate ID fields, add the parameter strict=true to the REST URI, as shown in the following example URI:

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

The following example shows a JSON resource that represents a LoyaltyClass. The JSON must be sent in the body of the POST request. Specifically, the following code samples demonstrate how to define and insert the LoyaltyClass.

Resource

{
  "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 Uri().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<WalletObjectMessage> messages = new ArrayList<WalletObjectMessage>();
WalletObjectMessage message = new WalletObjectMessage()
    .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 Uri()
            .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_Uri();
$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_Uri();
$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()

For a complete list of all LoyaltyClass fields, see the LoyaltyClass reference.

2. Generate a JWT that represents the object

First, define the LoyaltyObject as shown in the following snippets:

Resource

    {
  "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<WalletObjectMessage> messages = new ArrayList<WalletObjectMessage>();
WalletObjectMessage message = new WalletObjectMessage()
    .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'
}

Encode the LoyaltyObject into a JWT using your OAuth 2.0 service account private key. The following snippets show how to encode a JWT in various languages. The protocol tab shows an unencoded JWT. For an explanation of the fields in the JWT, see the Google Pay API for Passes JWT.

Protocol


{
  "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)

The safe length of an encoded JWT is 1800 characters. Your JWTs should remain below this limit. If the length is over 1800 characters, the save may not work due to truncation by web browsers. Objects encoded in JWTs should be small, containing only data that is specific to the user. Try to keep most data in the object's class, creating it before making the JWT. For larger objects that don't fit the limit, consider creating the object using the REST API and sending only the object ID in the JWT.

Fill in your generated JWT and class ID:

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

Make sure to include the trailing slash in the URL before the parameters.

The safe length of a deep link URL is 1800 characters. Your deep links should remain below this limit. If the length is over 1800 characters, the save may not work due to truncation by web browsers. Objects encoded in JWTs should be small, containing only data that is specific to the user. Try to keep most data in the object's class, creating it before making the JWT. For larger objects that don't fit the limit, consider creating the object using the REST API and sending only the object ID in the JWT.

See the Brand guidelines to download and correctly place the Save to Google Pay button image with your link. For more information on deep links and Save to Google Pay, watch the Introduction to Save to Android Pay Deep Links.

Gmail allows top-level buttons to be placed in the subject line of emails using Go-To Actions. For example, you may want to include a button labeled "Save to Google Pay" which will appear in the subject line of your email and allow the user to save their offer directly from their inbox. To enable this, include a View Action in your email with the above deep link.

From a native Android app

You can use the following methods to add the Save to Google Pay button to your native Android app:

Use the following steps to save your Pass to Google Pay from your app:

  1. Complete the steps in Add a link to an email or SMS.
  2. Use an ACTION_VIEW intent to open the deep link from the Save to Google Pay button.

    Make sure that the button that triggers the intent uses the Brand guidelines.

The following is an example flow summary:

  1. At some time before a Pass is saved, a class is created on the backend with the REST API.
  2. When the end user asks to saves a pass, your server backend sends a JWT to your Android client app that represents an object.
  3. Your Android client app includes a Save to Google Pay button that follows our brand guidelines. When clicked, it opens an ACTION_VIEW intent to a URI that includes the JWT in its path. Here's an example:
    https://pay.google.com/gp/v/save/{jwt_generated}
    

Use the native Android SDK

The Android API facilitates saving Pass in Google Pay. By integrating the Save to Google Pay button in your app, you make it easy for your customers to save their Pass to Google Pay.

The following steps outline how to add the Save to Google Pay button for the Loyalty Pass.

1. Add the Save to Google Pay button to your UI

The first step is to add the Save to Google Pay button to your app. Google Pay provides an Android SDK button for you to integrate into your app. The button assets are available in the Brand guidelines.

This toolkit contains vector images of the buttons.

To incorporate a button in your application, copy over the button image from the toolkit into the res folder of your application and add the following code to your Android layout file. Note that each button requires its unique contentDescription string and minWidth value in addition to the correct value for src.

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

The layout_height for the button is 48 dp and minWidth must be 200 dp.

2. Create a loyalty class

A class can be created from the Google Pay API for Passes Merchant Center. From the Classes page in the Merchant Center, select Create Class to create the loyaltyclass. Input fields with a red outline are required, while the remaining are optional. For any fields with a URL, make sure the link is publicly accessible. The created class will be referenced when creating the valuable object.

3. Create a loyalty object

The next step is to create the loyalty object. Following is an example of creating a loyalty object using the builder pattern:

// 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();

This object is the first parameter taken by the createWalletObject call described in the next section.

4. Initialize the Request to save the loyalty object

The class walletObjectsClient serves as the entry point for Wallet objects functionality.

The following code snippet illustrates how an app can instantiate a client for saving an object to 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);

You can also use the GoogleApiClient to initialize a request:

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

5. Handle onActivityResult

Define onActivityResult to react to the success, cancellation, or failure of the operation as shown:

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;
      }

Visszajelzés küldése a következővel kapcsolatban: