Перейти к содержимому

Android Push Provisioning API

Небольшая статья по Android Push Provisioning API- которое необходимо для взаимодействия банковского приложения и Google Pay.

В сети практически нет информации в открытом доступе, так как штука довольно специфичная и информация от Google открыта только для сотрудников финансовых учреждений- издателей карт

https://support.google.com/google-pay-and-wallet-console/answer/15157842?hl=en

Если вы считаете, что у вас должен быть доступ к этой информации, вы можете его запросить

https://developers.google.com/pay/issuers/request-access

Подробности реализации нельзя упоминать, поэтому напишу в общих чертах
Сначала в gradle нужно добавить зависимость tapAndPay, также скачать по указанной выше ссылке tapAndPay SDK и поместить его в папку

C:\Users\\AppData\Local\Android\Sdk\extras\google

Для отладки в эмуляторе нужно включить режим песочницы, для этого добавляем файл android_pay_env_override_sandbox в папку загрузки на устройстве

$ adb shell touch /sdcard/Download/android_pay_env_override_sandbox
$ adb reboot

перед adb не забываем ставить путь к нему, если папка не выбрана

для MacOS ~/Library/Android/sdk/platform-tools/adb
для Windows C:\Users\\AppData\Local\Android\Sdk\platform-tools\adb

выключить режим песочницы можно, удалив файл

$ adb shell rm /sdcard/Download/android_pay_env_override_sandbox
$ adb reboot

Нужно добавить приложение в список разрешенных, так как Google разрешает доступ к Push Provisioning API только аффилированным финансовым учреждениям. Следовательно, чтобы приложение эмитента карты могло вызвать API, приложению должен быть предоставлен доступ к API. Сделать это можно здесь

https://support.google.com/faqs/contact/pp_api_allowlist?hl=en

Если приложение не добавлено в разрешенные, API будет выдавать ошибку TAP_AND_PAY_UNAVAILABLE. Если используются суффиксы applicationIdSuffix, нужно добавить пакет и с ними, чтобы работало.
Google Pay выполняет проверку аутентификации при вызове через API. Эта проверка не удастся, если у устройства есть привилегии root.

Для работы нужно добавить UI, тут есть особенность в том, что кнопка для добавления карты и логотип Google Pay на картинке карты и других кнопках, связанных с Google Pay, должны точно соответствовать дизайну Google, иначе не пройдет модерацию.
Надпись Google Pay не должна быть сокращена, должна быть на английском, на странице мануала приводятся правильные переводы для кнопки “Добавить в Google Pay”

Все кнопки настройки Google Pay должны иметь ширину не менее 139 dp, всегда должно быть не менее 8 dp свободного пространства сверху , снизу, слева и справа от кнопки Google Pay, не помещайте графику или текст в свободное пространство.
Как вообще работает Google Pay можно почитать здесь

https://developers.google.cn/android/guides/overview?hl=ru

Карта добавляется через реквест в tapAndPay клиенте, в котором сначала нужно заполнить данные пользователя- имя, страна, адрес, квартира, город, область, почтовый индекс и телефон, если все это не задать в реквесте, пользователь должен будет ввести это в приложении Google Pay при добавлении.

После этого в реквесте нужно указать Opaque Payment Card — это зашифрованные объекты, созданные эмитентом карты и переданные в Google Pay во время инициализации. Каждый поставщик услуг токенов (TSP) имеет свои собственные спецификации для форматирования OPC и методы шифрования для эмитентов карт.

OPC можно сгенерировать, выполнив следующие действия.

Обменяйтесь ключами с TSP. Эти ключи используются для шифрования и дешифрования OPC.

Создайте и зашифруйте OPC в соответствии с документацией TSP.

Работайте с TSP, чтобы убедиться, что OPC действителен и правильно зашифрован.

OPC, который передается в Google, должен быть строкой в кодировке Base64. Если TSP отклоняет OPC по какой-либо причине, Google Pay покажет пользователю сообщение об общей ошибке.

