Зачем


У меня есть pet-project, приложение для учета финансов. На мой взгляд одной из ключевых проблем подобных приложений является ручной ввод баланса. У банков, в частности сбера, есть информация о транзакциях которые я совершаю и даже есть неплохая аналитика.
Но


  • Банков несколько и они ничего не знают друг про друга. В итоге
    • Нет единой аналитики
    • Перевод денег из одного банка в другой будет считаться как списание с одной стороны и зачисление с другой. Эта особенность портит аналитику.
  • Возможность работать с данными позволяет строить любую аналитику и прогнозы в отличие от ui банка

Приложения, в отличие от сайтов, запрашивают данные с сервера и только в своих кишках делают из него UI. В то время как сайты зачастую отчасти рендерятся на сервере. В приложения обычно приходят уже удобные json/xml.


Как


К сожалению, банки не выкладывают документацию на API в открытый доступ. Но его довольно легко получить из android приложения.


Краткая инструкция


  • Качаем charles, apktool, "штука для подписи приложений"
  • Подготавливаем приложение к MITM
    • С помощью apktool анбоксим приложение apktool d -f -r Sberbank.apk
    • Выгружаем из charles корневой сертификат Help > SSL Proxying > Save Charles Root Certificate
    • Заменяем доверенный сертификат сбербанка на сертификат charles cp <your.cer> Sberbank/res/raw/thawte_rsa_ca_2018_thawte_ssl_wildcard.cer
    • Теперь приложение будет доверять charles вместо сбера.
  • Собираем приложение обратно apktool b Sberbank -o ${apkName}
  • И подписываем его java -jar sign.jar ${apkName}
  • Подписанное приложение устанавливается вместо настоящего на телефон
  • Конфигурируем телефон на проксирование трафика через Charles (в настройках wifi выбирается Proxy. IP - машины с charles, PORT-8888)
  • Запускаем приложение и снифим трафик.

Итог


Получилась библиотека для kotlin.jvm. Под капотом используется okhttp для запросов
и jackson для парсинга xml. Есть возможность как получать сырые данные из XML, так и смапленные в объектную, автосгенеренную модель
Пример использования


 println("login:")

 // mguid Является переиспользуемым и получается один раз при регистрации девайса
 val mguid = SberbankRegistration().register(readLine()!!) {
                         println("smsPassword:")
                         readLine()!!
                     }
 //Логин нужно выполнять 1 раз на сессию
 val sberbank = SberbankLogining().login(mguid)

 val products = sberbank.productList()
 val result = ArrayList<Operation>()
         for (card in products.cards!!.list!!) {
             val elements = sberbank.paymentsList(
                    card = card,
                    from = LocalDate.now().minusYears(5),
                    to = LocalDate.now(),
                    paginationSize = Short.MAX_VALUE.toInt(),
                    paginationOffset = 0
            ).operations
             if(elements!=null){
                 result.addAll(elements)
             }
         }
  print(result)

Буду рад помощи в развитии проекта, например в публикации API в maven central.