We obtain the statistics of expenses by MCC: Tinkoff and Roketbank


Introduction


MCC (Merchant Category Code) is a merchant category code used in bank card transactions. According to this code, the bank determines which product the customer has purchased. It depends on him, you will receive a cashback, commission or cancel the grace period.


In an age when companies make money on data collected from users, it’s a sin not to take advantage of the reverse: to use information about yourself collected by companies so that, if you don’t make money from it, then at least save.


Knowing how much money you spend on each MCC code, you can calculate which bank card will bring great benefits. Therefore, if you used Tinkoff or Rocketbank cards for a sufficient time, this article will be useful to you in order to get statistics on expenses for each MCC.


Tinkoff


Tinkoff Bank's personal account shows the MCC operations when you click on it.



So you can see a dozen operations, but if we need to collect statistics for all the time the card is used, this business should be automated. Let's try to get the data in a convenient form for software processing.


UPD: As Smasher noted, the personal account provides the ability to upload all operations in CSV or Excel format. So, under the spoiler, a description of how I did it without knowing it.



Going the hard way

This will require the development tools of the browser, and specifically - the analysis of network activity (tab Network in Google Chrome). If you enable the analyzer and after that ask your personal account to display the operations “For all time”, then we will quickly find the desired request.



You can see that the server really gave the data for all the time, and the JSON response contains the required MCCs.



For convenience, we will simulate a request for Python. I am using Jupyter Notebook .



Send a POST request to the URL https://api.tinkoff.ru/v1/grouped_requests with identical sessionid and _methods parameters and requestsData data.


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) 

If we did everything right, then typing response.text in the console will display the response body. It remains to analyze this data and save the fragments we need.


 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) 

At the output we get a table of MCC-codes, values ​​of purchases and names of stores.


Roketbank


Rocketbank shows MCC operations in the receipt. Therefore, we will need to collect references to the receipt of all transactions.



With Roketbank a little more difficult, because access to your personal account is carried out only through a mobile application. I will tell only about what earned me, and only about Android. Install the Charles analyzer on the computer and skip the traffic from the phone through it.


For this phone and computer must be connected to the same network. You will need to know the IP of the computer on the local network. For example, using ifconfig .


Next, we configure the phone to work through the proxy server Charles. In Android 7.0, this is done in the Wi-Fi settings with a long press on the connected network. Specify the computer's IP and port 8888, the default used by Charles.



It goes without saying that the Roketbank application uses TLS when interacting with the server and we simply cannot listen to the traffic. Charles supports traffic interception with TLS certificate substitution, that is, it implements a MITM attack. However, for this, the device must trust the Charles root certificate.


Charles root certificate is installed when you follow the link https://chls.pro/ssl from a mobile device with proxying enabled. In addition, you need to add rocketbank.ru to the list of proxied hosts in Proxy -> SSL Proxying Settings .



But this will not be enough, because in Android 7.0, by default, applications do not trust user certificate authorities. Security! The application must be compiled with the appropriate permission. Let? Never. We decompile and compile as we need.


First we get the application package from the phone. This can be done using the Android Debug Bridge or the Apk Extractor application. The first method did not work on Android 7.0, and the second handled the task.


We take the package to the computer and decompile with apktool .


 apktool d rocket.apk 

You need to add a network security configuration file at res / xml / network_security_config.xml. More information about the format of the configuration file can be read here , we have enough of the following settings:


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

This configuration file must be specified in the application manifest (AndroidManifest.xml in the root) by adding the android: networkSecurityConfig parameter to the application tag.


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

Now compile.


 apktool b rocket 

It remains to sign the application, since unsigned applications are not installed. We use for this program to sign with a built-in test certificate .


 java -jar sign.jar rocket.apk 

Delete the original Roketbank application from the phone, copy the modified package to the phone and install (for example, through the Files application).


Now Charles traffic interception should work. Open the Roketbank application, log in and look at Charles. Here it is, our link to the receipt.



Let's go back to Python again and simulate this GET request, but we won’t waste time on trifles and ask the server to give us data about all operations. Well, or at least about the first 999999.


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

It was experimentally found out that the server trusts the session only if the correct x-device-id , x-time and x-sig are sent along with the token. We don’t feel sorry, because you don’t have to invent anything and count, just copy it.


 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) 

For pulling the MCC from the receipt will be enough regulars. We run over the operations, read the receipt, run it through the regular season and everything we need in our pocket.


 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) 

Perhaps you can remove the modified application and set back the original one.


Total


Combining data from two banks, grouping operations by MCC using a pivot table (Pivot Table), manually cleaning the data from transfers and withdrawing cash and grouping them into similar categories in places, I got the following picture:



Now, using a service like mcc-codes.ru , you can pick up cards with an increased cashback for the most expensive categories. And, correlating the amount of possible cashback with the cost of annual maintenance, determine whether it is advisable to issue a specific card.


What is the benefit of it? With my spending and the correct selection of cards can save 10 thousand rubles a year. Is it worth it? You decide :)

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


All Articles