Также указывается тип банковский сети- Visa, Mastercard или другая, всего их 7, и также провайдера токена- Visa, Mastercard и другие, всего их 10, все они находятся в качестве констант в классе клиента, также необходимо имя карты и последние 4 цифры номера карты. При нажатии “добавить карту” реквест будет отправляться в Google Pay и пользователь- перенаправляться в приложение Google Pay, если оно установлено, а если нет- нужно добавить соответствующую логику для установки из Play Market.

Для операций с кошельком нужен параметр TokenReferenceId и StableHardwareId- из названий в принципе понятно, что это.
Чтобы были понятны статусы и ошибки при работе с api при выводе в консоль, удобно сделать функцию с расшифровкой констант ошибок и статусов, я сделал это так

private fun logResult(pair: Pair<Boolean, String>) {
    if (pair.first) {
        logd(pair.second, "GooglePay")
    } else {
        loge(pair.second, "GooglePay")
    }
}

private fun walletStatus(statusCode: Int) = when (statusCode) {
    TapAndPayStatusCodes.TAP_AND_PAY_NO_ACTIVE_WALLET ->
        false to "No active wallet"
    TapAndPayStatusCodes.TAP_AND_PAY_TOKEN_NOT_FOUND ->
        false to "card issuer token ID presented does not match the token in the valid wallet"
    TapAndPayStatusCodes.TAP_AND_PAY_INVALID_TOKEN_STATE ->
        false to "Specified token was found but could not be processed because it was not in a valid state"
    TapAndPayStatusCodes.TAP_AND_PAY_ATTESTATION_ERROR ->
        false to "Tokenization failed because the device did not pass the compatibility check"
    TapAndPayStatusCodes.TAP_AND_PAY_UNAVAILABLE ->
        false to "TapAndPay API cannot be called in the current app"
    else ->
        false to "wallet status code $statusCode"
}

private fun tokenStatus(statusCode: Int) = when (statusCode) {
    TapAndPay.TOKEN_STATE_NEEDS_IDENTITY_VERIFICATION ->
        false to "The token is in a valid wallet, but requires additional user authentication to use (step up authentication required)"
    TapAndPay.TOKEN_STATE_PENDING ->
        false to "Currently, tokens cannot be used for payment, but after a while they will be available"
    TapAndPay.TOKEN_STATE_SUSPENDED ->
        false to "The token has been temporarily suspended"
    TapAndPay.TOKEN_STATE_ACTIVE ->
        true to "The token is valid and can be used for payment"
    TapAndPay.TOKEN_STATE_FELICA_PENDING_PROVISIONING ->
        false to "The token is issued by TSP, but Felica has not been provisioned yet"
    TapAndPay.TOKEN_STATE_UNTOKENIZED ->
        false to "This state does not apply to push provisioning"
    else ->
        false to "token status code $statusCode"
}

loge и logd в этом примере просто обрабатывают сообщения и выводят, если BuildConfig.DEBUG, а “GooglePay” это таг для поиска в logcat

Для удобства можно добавить классы для констант провайдера токена и сети

enum class TokenProvider(val value: Int) {
    MASTERCARD(3),
    VISA(4),
    DISCOVER(5),
    EFTPOS(6),
    INTERAC(7),
    OBERTHUR(8),
    PAYPAL(9),
    JCB(13),
    ELO(14),
    GEMALTO(15)
}

enum class CardNetwork(val value: Int) {
    AMEX(1),
    DISCOVER(2),
    MASTERCARD(3),
    VISA(4),
    INTERAC(5),
    PRIVATE_LABEL(6),
    EFTPOS(7),
    MAESTRO(8),
    ID(9),
    QUICPAY(10),
    JCB(11),
    ELO(12)
}

В версии API 17.1.0 добавлен метод listTokens, благодаря которому можно получить некоторую информацию о добавленных карточках, а именно

IssuerTokenId
FpanLastFour
DpanLastFour
TokenServiceProvider
Network
IsDefaultToken
PortfolioName

Похожим образом через tapAndPay клиент осуществляются и другие действия с картой- всего в его интерфейсе 15 методов, чуть выше описал самый сложный из них.

Copyright: Roman Kryvolapov