Obter estatísticas de custo da MCC: Tinkoff e Rocketbank


1. Introdução


MCC (Merchant Category Code) - um código de categoria de comerciante usado em operações com cartões bancários. De acordo com este código, o banco determina qual produto o cliente comprou. Depende dele se eles cobrarão um reembolso, comissão ou cancelarão o período de carência.


Em um século em que as empresas ganham dinheiro com os dados coletados pelos usuários, é pecado não dar o passo inverso: use os dados coletados pelas empresas para que, se você não ganhar dinheiro com isso, salve pelo menos.


Sabendo quanto gasta em cada código MCC, você pode calcular qual cartão bancário trará grandes benefícios. Portanto, se você tiver usado os cartões Tinkoff ou Rocketbank por tempo suficiente, este artigo será útil para obter estatísticas de gastos para cada MCC.


Tinkoff


A conta pessoal do Tinkoff Bank mostra as operações da MCC quando você clica nela.



Assim, você pode ver uma dúzia de operações, mas se precisarmos coletar estatísticas para o tempo inteiro de uso do cartão, esse caso deverá ser automatizado. Vamos tentar obter os dados de uma forma conveniente para o processamento de software.


UPD: Como Smasher observou, sua conta pessoal oferece a capacidade de carregar todas as operações no formato CSV ou Excel. Então, embaixo do spoiler, uma descrição de como eu fiz isso, sem saber.



Indo da maneira mais difícil

Isso exigirá ferramentas de desenvolvimento do navegador e, especificamente, análise da atividade da rede (guia Rede no Google Chrome). Se você ligar o analisador e pedir à sua conta pessoal para exibir as operações "Para sempre", encontraremos rapidamente a solicitação desejada.



Você pode perceber que o servidor realmente forneceu os dados o tempo todo e a MCC necessária está presente na resposta JSON.



Para conveniência do processamento de dados, simule uma solicitação no Python. Estou usando um notebook Jupyter .



Enviaremos uma solicitação POST para o URL https://api.tinkoff.ru/v1/grouped_requests com parâmetros idênticos sessionid e _methods e dados requestData .


import requests session_id = "b785Q2R5US2AZo2p5JoCtNQNkbmYsJbl.ds-api02" methods = "operations" #     , payments   params = {'sessionid': session_id, '_methods': methods} #      requestsData   requests_data = '[{"key":0,"operation":"operations","params":{"wuid":"28a44beaeee7460b94dbdd0aa0dc935a","account":"5059373083","start":1136062800000,"end":1529269199999}}]' data = {'requestsData': requests_data} response = requests.post('https://api.tinkoff.ru/v1/grouped_requests', params=params, data=data) 

Se fizermos tudo certo, digitar response.text no console exibirá o corpo da resposta. Resta analisar esses dados e salvar os fragmentos de que precisamos.


 import csv operations = [] payload = response.json()['payload'] for key in payload: feed = payload[key]['payload'] for operation in feed: mcc = operation['mcc'] # MCC   < 100         if (mcc > 100): #     ,    if 'merchant' in operation: merchant_name = operation['merchant']['name'] else: merchant_name = operation['description'] #  accountAmount     «»  cost = operation['accountAmount']['value'] operations.append((mcc, cost, merchant_name)) print(mcc, cost, merchant_name) #    csv output = open("tinkoff.csv",'w') wr = csv.writer(output) for item in operations: wr.writerow(item) 

Na saída, obtemos uma tabela de códigos MCC, custos de compra e nomes de lojas.


Rocketbank


O Rocketbank mostra as transações da MCC no recebimento. Portanto, precisamos coletar links para recibos de todas as operações.



Com o Rocketbank um pouco mais complicado, porque o acesso à sua conta pessoal é realizado apenas através do aplicativo móvel. Vou contar apenas sobre o que funcionou para mim e apenas sobre o Android. Instale o analisador Charles no computador e passe o tráfego do telefone através dele.


Para fazer isso, o telefone e o computador devem estar conectados à mesma rede. Você precisará descobrir o IP do computador na rede local. Por exemplo, usando ifconfig .


Em seguida, configure o telefone para funcionar através do servidor proxy Charles. No Android 7.0, isso é feito nas configurações de Wi-Fi pressionando longamente a rede conectada. Especifique o IP do computador e a porta 8888, o Charles padrão.



Escusado será dizer que o aplicativo Rocketbank usa TLS ao interagir com o servidor e não conseguiremos ouvir o tráfego assim. Charles suporta interceptação de tráfego com a substituição de um certificado TLS, ou seja, implementa um ataque MITM. No entanto, para isso, o dispositivo deve confiar no certificado raiz Charles.


