保存到 Google Pay

所有卡券行业都有相同的使用场景。例如,所有会员卡、礼品卡、优惠券、活动门票、登机牌和公交卡都可以通过下列方法添加到 Google Pay 应用:

在网页上添加按钮

在网站中添加保存到 Google Pay 按钮,以便用户将会员卡、礼品卡、优惠券、活动门票、登机牌和公交卡保存到 Google Pay 应用。

用户点击此按钮后,系统会向 Google 服务器发送一个代表用户卡券的 JSON 网络令牌 (JWT)。接着,Google 服务器会依据 JWT 创建相应的 Object 资源,并将它与用户的帐号相关联。

要将保存到 Google Pay 按钮集成到网站上,需要完成三个步骤:

  1. 定义对象要扩展的 Class
  2. 生成代表 Object 的 JWT。
  3. 保存到 Google Pay 按钮添加到网页中。

下列步骤以会员卡为例,但同样的过程适用于所有卡券。

1. 定义对象要扩展的类

首先,定义 LoyaltyClass。要插入 LoyaltyClass,请对以下 REST URI 发出 POST 请求:

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

要启用严格的错误解析功能并发现其他错误(例如,存在重复的 ID 字段),请按以下示例 URI 所示,将参数 strict=true 添加到 REST URI:

https://www.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 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()

如需查看所有 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<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'
}

使用 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 之前创建类。对于不符合长度限制的较大的对象,请考虑使用 REST API 创建对象,并且只把对象 ID 发送到 JWT。

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 网页按钮,请参阅适用于 Web API 的 Google Pay API for Passes 的参考文档。

要想在电子邮件中将卡券添加到 Google Pay,请在电子邮件中加入一个包含深层链接的按钮。

要将保存到 Google Pay 按钮集成到电子邮件或短信中,需要完成三个步骤:

  1. 定义对象要扩展的 Class
  2. 生成代表 Object 的 JWT
  3. 保存到 Google Pay 按钮添加到电子邮件或短信中

下列步骤以会员卡为例,但同样的过程适用于所有卡券。

1. 定义对象要扩展的类

首先,定义 LoyaltyClass。要插入 LoyaltyClass,请对以下 REST URI 发出 POST 请求:

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

要启用严格的错误解析功能并发现其他错误(例如,存在重复的 ID 字段),请按以下示例 URI 所示,将参数 strict=true 添加到 REST URI:

https://www.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 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()

如需查看所有 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<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'
}

使用 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 之前创建类。对于不符合长度限制的较大的对象,请考虑使用 REST API 创建对象,并且只把对象 ID 发送到 JWT。

填入生成的 JWT 和类 ID:

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

请务必在网址中的参数前加上结尾斜杠。

深层链接网址的安全长度是 1800 个字符。您的深层链接应少于此限制。如果长度超过 1800 个字符,则保存可能会由于网络浏览器执行的截断操作而失败。编码到 JWT 中的对象要小,只包含用户专属数据。尽量将大部分数据放入对象的类中,而且应在生成 JWT 之前创建类。对于不符合长度限制的较大的对象,请考虑使用 REST API 创建对象,并且只把对象 ID 发送到 JWT。

请参阅品牌推广指南,了解如何下载“保存到 Google Pay”按钮图片,以及如何正确放置包含您链接的按钮图片。有关深层链接和“保存到 Google Pay”按钮的详细信息,请观看“保存到 Android Pay”深层链接简介

Gmail 支持使用 Go-To 操作在电子邮件主题行放置顶层按钮。例如,您可能希望添加一个标有“保存到 Google Pay”的按钮,并让它出现在电子邮件的主题行中,这样用户就可以直接从收件箱保存自己的优惠券。要实现此功能,请在电子邮件中添加包含上述深层链接的 View 操作。

在原生 Android 应用中添加

您可以使用以下方法将保存到 Google Pay 按钮添加到您的原生 Android 应用:

要从应用将卡券保存到 Google Pay,请按以下步骤操作:

  1. 完成在电子邮件或短信中添加链接的步骤。
  2. 使用 ACTION_VIEW Intent 打开保存到 Google Pay 按钮包含的深层链接。

    请确保触发 Intent 的按钮遵循品牌指南

下面是流程摘要示例:

  1. 在保存卡券之前的某个时间,使用 REST API 在后端创建一个类。
  2. 当最终用户要求保存卡券时,您的服务器后端会将 JWT 发送给代表对象的 Android 客户端应用。
  3. 您的 Android 客户端应用包含符合我们品牌指南保存到 Google Pay 按钮。点击该按钮后,将针对路径中含有 JWT 的 URI 打开一个 ACTION_VIEW Intent。示例如下:
    https://pay.google.com/gp/v/save/{jwt_generated}
    

使用原生 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 是 48dp,minWidth 必须是 200dp。

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