Data Plan Agent API

动机

概览中所述,DPA 必须实现 Google 移动流量套餐共享 API 和流量套餐代理 API 的组合,具体取决于运营商希望支持的用例。本文档介绍了 Google 将用于识别用户的移动流量套餐、检索关于这些套餐的信息以及购买流量套餐的 Data Plan Agent API。

身份验证

GTAF 必须先调用 GTAF,然后才能对其进行调用。在运营商新手入门流程期间,我们将检查 DPA SSL 证书的有效性。目前,我们要求使用 OAuth2 进行双向身份验证。

API 说明

GTAF 在查询运营商的 DPA 时使用用户密钥来识别运营商的用户。当 GTAF 代表有权访问 MSISDN 的应用查询 DPA 时,GTAF 可以使用 MSISDN。概括来讲,建议的 Data Plan Agent API 包含以下组件:

  1. 查询用户流量套餐状态的机制。
  2. 查询 DPA 以获取用户的流量套餐方案的机制。
  3. 更改用户的流量套餐(例如,购买新的套餐)的机制。
  4. 用于验证用户是否有资格购买特定流量方案的机制。
  5. GTAF 向 DPA 注册 MSISDN 的机制。
  6. GTAF 验证 DPA 是否处于良好状态的机制。

本文档的其余部分详细介绍了这些 API 组件。除非另有明确说明,否则所有通信都必须通过 HTTPS(使用有效的 DPA SSL 证书)进行。根据支持的实际功能,运营商可以选择实现全部或部分 API 组件。

查询流量套餐状态

GTAF-DPA 互动

GTAF-DPA 互动

图 4.用于请求和接收用户数据套餐信息的调用流程。

图 4 展示了与查询用户的流量套餐状态和其他流量套餐信息的客户端相关联的呼叫流程。此调用流程由客户端在 UE 上触发的 API 调用共享。

  1. 客户端通过调用专用 Google API 来请求流量套餐状态和/或其他信息。客户端会在向 GTAF 发出的请求中包含用户密钥
  2. GTAF 使用用户密钥和客户端标识符来查询运算符的 DPA。支持的客户端标识符为 mobiledataplanyoutube。当 DPA 收到包含这些客户端标识符之一的调用时,它必须在响应中提供客户端可使用的方案信息。
  3. GTAF 将请求的信息返回给客户端,并且 GTAF 会缓存计划信息,直到 DPA 指定的过期时间。

图 4 中的第 1 步和第 3 步是私有 Google API,因此不再作进一步说明。第 2 步是下文所述的公共 API。从 GTAF 调用这些 API 时,DPA 必须遵循 Cache-Control: no-cache HTTP 标头。

方案状态

GTAF 会发出以下 HTTP 请求以获取方案状态:

GET DPA_URL/{userKey}/planStatus?key_type={CPID,MSISDN}&client_id=CLIENT_ID

您可以使用 CLIENT_ID 来标识 GTAF 联系 DPA 的客户端。根据 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}

您可以使用 CLIENT_ID 来标识 GTAF 联系 DPA 的客户端。根据 Google 客户端与运营商之间的协议,DPA 可以自定义对 GTAF 的响应。可选的上下文参数提供发出请求的应用上下文。通常,这是应用通过 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

其中 userKeyCPIDMSISDN。请求正文是 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 必须返回响应。响应正文是 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

其中 userKeyCPIDMSISDN。请求正文是 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 响应。成功的 EligabilityResponse 的格式为:

{
  "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 请求:

发布 DPA_网址/注册

请求正文将是 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 故障。对于这些用例,我们定义了一个 Monitoring API。

API 定义

Monitoring 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”状态。此外,它必须停止发送具有较长缓存周期的数据方案信息。它可能会通过以下两种方式之一停止发送具有较长缓存期的响应:

  1. 开始设置较短的缓存过期时间。
  2. 完全停止发送流量套餐信息。

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 内部服务器错误错误代码。
  • 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 字段指明其选择。