O certificado raiz Charles é instalado quando você clica no link https://chls.pro/ssl em um dispositivo móvel com o proxy ativado. Além disso, você precisa adicionar rocketbank.ru à lista de hosts com proxy em Proxy -> Configurações de proxy SSL .



Mas isso não será suficiente, já que no Android 7.0, por padrão, os aplicativos não confiam nas autoridades de certificação do usuário. Segurança! O aplicativo deve ser compilado com a permissão apropriada. Um obstáculo? Nem uma vez. Nós descompilamos e compilamos conforme necessário.


Primeiro, obtemos o pacote de aplicativos pelo telefone. Isso pode ser feito usando o Android Debug Bridge ou o aplicativo Apk Extractor . O primeiro método no Android 7.0 não funcionou para mim e o segundo lidou com a tarefa.


Levamos o pacote ao computador e descompilamos usando o apktool .


 apktool d rocket.apk 

Você deve adicionar o arquivo de configuração de segurança de rede no caminho res / xml / network_security_config.xml. Você pode ler mais sobre o formato do arquivo de configuração aqui , mas as seguintes configurações são suficientes para nós:


 <network-security-config> <base-config> <trust-anchors> <!-- Always trust user added CAs --> <certificates src="user" /> </trust-anchors> </base-config> </network-security-config> 

Esse arquivo de configuração deve ser especificado no manifesto do aplicativo (AndroidManifest.xml na raiz) adicionando o parâmetro android: networkSecurityConfig à tag do aplicativo.


 <application android:networkSecurityConfig="@xml/network_security_config" android:allowBackup="false" ...>...</application> 

Agora compile.


 apktool b rocket 

Resta assinar o aplicativo, pois os aplicativos não assinados não estão instalados. Utilizamos para isso um programa de assinatura com um certificado de teste interno .


 java -jar sign.jar rocket.apk 

Remova o aplicativo Rocketbank original do telefone, copie o pacote modificado para o telefone e instale-o (por exemplo, através do aplicativo "Arquivos").


Agora a interceptação de tráfego em Charles deve funcionar. Abra o aplicativo Rocketbank, faça o login e procure em Charles. Aqui está, o nosso link para o recibo.



Vamos voltar ao Python e simular essa solicitação GET, não perca tempo e peça ao servidor que nos forneça dados sobre todas as operações. Bem, ou pelo menos sobre o primeiro 999999.


 token = 'c8ccb54b-09e3-4608-a5b4-7914a92c21f3206582' params = {'token': token, 'page': 1, 'per_page': 999999} 

Foi experimentalmente descoberto que o servidor confia na sessão apenas se o x-device-id correto, x-time e x-sig foram enviados junto com o token. Não sentimos muito, porque não precisamos inventar e contar nada, basta copiá-lo.


 x_device_id = 'ANDROID_C6FBB57CD433E756_899EE771-4AC5-46ED-44A1-656CE47A417B' x_time = '1529194008' x_sig = 'c486365013ddebe8b7f4599afbf73d26' headers = {'x-device-id': x_device_id, 'x-time': x_time, 'x-sig': x_sig} response = requests.get('https://rocketbank.ru/api/v5/operations/sexy_feed', params=params, headers=headers) 

Regularmente o suficiente para retirar o MCC do recibo. Revisamos as operações, lemos o recibo, executamos o cronograma regular e tudo o que precisamos em nosso bolso.


 import re regex = re.compile('MCC:</dt><.+?>(\d+)</dd>') operations = [] feed = response.json()['feed'] for item in feed: if item[0] == 'operation': operation = item[1] merchant_name = operation['merchant']['name'] receipt_url = operation['receipt_url'] cost = operation['money']['amount'] #    if cost < 0: receipt = requests.get(receipt_url) match = regex.search(receipt.text) if match is not None: mcc = match[1] operations.append((mcc, -cost, merchant_name)) print(mcc, -cost, merchant_name) else: #  MCC  ,      , #        MCC operations.append((merchant_name, -cost)) print(merchant_name, -cost) output = open("rocket.csv",'w') wr = csv.writer(output) for item in operations: wr.writerow(item) 

Talvez você possa excluir o aplicativo modificado e instalar o original de volta.


Total


Combinando dados de dois bancos, agrupando operações pela MCC usando uma Tabela Dinâmica, limpando manualmente dados de transferências e saques em dinheiro e agrupando-os em categorias semelhantes em alguns locais, obtive a seguinte imagem:



Agora, usando um serviço como o mcc-codes.ru , você pode receber cartões com maior reembolso para as categorias mais caras. E, correlacionando a quantia possível de reembolso com o custo da manutenção anual, determine se é aconselhável elaborar um cartão específico.


Qual é o benefício disso? Com minhas despesas e a seleção correta de cartões, posso economizar 10 mil rublos por ano. Vale a pena? Você decide :)

Source: https://habr.com/ru/post/pt414349/


All Articles