API агента тарифного плана

Мотивация

Как упоминалось в обзоре , в зависимости от вариантов использования, которые оператор желает поддерживать, DPA должен реализовать комбинацию API Google Mobile Data Plan Sharing и API Data Plan Agent. В этом документе описывается API Data Plan Agent, который Google будет использовать для идентификации тарифных планов пользователя, получения информации об этих тарифных планах и покупки тарифных планов.

Аутентификация

Прежде чем GTAF сможет выполнить вызов, DPA должен аутентифицировать GTAF. В рамках процесса подключения оператора мы проверим действительность SSL-сертификата DPA. В настоящее время для взаимной аутентификации ТРЕБУЕТСЯ использование OAuth2.

Описание API

GTAF использует ключ пользователя , который идентифицирует абонента оператора, при запросе к DPA оператора. Когда GTAF запрашивает DPA от имени приложений, имеющих доступ к MSISDN, GTAF МОЖЕТ использовать MSISDN. На высоком уровне предлагаемый API Data Plan Agent включает следующие компоненты:

  1. Механизм запроса статуса тарифного плана пользователя.
  2. Механизм запроса у DPA предложений тарифных планов для пользователя.
  3. Механизм внесения изменений в тарифный план пользователя (например, приобретение нового тарифного плана).
  4. Механизм проверки права пользователя на приобретение определенного тарифного плана.
  5. Механизм регистрации MSISDN GTAF в DPA.
  6. Механизм проверки GTAF работоспособности DPA.

Далее в документе подробно рассматривается каждый из этих компонентов API. Если явно не указано иное, весь обмен данными ДОЛЖЕН осуществляться по протоколу HTTPS (с действительным SSL-сертификатом DPA). В зависимости от поддерживаемых функций оператор МОЖЕТ реализовать все или часть этих компонентов API.

Запрос статуса тарифного плана

Взаимодействие GTAF-DPA

GTAF-DPA Interaction

Рисунок 4. Поток вызовов для запроса и получения информации о тарифном плане пользователя.

На рисунке 4 показана схема вызова, связанная с запросом клиентом статуса тарифного плана пользователя и другой информации о нём. Эта схема вызова используется для вызовов API, инициированных клиентом на UE.

  1. Клиент запрашивает статус тарифного плана и/или другую информацию, обращаясь к закрытому API Google. Клиент включает ключ пользователя в запрос к GTAF.
  2. GTAF использует ключ пользователя и идентификатор клиента для запроса к DPA оператора. Поддерживаются идентификаторы клиентов: mobiledataplan и youtube . При получении вызова с одним из этих идентификаторов клиента DPA ОБЯЗАН предоставить информацию о тарифном плане, которую может использовать клиент.
  3. GTAF возвращает запрошенную информацию клиенту, а информация о плане кэшируется GTAF до истечения срока действия, указанного DPA.

Шаги 1 и 3 на рисунке 4 представляют собой частные API Google и поэтому далее не описываются. Шаг 2 представляет собой открытый API, описанный далее. DPA ДОЛЖЕН учитывать HTTP-заголовок Cache-Control: no-cache при обслуживании этих вызовов API из GTAF.

Статус плана

GTAF отправляет следующий HTTP-запрос для получения статуса плана:

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

Клиент, от имени которого GTAF обращается к DPA, идентифицируется с помощью CLIENT_ID . В зависимости от соглашения между клиентом Google и оператором связи, DPA может настроить ответ GTAF. Формат ответа — JSON-объект, представляющий PlanStatus .

{
  "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 МБ для игр и музыки). Предопределены следующие категории 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 тарифных планов. GTAF предоставляет доступ только к 10 тарифным планам, если приложение, запрашивающее предложения, использует интерфейс мобильного тарифного плана, который является частью Сервисов Google Play. Это необходимо для обеспечения комфортного использования Сервисов Google Play.

Строки в offerInfo предназначены для того, чтобы пользователь мог узнать больше о предложении, а также предоставить возможность отказаться от получения дополнительных предложений из внутренних приложений. Причина наличия этих полей заключается в том, что некоторым операторам не требуется согласие конечного пользователя для разрешения покупок в приложении, а требуется механизм, позволяющий пользователям отказаться от покупки. Обратите внимание, что оператор ДОЛЖЕН иметь механизм для выполнения запроса на покупку по любому предложению, направленному пользователю. Механизм, посредством которого с пользователя будет взиматься плата за любую покупку, можно сообщить GTAF с помощью параметра formOfPayment в ответе.

Запрос ДОЛЖЕН включать заголовок Accept-Language указывающий язык, на котором должны быть представлены удобочитаемые строки (например, описания планов).

Покупка данных

API плана покупки определяет, как GTAF может приобретать тарифные планы через DPA. GTAF инициирует транзакцию для покупки одного тарифного плана у DPA. Запрос ДОЛЖЕН включать уникальный идентификатор транзакции (transactionId) для отслеживания запросов и предотвращения дублирования транзакций. DPA ДОЛЖЕН ответить успешно/неуспешно.

Запрос транзакции

Получив запрос от клиента, GTAF отправляет POST-запрос к DPA. URL-адрес запроса:

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, что приобретенный идентификатор плана недействителен.
  • 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 регистрирует MSISDN в DPA. GTAF регистрирует MSISDN только при наличии приложений, обслуживаемых API Google Mobile Data Plan Sharing, при этом DPA отправляет информацию в GTAF через API Google. Для регистрации MSISDN GTAF отправляет POST-запрос в DPA:

POST DPA_URL/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 для различных состояний ошибки доступен здесь . В частности, если запрос на регистрацию MSISDN получен от пользователя, находящегося в роуминге или не подтвердившего предоставление Google информации о тарифном плане, DPA ДОЛЖЕН вернуть код статуса HTTP 403.

API мониторинга

В некоторых случаях GTAF требуется для мониторинга DPA и обнаружения сбоев DPA. Для таких случаев мы разработали API мониторинга.

Определение API

API мониторинга должен быть доступен через HTTP-запрос GET по следующему URL-адресу:

DPA_URL/dpaStatus

Если DPA и все его внутренние компоненты работают правильно, DPA должен ответить на этот запрос кодом состояния HTTP 200 и телом ответа, содержащим экземпляр DpaStatus .

{
    "status": enum(DpaStatusEnum),
    "message": "<optional human-readable status description>"
}

Если DPA или любой из его бэкэндов работает неправильно, он должен ответить кодом состояния HTTP 500 и телом ответа, содержащим экземпляр DpaStatus .

Поведение DPA

При обнаружении сбоя DPA должен возвращать статус «UNAVAILABLE» для всех запросов dpaStatus. Кроме того, он должен прекратить отправку информации о тарифном плане с длительными периодами кэширования. Прекращение отправки ответов с длительными периодами кэширования может быть выполнено одним из двух способов:

  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 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 , определенные в настоящее время, перечислены в справочнике API ErrorCause .

В противном случае DPA возвращает код 200 OK. Обратите внимание, что эти значения cause используются для всех ответов.

Интернационализация

Запросы GTAF к DPA включают заголовок Accept-Language, указывающий язык, на котором должны быть представлены удобочитаемые строки (например, описания планов). Кроме того, ответы DPA (PlanStatus, PlanOffers) включают обязательное поле languageCode, значением которого является код языка BCP-47 (например, «en-US») ответа.

Если DPA не поддерживает запрошенный пользователем язык, он может использовать язык по умолчанию и указать свой выбор в поле languageCode.