This guide explains how to use callbacks with the Google Wallet API. When a pass is created or deleted, Google can perform a callback to an HTTPS endpoint of your choosing. This callback is class-specific, and includes data about the event such as the class, object, and event type. This can be used to keep track of the number of user adds and deletions that occur. For example, callbacks can be configured to send events to an analytics application to track customer engagement during promotional events.
Prerequisites
Before you start, review the following prerequisites:
- Stand up an HTTPS endpoint that handles POST requests. This endpoint needs to be publicly available.
-
Programmatically update the callback endpoint for each class. See the
callbackOptions
property by class in the REST API. - Recommended: Use the Tink library to verify the signatures.
Implement callbacks
For every add or delete performed by the user on an an object , Google makes callbacks to the merchants with details about the add or delete on a per-class URL. Merchants need to first use the Public Keys to verify the authenticity of the message. After the callbacks verify the message, the callbacks can be used for downstream operations.
Verify the signature
We recommend that you use the Tink library to verify the message signature
when you implement your HTTPS endpoint. The
Tink library
provides PaymentMethodTokenRecipient
, a utility that
automatically verifies the signature and returns the actual message upon
successful verification.
The following example shows how to use the Tink library to implement
PaymentMethodTokenRecipient
:
import java.io.IOException; import javax.servlet.http.*; import com.google.common.io.CharStreams; import com.google.crypto.tink.apps.paymentmethodtoken.*; // Replace ISSUER_ID with your issuer id private static final String RECIPIENT_ID = "ISSUER_ID"; private static final String PUBLIC_KEY_URL = "https://pay.google.com/gp/m/issuer/keys"; private static final String SENDER_ID = "GooglePayPasses"; private static final String PROTOCOL = "ECv2SigningOnly"; private static final GooglePaymentsPublicKeysManager keysManager = new GooglePaymentsPublicKeysManager.Builder() .setKeysUrl(PUBLIC_KEY_URL) .build(); public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { try { // Extract signed message with signature from POST request body. String signedMessage = CharStreams.toString(request.getReader()); PaymentMethodTokenRecipient recipient = new PaymentMethodTokenRecipient.Builder() .protocolVersion(PROTOCOL) .fetchSenderVerifyingKeysWith(keysManager) .senderId(SENDER_ID) .recipientId(RECIPIENT_ID) .build(); String serializedJsonMessage = recipient.unseal(signedMessage); // Use serializedJsonMessage to extract the details } catch (Exception e) { // Handle the error } }
Expected message format
The message format is JSON that's serialized into a string with the following properties:
Identifier | Description |
---|---|
classId |
Fully qualified class ID. Uses the following format: <issuer_id.class_id> |
objectId |
Fully qualified object ID. Uses the following format: <issuer_id.object_id> |
expTimeMillis |
Expiration time in milliseconds since EPOCH. After the expiration time, the message needs to be deemed invalid. |
eventType |
Can be either del oder save for
DELETE and SAVE .
|
nonce |
Nonce to track any duplicate deliveries. |
Handle the request from a Google server
The following is a list of the key fields in the header of the request that's sent to your callback endpoint:
- User-Agent:
Googlebot
- Content-Type:
application/json
Configure your server so that it doesn't reject the request. To do so, you can
set the following in robots.txt
:
User-agent: Googlebot Disallow:
Retries
Callbacks are on a best-effort basis. Google will use common retry strategies to be resilient in cases where the callback endpoint is not responding or has an intermittent outage and will gracefully back off attempts.
Duplicate deliveries
There might be duplicate deliveries in some cases. We recommend that you use
nonce
to dedupe them.