This page provides the technical details a Public Transit Operator (PTO) and their system integrator need to integrate with Google to provide Motics tickets in Google Wallet. The solution makes use of the Google Wallet API and also relies on the PTO implementing an activation endpoint.
System Architecture
This section shows the system architecture and the Motics save flow.
Figure 1. Motics Ticket Save Flow
Figure 1 shows the flow for creating, activating and pinning a Motics ticket in Google Wallet, across several entities:
- Google servers
- PTO (System Integrator) server
- Motics SCE server
- Web shop
The following describes the flow in more detail:
- In the initial setup phase, the PTO server creates the
transitClass
, passing theownerId
andactivationUrl
using the transitClass:Insert Google Wallet API endpoint. This is a one-off activity. - Next, when a user purchases a ticket from the web shop, the PTO server calls transitObject:Insert containing basic ticketing information and some initial fields indicating that this a Motics ticket.
- Then the PTO server and web shop work together to render the Add to Google Wallet button and ultimately return the ticket's JWT to Google, using the save link.
- Now the ticket pinning phase can begin, when the Google server calls the
Activation Endpoint behind the
activationUrl
. - In response to Step 4, the PTO server generates the signature (sigSTB) containing the SCE_ID signed with the SAM.
- Before responding to the
activationUrl
call, the PTO server should first call transitObject:Patch containing all the necessary Motics information, including the Motics applicationData. - Only after the transitObject:Patch call has been successful, the PTO
server should return a success (HTTP-200) response to the
activationUrl
call.
Implement the Move & Unlink Flow
To provide a good user experience, a user should be able to move their Motics ticket from one device to another, within certain limits defined by the issuer. For this, the issuer has to implement the Move and Unlink Flow.
Activation Endpoint
The issuer/PTO (or their system integrator) needs to implement a ticket activation endpoint which Google will invoke when the ticket is saved. The URL to this endpoint should be provided in the invocation to transitClass:Insert. The activation endpoint will generate the signature (sigSTB) and call the transitObject:Patch method with the parameters defined in the following section.
Request
The request to the activation endpoint has the following format:
Content-Type: application/json
Body: {
"classId": "123.classId",
"expTimeMillis": 1669671940735,
"eventType": "activate",
"objectId": string - base64 encoded ID of the TransitObject,
"deviceContext": string - base64 encoded SCE_ID,
}
Response
An HTTP-200
success response with an empty body, should be returned if:
- The sigSTB containing SCE_ID was generated and signed with the SAM
- The transitObject:Patch method was called successfully
Status: 200 - OK
Body: {}
Latency Targets
The activation endpoint should adhere to the following latency targets:
- At least
50%
of all requests should be responded to within200ms
- At least
95%
of all requests should be responded to within2s
- There is a hard upper limit of
10s
Google Wallet API changes
The following outlines the changes to the Google Wallet API endpoints in order to support Motics as outlined in the system architecture.
Method: transitClass:insert
This is the Google Wallet API endpoint to create a transitClass
on Google's
backend. The system integrator needs to invoke this API with the following
request parameters along with any other fields which are applicable. Refer to
the transitClass & transitClass.Insert API documentation for a full list of
(non-Motics) parameters and more details.
POST: https://walletobjects.googleapis.com/walletobjects/v1/transitClass
JSON representation
The Motics integration requires at minimum the following JSON representation of
the transitClass
in the transitClass:insert
request body. Other mandatory
transitClass
metadata fields will need to be set as well.
{
"id": string,
"multipleDevicesAndHoldersAllowedStatus": ONE_USER_ONE_DEVICE (MultipleDevicesAndHoldersAllowedStatus),
"deviceCertificationSupport": {
"vdvCertDetails": {
"ownerId" string,
"certEnvironment": PRODUCTION/STAGING,
},
},
"activationOptions": {
"activationUrl": string
},
...
}
When certEnvironment = PRODUCTION the Google server will fetch the certificate from the production Motics server. When certEnvironment = STAGING the Google server will fetch the certificate from the sandbox Motics server.
Method: transitObject:insert
This is the Google Wallet API endpoint to insert the transitObject
for the new
ticket that a user wants to purchase and add to Google Wallet. The system
integrator should pass a transitObject
with mainly the ticket information at
this point. Refer to the transitObject & transitObject.Insert API
documentation for a full list of (non-Motics) parameters and more details.
POST
: https://walletobjects.googleapis.com/walletobjects/v1/transitObject
JSON representation
The Motics integration requires at minimum the following JSON representation of
the transitObject
in the transitObject:insert
request body. Other object
metadata fields may be set as well and all other mandatory fields should also be
included.
{
"id": string,
"classId": string,
"validTimeInterval": {
object (TimeInterval)
},
"activationStatus": {
"state": NOT_ACTIVATED (State)
},
"rotatingBarcode": {
"type": AZTEC (BarcodeType),
"valuePattern": "{vdv_barcode}",
"deviceEntitlementSupport": {
"vdvEntitlementDetails": {
"applicationData": "",
},
},
},
...
}
Notes:
- The API requires that the
applicationData
field is included. At this point in the Motics activation flow, theapplicationData
value is not yet known, so it has to be set to an empty string.- The
applicationData
will be set later in thetransitObject:Patch
call.
- The
- The
validTimeInterval
DateTime objects must have the timezone offset specified, for example:2024-04-12T19:20:50.52-04:00
.
Method: transitObject:patch
This is the Google Wallet API endpoint to patch the transitObject
with data to be
used by Google for Motics barcode generation and fetching VDV eTicket Service
certificates. Refer to the transitObject & transitObject.Patch API
documentation for a full list of (non-Motics) parameters and more details.
PATCH:
https://walletobjects.googleapis.com/walletobjects/v1/transitObject/{resourceId}
JSON representation
The Motics integration requires the following representation of the
transitObject
in transitObject:patch
request body. Note that it is at this
point that the applicationData
field is populated.
{
"activationStatus": {
"state": ACTIVATED (State)
},
"rotatingBarcode": {
"type": AZTEC (BarcodeType),
"valuePattern": "{vdv_barcode}",
"deviceEntitlementSupport": {
"vdvEntitlementDetails": {
"applicationData": string - Hex encoded,
},
},
}
}
Application Data specifications
The following is the Motics specification for the contents of the
applicationData
(tag:0x5F07
). The applicationData
should be generated by
the system integrator in tag-length-value (TLV) format. This data is later
encapsulated in a larger data structure to be finally encoded as part of the QR
code.
Tag | Length | Value |
0x9E
|
81 80 |
SignatureOctetString , first 128 bytes of signed entitlement dataGoogle term: sigSTB
|
0x9A
|
Varies |
Residual dataOctetString , residual entitlement dataGoogle term: sigSTB cont.
|
0x7F21
|
81 C8 |
Certificate of the issuingOctetString , certificate dataGoogle term: Cert(puk_SAM)
|
0x42
|
08 |
Certificate Authority Reference (CAR)OctetString , CAR valueGoogle term: CAR
|