设计初衷
如概览中所述,根据运营商希望支持的用例,DPA 必须实现 Google 移动数据流量共享 API 和数据流量代理 API 的组合。本文档介绍了 Google 将用于识别用户的移动数据流量套餐、检索有关这些套餐的信息以及购买数据流量套餐的数据流量套餐代理 API。
身份验证
在 GTAF 可以调用之前,DPA 必须对 GTAF 进行身份验证。在运营商的初始配置过程中,我们会检查 DPA SSL 证书的有效性。我们目前要求使用 OAuth2 进行双向身份验证。
API 说明
在查询运营商的 DPA 时,GTAF 会使用用户密钥(用于标识运营商的订阅者)。当 GTAF 代表有权访问 MSISDN 的应用查询 DPA 时,GTAF 可以使用 MSISDN。从宏观层面来看,提议的数据流量方案代理 API 包含以下组件:
- 用于查询用户数据流量套餐状态的机制。
- 用于向 DPA 查询用户的数据流量方案优惠的机制。
- 用于更改用户数据流量方案(例如购买新方案)的机制。
- 用于验证用户是否符合购买特定流量套餐的条件。
- GTAF 向 DPA 注册 MSISDN 的机制。
- 供 GTAF 验证 DPA 是否处于健康状态的机制。
本文档的其余部分将详细介绍这些 API 组件。除非另有明确说明,否则所有通信都必须通过 HTTPS(使用有效的 DPA SSL 证书)进行。运营商可以选择实现所有或部分这些 API 组件,具体取决于所支持的实际功能。
查询数据流量套餐状态
GTAF-DPA 互动
图 4. 用于请求和接收用户数据流量方案信息的调用流程。
图 4 展示了与客户端查询用户的数据流量套餐状态和其他数据流量套餐信息相关的调用流程。此调用流程适用于由 UE 上的客户端触发的 API 调用。
- 客户端通过调用私有 Google API 请求流量方案状态和/或其他信息。客户端在向 GTAF 发送的请求中包含用户密钥。
- GTAF 使用用户密钥和客户端标识符来查询运营商的 DPA。支持的客户端标识符为 mobiledataplan 和 youtube。当 DPA 收到包含这些客户端标识符之一的调用时,必须使用客户端可用的方案信息进行响应。
- GTAF 会将所请求的信息返回给客户端,并且 GTAF 会缓存方案信息,直到 DPA 指定的过期时间为止。
图 4 中的步骤 1 和 3 是专用 Google API,因此不再进一步说明。步骤 2 是下文所述的公共 API。DPA 在通过 GTAF 处理这些 API 调用时,必须遵循 Cache-Control: no-cache
HTTP 标头。
方案状态
GTAF 会发出以下 HTTP 请求来获取方案状态:
GET DPA_URL/{userKey}/planStatus?key_type={CPID,MSISDN}&client_id=CLIENT_ID
GTAF 代表其与 DPA 联系的客户端使用 CLIENT_ID 进行标识。根据 Google 客户端与运营商之间的协议,DPA 可以自定义对 GTAF 的响应。响应的格式为表示 PlanStatus 的 JSON 对象。
{
"plans": [{
"planName": "ACME1",
"planId": "1",
"planCategory": "PREPAID",
"expirationTime": "2017-01-29T01:00:03.14159Z", // req.
"planModules": [{
"moduleName": "Giga Plan", // req.
"trafficCategories": ["GENERIC"],
"expirationTime": "2017-01-29T01:00:03.14159Z", // req.
"overUsagePolicy": "BLOCKED",
"maxRateKbps": "1500",
"description": "1GB for a month", // req.
"coarseBalanceLevel": "HIGH_QUOTA"
}]
}],
"languageCode": "en-US", // req.
"expireTime": "2018-06-14T08:41:27-07:00", // req.
"updateTime": "2018-06-07T07:41:22-07:00", // req.
"title": "Prepaid Plan"
"planInfoPerClient": {
"youtube": {
"rateLimitedStreaming": {
"maxMediaRateKbps": 256
}
}
}
}
请求应包含 Accept-Language
标头,以指明人类可读字符串(例如方案说明)应采用的语言。
对于后付费方案,expirationTime
必须是方案的周期性日期(即数据余额刷新/重新加载的日期)。
每个计划模块可能包含多个计划模块流量类别(PMTCs)
,用于对多个应用共享一个计划模块的情况进行建模,例如,500 MB(游戏和音乐)。以下 PMTC 是预定义的:GENERIC, VIDEO,
VIDEO_BROWSING, VIDEO_OFFLINE, MUSIC, GAMING, SOCIAL and MESSAGING.
预计运营商会联系各个 Google 团队,就与不同 Google 应用相关的流量类别及其语义达成一致。
查询方案优惠
GTAF 会发出以下 HTTP 请求,以从运营商处获取方案优惠:
GET DPA_URL/{userKey}/planOffer?key_type={CPID,MSISDN}&client_id=CLIENT_ID&context={purchaseContext}
GTAF 代表其与 DPA 联系的客户端使用 CLIENT_ID 进行标识。根据 Google 客户端与运营商之间的协议,DPA 可以自定义对 GTAF 的响应。可选的 context 参数提供发出请求的应用上下文。通常,这是应用通过 GTAF 传递给运营商的字符串。
响应正文包含一个 PlanOffer 实例。
{
"offers": [
{
"planName": "ACME Red", // req.
"planId": "turbulent1", // req.
"planDescription": "Unlimited Videos for 30 days.", // req.
"promoMessage": "Binge watch videos.",
"languageCode": "en_US", // req.
"overusagePolicy": "BLOCKED",
"cost": { // req.
"currencyCode": "INR",
"units": "300",
"nanos": 0
},
"duration": "2592000s",
"offerContext": "YouTube",
"trafficCategories": ["VIDEO"],
"quotaBytes": "9223372036850"
}
],
"expireTime": "2019-03-04T00:06:07Z" // req.
}
offers
数组中数据方案的顺序可能会决定向用户呈现数据方案的顺序。此外,如果应用由于界面或其他限制只能显示 x 个方案,而响应包含 y > x 个方案,则只能显示前 x 个方案。如果查询优惠的应用是移动数据流量方案界面(属于 Google Play 服务),则 GTAF 最多只会分享 10 个方案。这是为了确保 Google Play 服务的用户获得良好的用户体验。
offerInfo
中的字符串旨在让用户详细了解相应优惠,还包含一种选择不再接收应用内更多优惠的方式。设置这些字段的原因是,某些运营商不需要征得最终用户同意即可允许应用内购,但需要一种供用户选择停用的机制。请注意,运营商必须具备一种机制来满足向用户提供的任何优惠的购买请求。用户购买任何商品时所用的付款机制可以通过响应中的 formOfPayment 选项与 GTAF 进行通信。
请求应包含 Accept-Language
标头,以指明人类可读字符串(例如方案说明)应采用的语言。
数据购买
购买方案 API 定义了 GTAF 如何通过 DPA 购买方案。GTAF 会启动交易,以向 DPA 购买一个流量套餐。请求应包含唯一的交易标识符 (transactionId),以跟踪请求并避免重复执行交易。DPA 必须返回成功/失败响应。
交易请求
一旦收到来自客户端的请求,GTAF 就会向 DPA 发出 POST 请求。请求的网址为:
POST DPA_URL/{userKey}/purchasePlan?key_type={CPID,MSISDN}&client_id=CLIENT_ID
其中 userKey
为 CPID
或 MSISDN
。请求正文是 TransactionRequest 的实例,包含以下字段:
{
"planId": string, // Id of plan to be purchased. Copied from
// offers.planId field returned from a
// Upsell Offer request,
// if available. (req.).
"transactionId": string, // Unique request identifier (req.)
"offerContext": string, // Copied from from the
// offers.offerContext, if available.
// (opt.)
"callbackUrl": string // URL that the DPA can call back with response once
// it has handled the request.
}
交易响应
如果出现错误,DPA 应返回常见的错误原因。 此外,以下错误代码表示交易失败:
- DPA 返回 400 BAD REQUEST 错误代码,向 GTAF 表明所购买的方案 ID 无效。
- DPA 返回 402 PAYMENT REQUIRED 错误代码,向 GTAF 指示用户没有足够的余额来完成购买交易。
- DPA 返回 409 CONFLICT 错误代码,向 GTAF 指示要购买的方案与用户当前的产品组合不兼容。例如,如果运营商数据流量方案政策不允许混合使用后付费和预付费方案,那么尝试为后付费用户购买预付费方案会导致 409 CONFLICT 错误。
- DPA 返回 403 FORBIDDEN 错误代码,向 GTAF 指示当前交易与之前签发的交易重复。DPA 应在响应中返回以下错误原因:
- 如果上一个事务失败,则表示失败原因的错误原因。
- 如果上一次交易成功,则为 DUPLICATE_TRANSACTION。
- 如果上一个交易仍在队列中,则为 REQUEST_QUEUED。
DPA 仅应针对成功执行的交易或已加入队列的交易生成 200-OK 响应。如果交易已排队,DPA 应仅填充交易状态,并将响应中的其他字段留空。DPA 必须在处理完排队的交易后,通过响应回调 GTAF。响应正文是 TransactionResponse 的实例,其中包含以下详细信息:
{
"transactionStatus": "SUCCESS",
"purchase": {
"planId": string, // copied from request. (req.)
"transactionId": string, // copied from request. (req.)
"transactionMessage": string, // status message. (opt.)
"confirmationCode": string, // DPA-generated confirmation code
// for successful transaction. (opt.)
"planActivationTime" : string, // Time when plan will be activated,
// in timestamp format. (opt.)
},
// walletInfo is populated with the balance left in the user's account.
"walletBalance": {
"currencyCode": string, // 3-letter currency code defined in ISO 4217.
"units": string, // Whole units of the currency amount.
"nanos": number // Number of nano units of the amount.
}
}
如果缺少 planActivationTime
,GTAF 应假定相应方案已激活。
同意
GTAF 可能会发出以下请求,以将用户同意偏好传递给运营商。
POST DPA_URL/{userKey}/consent?key_type={CPID,MSISDN}&client_id=CLIENT_ID
其中 userKey
为 CPID
或 MSISDN
。请求正文是 SetConsentStatusRequest 的实例。
如果成功,则响应正文应为空。
资格要求
GTAF 可能会发出以下资格要求,以检查用户是否符合购买方案的条件。
GET DPA/{userKey}/Eligibility/{planId}?key_type={CPID,MSISDN}
请注意,planId
是方案的唯一标识符,可用于代表用户购买方案(请参阅数据购买)。如果未指定 planId
,DPA 必须返回相应用户可购买的所有方案。
如果出现错误,DPA 应返回常见的错误原因。 此外,DPA 应在以下错误情况下返回错误:
- DPA 返回 400 BAD REQUEST 错误代码,向 GTAF 表明
planId
无效。 - DPA 返回 409 CONFLICT 错误代码,表明
planId
与用户的数据流量套餐不兼容。
否则,DPA 应返回 200-OK 响应。成功的 EligibilityResponse 的格式如下:
{
"eligiblePlans":
[
{
"planId": string, // Plan identifier. Can be used to
// refer to the plan during
// offers, etc. (req.)
}
]
}
如果请求中包含 planId
,则响应中仅包含该方案。否则,该列表会包含用户符合购买条件的所有方案。如果 planId
为空,且 DPA 不支持返回符合条件的方案列表,则必须返回 400 BAD REQUEST 错误。
MSISDN 注册端点
为了提供可访问 MSISDN 的应用,GTAF 会向 DPA 注册 MSISDN。只有当有应用通过 Google 移动数据流量共享 API 提供服务时,GTAF 才会注册 MSISDN,其中 DPA 会使用 Google API 将信息发送给 GTAF。如需注册 MSISDN,GTAF 将向 DPA 发出 POST 请求:
POST DPA_网址/register
请求正文将是 RegistrationRequest 的实例。
{
"msisdn": "<msisdn_string>"
}
如果 MSISDN 注册成功,DPA 必须返回 200 OK 响应,其中包括 RegistrationResponse。JSON 的格式如下:
{
// msisdn that was registered.
"msisdn": "<msisdn_string>",
// time after which DPA will not send updates to GTAF.
"expirationTime": string
}
然后,DPA 应向 GTAF 发送有关用户数据流量套餐的更新,直到 expirationTime 过去为止。
如果发生错误,应返回 ErrorResponse:
{
"error": "<error message>",
"cause": enum(ErrorCause)
}
如需查看不同错误情况的可能原因值和 HTTP 状态代码的完整列表,请点击此处。具体而言,如果收到漫游用户或未选择与 Google 分享流量套餐信息的用户发出的 MSISDN 注册请求,DPA 必须返回 HTTP 状态代码 403。
Monitoring API
某些使用情形需要 GTAF 监控 DPA 并检测 DPA 故障。对于这些使用情形,我们定义了监控 API。
API 定义
监控 API 应可通过以下网址中的 HTTP GET 请求获得:
DPA_URL/dpaStatus
如果 DPA 及其所有后端均正常运行,则 DPA 应使用 HTTP 状态代码 200 和包含 DpaStatus 实例的响应正文来响应此查询。
{
"status": enum(DpaStatusEnum),
"message": "<optional human-readable status description>"
}
如果 DPA 或其任何后端未正常运行,则应返回 HTTP 状态代码 500 和包含 DpaStatus 实例的响应正文。
DPA 行为
检测到故障时,DPA 必须针对所有 dpaStatus 查询返回“UNAVAILABLE”状态。此外,它还必须停止发送具有较长缓存周期的流量方案信息。它可能会通过以下两种方式之一停止发送具有较长缓存期限的响应:
- 开始设置较短的缓存过期时间。
- 完全停止发送流量套餐信息。
GTAF 行为
GTAF 会定期轮询 dpaStatus。当检测到 DPA 失败(基于“UNAVAILABLE”响应)时,它会清除其针对相应运营商的缓存。
错误情形
如果出现错误,DPA 应返回与以下状态代码之一对应的 HTTP 状态代码:
- 用户目前处于漫游状态,并且已为此用户停用 DPA 查询。DPA 返回 403 错误。
- DPA 返回 404 NOT_FOUND 错误代码,向 GTAF 表明用户密钥无效(即不存在的用户密钥)。
- DPA 返回 410 GONE 错误代码,向 GTAF 指示,如果 key_type = CPID 且 CPID 已过期,客户端应获取新的用户密钥。
- DPA 返回 501 NOT_IMPLEMENTED 错误代码,表明它不支持此调用。
- 服务暂时不可用。DPA 会返回 503 SERVICE UNAVAILABLE,并附带 Retry-After 标头,指明何时可以尝试新请求。
- 对于所有其他未指定的错误,DPA 会返回 500 INTERNAL SERVER ERROR 错误代码。
- DPA 返回 429 TOO_MANY_REQUESTS 错误,并附带 Retry-After 标头,表明 GTAF 向 DPA 发出的请求过多。
- DPA 返回 409 CONFLICT 错误,表明由于与 DPA 的当前状态存在冲突,因此请求无法完成。
在所有错误情况下,HTTP 响应的正文都必须包含一个 JSON 对象,其中包含有关错误的更多信息。错误响应正文必须包含 ErrorResponse 的实例。
{
"error": string,
"cause": enum(ErrorCause)
}
目前定义的 cause
值列在 ErrorCause API 参考文档中。
否则,DPA 会返回 200 OK。请注意,这些 cause
值适用于所有响应。
国际化
发送给 DPA 的 GTAF 请求包含 Accept-Language 标头,用于指明人类可读字符串(例如方案说明)应采用的语言。此外,DPA 响应(PlanStatus、PlanOffers)包含一个必需的 languageCode 字段,其值为 BCP-47 语言代码(例如,响应的“en-US”)。
如果 DPA 不支持用户请求的语言,则可以使用默认语言,并通过 languageCode 字段指明其选择。