예제 #1
0
    def __init__(self, document, password, days=15, omit_sensitive_data=False, quiet=False, validator=SantanderValidator):
        if not quiet:
            print('[*] Santander Parser is starting...')

        self.validator = validator()

        self.account = Account(document=document, password=password)

        self.validate()
        self.account.bank = 'Santander'
        self.account.currency = 'R$'

        self.omit_sensitive_data = omit_sensitive_data
        self.quiet = quiet

        self.balance = False

        self.transaction_days = days

        webdriver.DesiredCapabilities.PHANTOMJS['phantomjs.page.settings.userAgent'] = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36'
        webdriver.DesiredCapabilities.PHANTOMJS['phantomjs.page.customHeaders.Accept-Language'] = 'pt-BR'
        webdriver.DesiredCapabilities.PHANTOMJS['phantomjs.page.customHeaders.Connection'] = 'keep-alive'

        self.session = webdriver.PhantomJS()
        self.session.implicitly_wait(10)
        self.session.set_window_size(1920, 1080)

        self.wait = WebDriverWait(self.session, 10)
예제 #2
0
    def __init__(self, card, omit_sensitive_data=False, quiet=False, dbc_username=None, dbc_password=None):
        if not quiet:
            print('[*] Ticket Parser is starting...')


        self.account = Account(None, card, account_type='card')

        self.account.currency = 'R$'

        self.omit_sensitive_data = omit_sensitive_data
        self.quiet = quiet
        self.account.currency = 'R$'
        self.account.bank = 'Ticket'

        #self.dbc_username = dbc_username
        #self.dbc_password = dbc_password

        #self.dbc_client = deathbycaptcha.SocketClient(self.dbc_username, self.dbc_password)

        self.captcha = ''
        self.token = ''



        self.session = requests.Session()
        self.session.mount(self.api_endpoint, HTTPAdapter(max_retries=32,pool_connections=50, pool_maxsize=50))
        self.session.headers.update({'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36'})
        self.session.headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
        self.session.headers.update({'Referer': 'http://www.ticket.com.br/portal/consulta-de-saldo/'})
예제 #3
0
    def __init__(self, branch, account, password, days=15, omit_sensitive_data=False, quiet=False, validator=ItauValidator):
        if not quiet:
            print('[*] Itaú Parser is starting...')

        number = account.split('-')[0] if '-' in account else account[:5]
        dac = account.split('-')[1] if '-' in account else account[-1]

        self.validator = validator()
        self.account = Account(branch=branch, number=number, password=password, dac=dac)
        self.validate()
        self.account.bank = 'Itaú'
        self.account.currency = 'R$'

        self.session = requests.Session()

        self.omit_sensitive_data = omit_sensitive_data
        self.quiet = quiet

        self.encoding = ''
        self.ticket = ''

        self.transaction_days = days

        self.holder_code = ''

        self.session.mount(self.api_endpoint, HTTPAdapter(max_retries=32, pool_connections=50, pool_maxsize=50))
        self.session.headers.update({'User-Agent': 'Apache-HttpClient/android/Nexus 5'})
        self.session.headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
        self.session.headers.update({'Cookie2': '$Version=1'})
예제 #4
0
    def __init__(self, branch, account, password, days, omit_sensitive_info=False, quiet=False):
        if not quiet:
            print('[*] Banco do Brasil Parser is starting...')

        self.account = Account(branch, account, password)

        self.account.bank = 'Banco do Brasil'
        self.account.currency = 'R$'

        self.days = days

        self.omit_sensitive_info = omit_sensitive_info
        self.quiet = quiet

        self.nick = 'NickRandom.{}'.format(randint(1000,99999))

        self.idh = ''

        self.mci = ''
        self.segmento = ''

        self.session = requests.Session()
        self.session.mount(self.api_endpoint, HTTPAdapter(max_retries=32,pool_connections=50, pool_maxsize=50))
        self.session.headers.update({'User-Agent': 'Android;Google Nexus 5 - 6.0.0 - API 23 - 1080x1920;Android;6.0;vbox86p-userdebug 6.0 MRA58K eng.buildbot.20160110.195928 test-keys;mov-android-app;6.14.0.1;en_US;cpu=0|clock=|ram=2052484 kB|espacoSDInterno=12.46 GB|isSmartphone=true|nfc=false|camera=true|cameraFrontal=true|root=true|reconhecimentoVoz=false|resolucao=1080_1776|densidade=3.0|'})
        self.session.headers.update({'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'})
예제 #5
0
    def __init__(self,
                 document,
                 password,
                 omit_sensitive_data=False,
                 quiet=False):
        if not quiet:
            print('[*] Nubank Parser is starting...')

        self.account = Account(document, None, password, account_type='card')

        self.omit_sensitive_data = omit_sensitive_data
        self.quiet = quiet
        self.account.currency = 'R$'
        self.account.bank = 'Nubank'

        self.session = requests.Session()
        self.session.mount(
            self.api_endpoint,
            HTTPAdapter(max_retries=32, pool_connections=50, pool_maxsize=50))
        self.session.headers.update({
            'User-Agent':
            'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36'
        })
        self.session.headers.update({'Content-Type': 'application/json'})
        self.session.headers.update(
            {'Referer': 'https://conta.nubank.com.br/'})
예제 #6
0
파일: itau.py 프로젝트: yurifds/bankscraper
    def __init__(self,
                 branch,
                 account,
                 password,
                 days=15,
                 omit_sensitive_data=False,
                 quiet=False,
                 validator=ItauValidator):
        if not quiet:
            print('[*] Itaú Parser is starting...')

        number = account.split('-')[0] if '-' in account else account[:5]
        dac = account.split('-')[1] if '-' in account else account[-1]

        self.validator = validator()
        self.account = Account(branch=branch,
                               number=number,
                               password=password,
                               dac=dac)
        self.validate()
        self.account.bank = 'Itaú'
        self.account.currency = 'R$'

        self.session = requests.Session()

        self.omit_sensitive_data = omit_sensitive_data
        self.quiet = quiet

        self.encoding = ''
        self.ticket = ''

        self.transaction_days = days

        self.holder_code = ''

        self.session.mount(
            self.api_endpoint,
            HTTPAdapter(max_retries=32, pool_connections=50, pool_maxsize=50))
        self.session.headers.update(
            {'User-Agent': 'Apache-HttpClient/android/Nexus 5'})
        self.session.headers.update(
            {'Content-Type': 'application/x-www-form-urlencoded'})
        self.session.headers.update({'Cookie2': '$Version=1'})
예제 #7
0
    def __init__(self, card, document, omit_sensitive_data=False, quiet=False):
        if not quiet:
            print('[*] Sodexo Parser is starting...')


        self.account = Account(document, card, account_type='card')

        self.omit_sensitive_data = omit_sensitive_data
        self.quiet = quiet
        self.account.currency = 'R$'
        self.account.bank = 'Sodexo'


        self.session = requests.Session()
        self.session.mount(self.api_endpoint, HTTPAdapter(max_retries=32,pool_connections=50, pool_maxsize=50))
        self.session.headers.update({'User-Agent': 'Apache-HttpClient/android/Nexus 5'})
        self.session.headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
예제 #8
0
    def __init__(self, branch, account, password, days=15, omit_sensitive_data=False, quiet=False):
        if not quiet:
            print('[*] Itaú Parser is starting...')

        self.account = Account(str(branch), str(account).split('-')[0], str(password), str(account).split('-')[1])
        self.account.bank = 'Itaú'
        self.account.currency = 'R$'

        self.session = requests.Session()

        self.omit_sensitive_data = omit_sensitive_data
        self.quiet = quiet

        self.encoding = ''
        self.ticket = ''


        self.transaction_days = days


        self.holder_code = ''


        self.eula_url = ''

        self.android_last_build = ''
        self.android_url = ''

        self.ios_last_build = ''
        self.ios_url = ''

        self.windowsphone_last_build = ''
        self.windowsphone_url = ''

        self.session.mount(self.api_endpoint, HTTPAdapter(max_retries=32,pool_connections=50, pool_maxsize=50))
        self.session.headers.update({'User-Agent': 'Apache-HttpClient/android/Nexus 5'})
        self.session.headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
        self.session.headers.update({'Cookie2': '$Version=1'})
예제 #9
0
class Ticket(object):

    api_endpoint = 'https://www.app.ticket.com.br/PMobileServer/Primeth'

    captcha_url = 'http://www.ticket.com.br/portal/stickyImg'
    login_url = 'http://www.ticket.com.br/portal/portalticket/dpages/service/captcha/getConsultCard.jsp'
    transactions_url = 'http://www.ticket.com.br/portal-web/consult-card/release/json'


    def __init__(self, card, omit_sensitive_data=False, quiet=False, dbc_username=None, dbc_password=None):
        if not quiet:
            print('[*] Ticket Parser is starting...')


        self.account = Account(None, card, account_type='card')

        self.account.currency = 'R$'

        self.omit_sensitive_data = omit_sensitive_data
        self.quiet = quiet
        self.account.currency = 'R$'
        self.account.bank = 'Ticket'

        #self.dbc_username = dbc_username
        #self.dbc_password = dbc_password

        #self.dbc_client = deathbycaptcha.SocketClient(self.dbc_username, self.dbc_password)

        self.captcha = ''
        self.token = ''



        self.session = requests.Session()
        self.session.mount(self.api_endpoint, HTTPAdapter(max_retries=32,pool_connections=50, pool_maxsize=50))
        self.session.headers.update({'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36'})
        self.session.headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
        self.session.headers.update({'Referer': 'http://www.ticket.com.br/portal/consulta-de-saldo/'})


    def get_unix_timestamp(self):
        return int((datetime.now(timezone.utc) + timedelta(days=3)).timestamp() * 1e3)

    def login(self):

        # We can just pretend to solve the captcha
        unixtm = self.get_unix_timestamp()
        path = '/tmp/.bankscraper_captcha_{}'.format(os.getpid())
        r = self.session.get('{}?{}'.format(self.captcha_url, unixtm, stream=True))
        if r.status_code == 200:
            with open(path, 'wb') as f:
                for chunk in r:
                    f.write(chunk)

        captcha = '123456'

        if captcha:
            self.captcha = captcha

            r = self.session.post('{}?answer={}&card={}&d={}'.format(self.login_url, self.captcha, self.account.card, unixtm))

            self.token = r.json()['token']

            if not self.quiet:
                print('[*] Captcha decoded: {}'.format(self.captcha))
                print('[*] Token: {}'.format(self.token))

            return self.token



    def get_balance(self):
        payload = {
            'card': self.account.card,
            'answer': self.captcha,
            'token': self.token,
        }


        r = self.session.post(self.transactions_url, data=payload)

        body = r.json()

        self.account.balance = Decimal(body['card']['balance']['value'].replace(',', '.'))

        print(self.account.get_balance())

        return self.account.get_balance()

    def get_transactions(self):
        if not self.quiet:
            print('[*] Getting transactions...')
            print()

        payload = {
            'card': self.account.card,
            'answer': self.captcha,
            'token': self.token,
        }


        r = self.session.post(self.transactions_url, data=payload)

        body = r.json()

        self.account.balance = Decimal(body['card']['balance']['value'].replace(',', '.'))


        self.parse_transactions(body['card']['release'])
        for trans in self.account.transactions:
            trans.print_info()

        return self.account.transactions


    def parse_transactions(self, transactions):
        tlist = []

        for trans in transactions:
            try:
                t = Transaction(trans['description'])
                t.currency = 'R$'
                t.date = datetime.strptime(trans['date'], '%d/%m/%Y').date()
                t.value = Decimal(trans['value'].split()[-1].replace('.', '').replace(',', '.'))
                t.sign = '-' if trans['description'] != 'DISPONIB. DE CREDITO' else '+'
                t.raw = trans
                self.account.transactions.append(t)
            except:
                traceback.print_exc()
                continue

        return self.account.transactions
예제 #10
0
class Itau(object):

    app_id = 'kspf'
    app_version = '4.1.19'
    platform = 'android'
    platform_version = '6.0.1'
    platform_extra_version = '5.6.GA_v201508271451_r3'
    platform_model = 'Nexus 5'

    device_id = 12345678
    user_id = 1234

    api_endpoint = 'https://kms.itau.com.br/middleware/MWServlet'


    device_session_template = 'Modelo: {platform_model}|Operadora:|VersaoSO:{platform_version}|appIdCore:'

    def __init__(self, branch, account, password, days=15, omit_sensitive_data=False, quiet=False):
        if not quiet:
            print('[*] Itaú Parser is starting...')

        self.account = Account(str(branch), str(account).split('-')[0], str(password), str(account).split('-')[1])
        self.account.bank = 'Itaú'
        self.account.currency = 'R$'

        self.session = requests.Session()

        self.omit_sensitive_data = omit_sensitive_data
        self.quiet = quiet

        self.encoding = ''
        self.ticket = ''


        self.transaction_days = days


        self.holder_code = ''


        self.eula_url = ''

        self.android_last_build = ''
        self.android_url = ''

        self.ios_last_build = ''
        self.ios_url = ''

        self.windowsphone_last_build = ''
        self.windowsphone_url = ''

        self.session.mount(self.api_endpoint, HTTPAdapter(max_retries=32,pool_connections=50, pool_maxsize=50))
        self.session.headers.update({'User-Agent': 'Apache-HttpClient/android/Nexus 5'})
        self.session.headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
        self.session.headers.update({'Cookie2': '$Version=1'})


    def json_recursive_loads(self, obj):
        obj = json.loads(obj)

        for k in obj.keys():       
            if type(obj[k]) == type(''):
                try:
                    obj[k] = json.loads(obj[k])
                except:
                    pass
        
        for k in obj.keys():       
            if type(obj[k]) == type({}):
                for kk in obj[k].keys():
                    if type(obj[k][kk]) == type(''):
                        try:
                            obj[k][kk] = json.loads(obj[k][kk])
                        except:
                            pass

        return obj


    def generate_timestamps(self):
        now1 = self.format_date_pd(datetime.now())
        sleep(0.2)
        now2 = self.format_date_pd(datetime.now())
        sleep(0.2)
        now3 = self.format_date_pd(datetime.now())
        sleep(0.2)
        now4 = self.format_date_pd(datetime.now())

        return {'d1': now1, 'd2': now2, 'd3': now3, 'd4': now4}



    def build_device_session(self, extra):

        msg = self.device_session_template.format(platform_model=self.platform_model, platform_version=self.platform_version)

        msg = msg + '|' + extra

        return msg


    def format_date_pd(self, dtobj):

        return dtobj.strftime('%-m/%-d/%Y %-H-%-M-%-S-%f')[:-3]

    def post(self, payload):
        return self.session.post(self.api_endpoint, data=payload)



    def login(self):
        if not self.quiet:
            print('[*] Logging in to {} {}-{}'.format(self.account.branch,self.account.number,self.account.dac))

        payload = {
            'Guid': '7C9C0508-6EFD-47B6-9DBA-5E4B1205D560',
            'DeviceId': self.device_id,
            'UserId': self.user_id,
            'Params': 'MOBILECORE_JSON_SMART_ITAUPF',
            'platform': 'android',
            'appID': self.app_id,
            'appver': self.app_version,
            'IPCliente': '',
            'Ticket': '',
            'channel': 'rc',
            'serviceID': 'srvJCoreRuntime',
            'cacheid': '',
            'platformver': self.platform_extra_version,
            'DadosSessaoDevice': 'Modelo:Nexus 5|Operadora:|VersaoSO:6.0.1|appIdCore:'
        }


        r = self.post(payload)


        obj = self.json_recursive_loads(r.content.decode())


        if obj['opstatus'] == 0:
            if not self.quiet:
                print('[+] Login successful!')
        else:
            raise GeneralException('Something went wrong...', request=r)


        self.account.app = App('Itaú')

        self.account.app.eula_url = obj['Dados']['home_config']['link_termos_uso']


        for o in obj['Dados']['app_config']['plataforma']:
            if o['nome'] == 'android':
                self.account.app.platform['android']['version'] = o['build_number_atual']
                self.account.app.platform['android']['url'] = o['url_loja:']
            elif o['nome'] == 'iphone':
                self.account.app.platform['ios']['version'] = o['build_number_atual']
                self.account.app.platform['ios']['url'] = o['url_loja:']
            elif o['nome'] == 'windowsphone':
                self.account.app.platform['windowsphone']['version'] = o['build_number_8']
                self.account.app.platform['windowsphone']['url']= o['url_loja:']


        if not self.quiet:
            print()
            self.account.app.print_info()
            print()

        now = datetime.now()

        if not self.quiet:
            print('[*] Getting account information...')

        t = self.generate_timestamps()
        payload = {
            'DeviceId': self.device_id,
            'UserId': self.user_id,
            'UA': 'AppItauSmartPF:R1;{version};{platform};{platform_version};{platform_model};{{F001;}}'.format(version=self.app_version, platform=self.platform, platform_version=self.platform_version,platform_model=self.platform_model),
            'Agencia': self.account.branch,
            'Dac':  self.account.dac,
            'platform': self.platform,
            'Tecnologia': 4,
            'Sv': '',
            'appID': self.app_id,
            'appver': self.app_version,
            'ListaMenu': '',
            'Conta': self.account.number,
            'channel': 'rc',
            'serviceID': 'srvJLogin',
            'cacheid': '',
            'Senha': self.account.password,
            'platformver': self.platform_extra_version,
            'DadosSessaoDevice': self.build_device_session('root:X|PD:{d1},{d2}H'.format(**t))
        }

        r = self.post(payload)

        obj = self.json_recursive_loads(r.content.decode())

        if obj['opstatus'] == 0:
            pass
        else:
            raise GeneralException('Something went wrong...', request=r)

        try:

            if int(obj['Dados']['RESPOSTA']['DADOS']['CODIGO']) == 31 :
                raise AnotherActiveSessionException(obj['Dados']['RESPOSTA']['DADOS']['MENSAGEM'])
            elif int(obj['Dados']['RESPOSTA']['DADOS']['CODIGO']) == 30:
                raise MaintenanceException(obj['Dados']['RESPOSTA']['DADOS']['MENSAGEM'])
        except KeyError:
            pass


        self.encoding = obj['Dados']['?xml']['@encoding']

        self.account.owner = Owner(obj['Dados']['RESPOSTA']['DADOS']['NOME_CORRENTISTA'].strip().title())
        self.account.segment = obj['Dados']['RESPOSTA']['DADOS']['SEGMENTO'].strip()
        self.account.type = 'Física' if obj['Dados']['RESPOSTA']['DADOS']['PESSOA'] == 'F' else 'Jurídica'
        self.account.owner.document = obj['Dados']['RESPOSTA']['DADOS']['CPF_CNPJ_CLIENTE'].strip()
        self.account.owner.birthday = datetime.strptime(obj['Dados']['RESPOSTA']['DADOS']['DT8_GB07'], '%d%m%Y')

        self.holder_code = obj['Dados']['RESPOSTA']['DADOS']['TITULARIDADE']
        self.ticket = obj['Ticket']
        

        if not self.quiet:
            print()
            self.account.print_info()
            print()
            self.account.owner.print_info()
            print()


    def logout(self):

        if not self.quiet:
            print('[*] Logging out...')

        t = self.generate_timestamps()
        payload = {
            'DeviceId': self.device_id,
            'UserId': self.user_id,
            'UA': 'AppItauSmartPF:R1;{version};{platform};{platform_version};{platform_model};{{F001;}}'.format(version=self.app_version, platform=self.platform, platform_version=self.platform_version,platform_model=self.platform_model),
            'ServiceName': 'SAIR',
            'Sv': '', 
            'appID': self.app_id,
            'appver': self.app_version,
            'IPCliente': '',
            'Ticket': self.ticket,
            'channel': 'rc',
            'serviceID': 'srvJGenerico',
            'platformver': self.platform_extra_version,
            'DadosSessaoDevice': 'PD:{d1},{d2},{d3},{d4}|AGC_SAIR:{ag}{ac}{dac}'.format(ag=self.account.branch,ac=self.account.number,dac=self.account.dac,**t),
            'Lista': ''

        }

        r = self.post(payload)

        obj = self.json_recursive_loads(r.content.decode())

        if obj['opstatus'] == 0:
            if not self.quiet:
                print('[+] Logged out succesfully!')
        else:
            raise GeneralException('Something went wrong...', request=r)


    def post_login_warmup(self):
        if not self.quiet:
            print('[*] Warming up...')
        t = self.generate_timestamps()
        payload = {
            'DeviceId': self.device_id,
            'UserId': self.user_id,
            'UA': 'AppItauSmartPF:R1;{version};{platform};{platform_version};{platform_model};{{F001;}}'.format(version=self.app_version, platform=self.platform, platform_version=self.platform_version,platform_model=self.platform_model),
            'ServiceName': 'CSTA_POR_TIPO',
            'Sv': '', 
            'appID': self.app_id,
            'appver': self.app_version,
            'IPCliente': '',
            'Ticket': self.ticket,
            'channel': 'rc',
            'serviceID': 'srvJGenerico',
            'platformver': self.platform_extra_version,
            'DadosSessaoDevice': 'PD:{d1},{d2},{d3},{d4}|AGC_CSTA_PORT_TIPO:{ag}{ac}{dac}'.format(ag=self.account.branch,ac=self.account.number,dac=self.account.dac,**t),
            'Lista': 'EMHUOYKIRBVPRCMNEWZ60XJPRNY|PF |352136067883617|00012'

        }

        r = self.post(payload)

        obj = self.json_recursive_loads(r.content.decode())

        if obj['opstatus'] == 0:
            pass
        else:
            raise GeneralException('Something went wrong...')


        payload = {
            'appID': self.app_id,
            'appver': self.app_version,
            'Ticket': self.ticket,
            'channel': 'rc',
            'serviceID': 'srvJMenu',
            'platformver': self.platform_extra_version,

        }

        r = self.post(payload)

        obj = self.json_recursive_loads(r.content.decode())

        if obj['opstatus'] == 0:
            pass
        else:
            raise GeneralException('Something went wrong...', request=r)



        payload = {
            'Guid': '7C9C0508-6EFD-47B6-9DBA-5E4B1205D560',
            'DeviceId': self.device_id,
            'UserId': self.user_id,
            'Params': self.ticket,
            'appID': self.app_id,
            'appver': self.app_version,
            'IPCliente': '',
            'Ticket': self.ticket,
            'channel': 'rc',
            'serviceID': 'srvJCoreRuntime',
            'platformver': self.platform_extra_version,
            'DadosSessaoDevice': self.build_device_session('root:X')

        }

        r = self.post(payload)

        obj = self.json_recursive_loads(r.content.decode())

        if obj['opstatus'] == 0:
            pass
        else:
            raise GeneralException('Something went wrong...', request=r)

        payload = {
            'Guid': '7C9C0508-6EFD-47B6-9DBA-5E4B1205D560',
            'DeviceId': self.device_id,
            'UserId': self.user_id,
            'Params': 'SMARTPHONE_PF_TOKEN_WEBVIEW',
            'appID': self.app_id,
            'appver': self.app_version,
            'IPCliente': '',
            'Ticket': self.ticket,
            'channel': 'rc',
            'serviceID': 'srvJGenerico',
            'platformver': self.platform_extra_version,
            'DadosSessaoDevice': self.build_device_session('root:X')

        }

        r = self.post(payload)

        obj = self.json_recursive_loads(r.content.decode())

        if obj['opstatus'] == 0:
            pass
        else:
            raise GeneralException('Something went wrong...', request=r)



        payload = {
            'HolderCodeType': 1,
            'AccountNumber': self.account.number,
            'Dac': self.account.dac,
            'Type': 0,
            'BranchNumber': self.account.branch,
            'HolderCode': self.holder_code,
            'appID': self.app_id,
            'appver': self.app_version,
            'IPCliente': '',
            'Ticket': self.ticket,
            'channel': 'rc',
            'serviceID': 'srvJGetUserInfo',
            'platformver': self.platform_extra_version,

        }

        r = self.post(payload)

        obj = self.json_recursive_loads(r.content.decode())

        if obj['opstatus'] == 0:
            pass
        else:
            raise GeneralException('Something went wrong...', request=r)


    def get_balance(self):
        if not self.quiet:
            print('[*] Getting transactions...')
        t = self.generate_timestamps()
        payload = {
            'DeviceId': self.device_id,
            'UserId': self.user_id,
            'UA': 'AppItauSmartPF:R1;{version};{platform};{platform_version};{platform_model};{{F001;}}'.format(version=self.app_version, platform=self.platform, platform_version=self.platform_version,platform_model=self.platform_model),
            'ServiceName': 'EXTRATO',
            'Sv': '', 
            'appID': self.app_id,
            'appver': self.app_version,
            'IPCliente': '',
            'Ticket': self.ticket,
            'channel': 'rc',
            'cacheid': '',
            'platform': self.platform,
            'serviceID': 'srvJGenerico',
            'platformver': self.platform_extra_version,
            'DadosSessaoDevice': 'PD:{d1},{d2},{d3},{d4}|AGC_EXTRATO:{ag}{ac}{dac}'.format(ag=self.account.branch,ac=self.account.number,dac=self.account.dac,**t),
            'Lista': '{}|V|CC|E|1'.format(self.transaction_days)

        }


        r = self.post(payload)

        obj = self.json_recursive_loads(r.content.decode())

        if obj['opstatus'] == 0:
            pass
        else:
            raise GeneralException('Something went wrong...', request=r)


        for o in obj['Dados']['RESPOSTA']['DADOS']['DADOSEXTRATO']['SALDORESUMIDO']['ITEM']:
            if o['NOME'] == 'SALDODISPSAQUERESUMO':
                self.account.balance = Decimal(o['VALOR'].replace('.', '').replace(',', '.'))
                self.account.sign = '-' if o['SINAL'] == 'D' else '+'
            elif o['NOME'] == 'LIMITELISRESUMO':
                self.account.overdraft = Decimal(o['VALOR'].replace('.', '').replace(',', '.'))

        print(self.account.get_balance())

        return self.account.get_balance()


    def get_transactions(self):
        if not self.quiet:
            print('[*] Getting transactions...')

        t = self.generate_timestamps()
        payload = {
            'DeviceId': self.device_id,
            'UserId': self.user_id,
            'UA': 'AppItauSmartPF:R1;{version};{platform};{platform_version};{platform_model};{{F001;}}'.format(version=self.app_version, platform=self.platform, platform_version=self.platform_version,platform_model=self.platform_model),
            'ServiceName': 'EXTRATO',
            'Sv': '', 
            'appID': self.app_id,
            'appver': self.app_version,
            'IPCliente': '',
            'Ticket': self.ticket,
            'channel': 'rc',
            'cacheid': '',
            'platform': self.platform,
            'serviceID': 'srvJGenerico',
            'platformver': self.platform_extra_version,
            'DadosSessaoDevice': 'PD:{d1},{d2},{d3},{d4}|AGC_EXTRATO:{ag}{ac}{dac}'.format(ag=self.account.branch,ac=self.account.number,dac=self.account.dac, **t),
            'Lista': '{}|V|CC|E|1'.format(self.transaction_days)

        }


        r = self.post(payload)

        obj = self.json_recursive_loads(r.content.decode())

        if obj['opstatus'] == 0:
            pass
        else:
            raise GeneralException('Something went wrong...', request=r)

        self.parse_transactions(obj['Dados']['RESPOSTA']['DADOS']['DADOSEXTRATO']['EXTRATO']['MOVIMENT'])

        
        for transaction in self.account.transactions:
            transaction.print_info()

        return self.account.transactions


    def parse_transactions(self, transactions):
        tlist = []

        for trans in transactions:
            try:
                if self.omit_sensitive_data:
                    if trans['HISTOR'] not in ['SALDO', 'S A L D O'] and 'REMUNERACAO' not in trans['HISTOR'] and 'SALDO' not in trans['HISTOR'] and 'SDO CTA' not in trans['HISTOR']:
                        t = Transaction(trans['HISTOR'])
                        t.value = Decimal(trans['VAL2'].replace('.', '').replace(',', '.'))
                        t.sign = '-' if trans['DC2'] == 'D' else '+'
                        t.date = self.parse_date(trans['DT8']).date()
                        t.currency = 'R$'
                        t.raw = trans

                        self.account.transactions.append(t)
                else:
                    t = Transaction(trans['HISTOR'])
                    t.value = Decimal(trans['VAL2'].replace('.', '').replace(',', '.'))
                    t.sign = '-' if trans['DC2'] == 'D' else '+'
                    t.date = self.parse_date(trans['DT8']).date()
                    t.currency = 'R$'
                    t.raw = trans
                    self.account.transactions.append(t)
            except:
                traceback.print_exc()
                pass

        return self.account.transactions


    def parse_date(self, d):
        day = d.split('/')[0]
        month = d.split('/')[1]
        year = date.today().year

        if int(month) > date.today().month:
            year = date.today().year - 1

        d = '{}/{}/{}'.format(day, month, year)

        return datetime.strptime(d, '%d/%m/%Y')
예제 #11
0
class Sodexo(object):

    api_endpoint = 'https://www.app.sodexo.com.br/PMobileServer/Primeth'


    def __init__(self, card, document, omit_sensitive_data=False, quiet=False):
        if not quiet:
            print('[*] Sodexo Parser is starting...')


        self.account = Account(document, card, account_type='card')

        self.omit_sensitive_data = omit_sensitive_data
        self.quiet = quiet
        self.account.currency = 'R$'
        self.account.bank = 'Sodexo'


        self.session = requests.Session()
        self.session.mount(self.api_endpoint, HTTPAdapter(max_retries=32,pool_connections=50, pool_maxsize=50))
        self.session.headers.update({'User-Agent': 'Apache-HttpClient/android/Nexus 5'})
        self.session.headers.update({'Content-Type': 'application/x-www-form-urlencoded'})

    
    def get_balance(self):
        payload = {
            'th': 'thsaldo',
            'cardNumber': self.account.card,
            'document': self.account.document
        }


        r = self.session.post(self.api_endpoint, data=payload)

        body = r.json()

        self.account.service_name = body['serviceName']
        self.account.status = body['cardStatus']
        self.account.company = body['companyName']
        self.account.owner = Owner(body['name'])


        self.account.balance = Decimal(body['balanceAmount'].split()[-1].replace('.', '').replace(',', '.'))



        if not self.quiet:
            print()
            self.account.print_info()
            print()

        print(self.account.get_balance())

        return self.account.get_balance()

    def get_transactions(self):
        if not self.quiet:
            print('[*] Getting transactions...')

        payload = {
            'th': 'thsaldo',
            'cardNumber': self.account.card,
            'document': self.account.document
        }


        r = self.session.post(self.api_endpoint, data=payload)

        body = r.json()

        self.account.service_name = body['serviceName']
        self.account.status = body['cardStatus']
        self.account.company = body['companyName']
        self.account.owner = Owner(body['name'])


        self.account.balance = body['balanceAmount']



        if not self.quiet:
            print()
            self.account.print_info()
            print()


        self.parse_transactions(body['transactions'])
        for trans in self.account.transactions:
            trans.print_info()

        return self.account.transactions


    def parse_transactions(self, transactions):
        tlist = []

        for trans in transactions:
            try:
                t = Transaction(trans['history'])
                t.id = trans['authorizationNumber']
                t.currency = 'R$'
                t.date = datetime.strptime(trans['date'], '%d/%m/%Y').date()
                t.value = Decimal(trans['value'].split()[-1].replace('.', '').replace(',', '.'))
                t.sign = '-' if trans['type'].endswith('bito') else '+'
                t.raw = trans
                self.account.transactions.append(t)
            except:
                traceback.print_exc()
                continue

        return self.account.transactions
예제 #12
0
class Santander(BankScraper):

    api_endpoint = 'https://www.santandernet.com.br/'

    first_page_url = 'https://www.santander.com.br/'

    logout_url_1 = 'https://www.santandernet.com.br/IBPF_Logout.asp'
    logout_url_2 = 'https://www.santandernet.com.br/logout.asp'
    login_url1 = 'https://www.santandernet.com.br/'
    login_url2 = 'https://www.santandernet.com.br/IBPF/NMSDLoginAsIs.asp'

    def __init__(self, document, password, days=15, omit_sensitive_data=False, quiet=False, validator=SantanderValidator):
        if not quiet:
            print('[*] Santander Parser is starting...')

        self.validator = validator()

        self.account = Account(document=document, password=password)

        self.validate()
        self.account.bank = 'Santander'
        self.account.currency = 'R$'

        self.omit_sensitive_data = omit_sensitive_data
        self.quiet = quiet

        self.balance = False

        self.transaction_days = days

        webdriver.DesiredCapabilities.PHANTOMJS['phantomjs.page.settings.userAgent'] = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36'
        webdriver.DesiredCapabilities.PHANTOMJS['phantomjs.page.customHeaders.Accept-Language'] = 'pt-BR'
        webdriver.DesiredCapabilities.PHANTOMJS['phantomjs.page.customHeaders.Connection'] = 'keep-alive'

        self.session = webdriver.PhantomJS()
        self.session.implicitly_wait(10)
        self.session.set_window_size(1920, 1080)

        self.wait = WebDriverWait(self.session, 10)

    def login(self):
        if not self.quiet:
            print('[*] Logging in as {}'.format(self.account.document))

        try:
            self.session.get(self.first_page_url)

            elem = self.wait.until(EC.visibility_of_element_located((By.NAME, 'txtCPF')))
            elem.send_keys(self.account.document)
            elem.send_keys(Keys.ENTER)

            sleep(3)

            self.session.switch_to.frame(self.wait.until(EC.visibility_of_element_located((By.NAME, 'Principal'))))
            self.session.switch_to.frame(self.wait.until(EC.visibility_of_element_located((By.NAME, 'MainFrame'))))

            if 'iframeContrato' in self.session.page_source:
                print('[-] You need to manually accept an usage agreement')
                exit(1)

            elem = self.wait.until(EC.visibility_of_element_located((By.ID, 'txtSenha')))
            elem.send_keys(self.account.password)
            elem.send_keys(Keys.ENTER)

            self.session.switch_to.default_content()
            self.session.switch_to.frame(self.wait.until(EC.visibility_of_element_located((By.NAME, 'Principal'))))
            self.session.switch_to.frame(self.wait.until(EC.visibility_of_element_located((By.NAME, 'Corpo'))))

            ola = self.session.find_element_by_id('ola')

            soup = bs(ola.get_attribute('innerHTML'))

            table = soup.find('table')

            self.account.owner = Owner(table.find_all('td')[0].find('strong').text.strip())
            self.account.owner.document = self.account.document

            self.account.branch = table.find_all('td')[1].text.split()[1]
            self.account.number = ''.join(table.find_all('td')[1].text.split()[3].split('.')[:2])
            self.account.dac = table.find_all('td')[1].text.split()[3].split('.')[-1]

            self.account.print_info()
            self.account.owner.print_info()
        except UnexpectedAlertPresentException:
            print('[-] Login failed, invalid credentials')
            exit(1)
        except Exception:
            traceback.print_exc()
            self.session.save_screenshot('/tmp/screenie.png')
            exit(1)

    def logout(self):

        self.session.switch_to.default_content()

        self.session.get(self.logout_url_1)
        self.session.get(self.logout_url_2)

    def get_balance(self):
        # All on the same page
        self.balance = True
        self.get_transactions()

    def get_transactions(self):
        if not self.quiet:
            print('[*] Getting transactions...')

        self.session.switch_to.frame(self.session.find_element_by_name('iframePainel'))

        elem = self.session.find_element_by_id('extrato')

        select = Select(elem.find_element_by_name('cboSelectPeriodoExtrato'))

        select.select_by_value(self.transaction_days)

        elem.find_element_by_class_name('botao').click()

        self.session.switch_to.default_content()
        self.session.switch_to.frame(self.wait.until(EC.visibility_of_element_located((By.NAME, 'Principal'))))
        self.session.switch_to.frame(self.wait.until(EC.visibility_of_element_located((By.NAME, 'Corpo'))))
        self.session.switch_to.frame(self.wait.until(EC.visibility_of_element_located((By.NAME, 'iframePrinc'))))
        self.session.switch_to.frame(self.wait.until(EC.visibility_of_element_located((By.ID, 'extrato'))))

        elem = self.session.find_elements_by_class_name('lista')

        soup = bs(elem[0].get_attribute('innerHTML'))

        if not self.balance:
            transactions = self.parse_transactions(soup.find_all('tr'))

            if not self.quiet:
                for trans in transactions:
                    trans.print_info()

        soup = bs(elem[1].get_attribute('innerHTML'))

        for tr in soup.find_all('tr'):
            if tr.find_all('td')[0].text.strip() == 'A - Saldo de ContaMax':
                self.account.balance = Decimal(tr.find_all('td')[1].text.strip().replace('-', '').replace('.', '').replace(',', '.'))
                self.account.sign = '-' if '-' in tr.find_all('td')[1].text.strip() else '+'
            elif tr.find_all('td')[0].text.strip().startswith('D -'):
                self.account.overdraft = Decimal(tr.find_all('td')[1].text.strip().replace('-', '').replace('.', '').replace(',', '.'))

        self.session.switch_to.default_content()
        self.session.switch_to.frame(self.wait.until(EC.visibility_of_element_located((By.NAME, 'Principal'))))
        self.session.switch_to.frame(self.wait.until(EC.visibility_of_element_located((By.NAME, 'Corpo'))))
        self.session.switch_to.frame(self.wait.until(EC.visibility_of_element_located((By.ID, 'ifr_sal'))))

        elem = self.session.find_element_by_id('tblSaldos')

        soup = bs(elem.get_attribute('innerHTML'))

        t = soup.find('div', {'id': 'CPVendedora'})

        self.account.personal_credit = Decimal(t.find_all('td')[1].text.strip().replace('-', '').replace('.', '').replace(',', '.'))

    def parse_transactions(self, transactions):

        for tr in transactions:
            if tr.find('th'):
                continue
            description = tr.find_all('td')[2].text.strip()
            if description.startswith('SALDO'):
                continue
            t = Transaction(description)
            t.date = datetime.strptime(tr.find_all('td')[0].text.strip(), '%d/%m/%Y')
            t.id = tr.find_all('td')[3].text.strip()

            v = tr.find_all('td')[5].text.strip()

            t.sign = '-' if '-' in v else '+'
            t.value = Decimal(v.replace('-', '').replace('.', '').replace(',', '.'))

            self.account.transactions.append(t)

        return self.account.transactions
예제 #13
0
class BB(BankScraper):

    api_endpoint = 'https://mobi.bb.com.br/mov-centralizador/'
    idDispositivo = '000000000000000'
    ida = '00000000000000000000000000000000'

    hash_url = 'https://mobi.bb.com.br/mov-centralizador/hash'
    login_url = 'https://mobi.bb.com.br/mov-centralizador/servico/ServicoLogin/login'
    balance_url = 'https://mobi.bb.com.br/mov-centralizador/servico/ServicoSaldo/saldo'
    transactions_url = 'https://mobi.bb.com.br/mov-centralizador/tela/ExtratoDeContaCorrente/extrato'


    post_login_warmup_url1 = 'https://mobi.bb.com.br/mov-centralizador/servico/ServicoVersionamento/servicosVersionados'
    post_login_warmup_url2 = 'https://mobi.bb.com.br/mov-centralizador/servico/ServicoVersaoCentralizador/versaoDaAplicacaoWeb'
    post_login_warmup_url3 = 'https://mobi.bb.com.br/mov-centralizador/servico/ServicoMenuPersonalizado/menuPersonalizado'
    post_login_warmup_url4 = 'https://mobi.bb.com.br/mov-centralizador/servico/ServicoMenuTransacoesFavoritas/menuTransacoesFavoritas'





    def __init__(self, branch, account, password, days, omit_sensitive_info=False, quiet=False):
        if not quiet:
            print('[*] Banco do Brasil Parser is starting...')

        self.account = Account(branch, account, password)

        self.account.bank = 'Banco do Brasil'
        self.account.currency = 'R$'

        self.days = days

        self.omit_sensitive_info = omit_sensitive_info
        self.quiet = quiet

        self.nick = 'NickRandom.{}'.format(randint(1000,99999))

        self.idh = ''

        self.mci = ''
        self.segmento = ''

        self.session = requests.Session()
        self.session.mount(self.api_endpoint, HTTPAdapter(max_retries=32,pool_connections=50, pool_maxsize=50))
        self.session.headers.update({'User-Agent': 'Android;Google Nexus 5 - 6.0.0 - API 23 - 1080x1920;Android;6.0;vbox86p-userdebug 6.0 MRA58K eng.buildbot.20160110.195928 test-keys;mov-android-app;6.14.0.1;en_US;cpu=0|clock=|ram=2052484 kB|espacoSDInterno=12.46 GB|isSmartphone=true|nfc=false|camera=true|cameraFrontal=true|root=true|reconhecimentoVoz=false|resolucao=1080_1776|densidade=3.0|'})
        self.session.headers.update({'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'})





    def login(self):
        payload = {
            'hash': '',
            'idh': '',
            'id': self.ida,
            'idDispositivo': self.idDispositivo,
            'apelido': self.nick
        }


        r = self.session.post(self.hash_url, data=payload)

        self.idh = r.content


        payload = {
            'idh': self.idh,
            'senhaConta': self.account.password,
            'apelido': self.nick,
            'dependenciaOrigem': self.account.branch,
            'numeroContratoOrigem': self.account.number,
            'idRegistroNotificacao': '',
            'idDispositivo': self.idDispositivo,
            'titularidade': 1
        }


        r = self.session.post(self.login_url, data=payload)

        j = r.json()

        self.mci = j['login']['mci']
        self.account.type = j['login']['segmento']
        self.account.owner = Owner(j['login']['nomeCliente'])

        if not self.quiet:
            print()
            self.account.print_info()
            self.account.owner.print_info()
            print()



    def post_login_warmup(self):
        payload = {
            'servico/ServicoVersionamento/servicosVersionados:': '',
            'idh': self.idh,
            'idDispositivo': self.idDispositivo,
            'apelido': self.nick
        }

        for url in [post_login_warmup_url1, post_login_warmup_url2, post_login_warmup_url3, post_login_warmup_url4]:
            self.session.post(url, data=payload)


    def get_balance(self):
        payload = {
            'servico/ServicoSaldo/saldo': '',
            'idh': self.idh, 
            'idDispositivo': self.idDispositivo,
            'apelido': self.nick
        }


        r = self.session.post(self.balance_url, data=payload)

        j = r.json()

        jr = j['servicoSaldo']['saldo']

        self.account.balance = Decimal(jr.split()[0].replace('.', '').replace(',', '.')) * -1 if jr.split()[-1] == 'D' else float(jr.split()[0].replace('.', '').replace(',', '.'))

        print(self.account.get_balance())


    def get_transactions(self):
        payload = {
            'abrangencia': 8,
            'idh': self.idh, 
            'idDispositivo': self.idDispositivo,
            'apelido': self.nick
        }


        r = self.session.post(self.transactions_url, data=payload)

        j = r.json()

        jr = j['conteiner']['telas'][0]['sessoes']

        for s in jr:
            if s['TIPO'] == 'sessao' and s.get('cabecalho'):
                if s['cabecalho'].startswith('M') and 'ncia:' in s['cabecalho']:
                    month = s['cabecalho'].split()[-3:]

                    for tt in s['celulas']:
                        if tt['TIPO'] == 'celula':
                            if len(tt['componentes']) == 3 and tt['componentes'][0]['componentes'][0]['texto'] != 'Dia':
                                t = Transaction(tt['componentes'][1]['componentes'][0]['texto'])
                                t.date = self.parse_date(tt['componentes'][0]['componentes'][0]['texto'], month[0], month[2]).date()
                                t.value = Decimal(tt['componentes'][2]['componentes'][0]['texto'].split()[0].replace('.', '').replace(',', '.'))
                                t.sign = '-' if tt['componentes'][2]['componentes'][0]['texto'].split()[-1] == 'D' else '+'
                                t.currency = 'R$'
                                t.raw = tt['componentes']
                                self.account.transactions.append(t)
                            else:
                                continue
                elif s['cabecalho'].startswith('Informa') and s['cabecalho'].endswith('es adicionais'):
                    for tt in s['celulas']:
                        if tt['TIPO'] == 'celula':
                            print(tt['componentes'][0]['componentes'][0]['texto'])
                            if tt['componentes'][0]['componentes'][0]['texto'] == 'Juros':
                                self.account.interest = Decimal(tt['componentes'][1]['componentes'][0]['texto'].split()[-1].replace('.', '').replace(',', '.'))


        for trans in self.account.transactions:
            trans.print_info()

        return self.account.transactions

    def parse_date(self, day, month, year):

        m2n = {
            'Janeiro': 1,
            'Fevereiro': 2,
            'Marco': 3,
            'Março': 3,
            'Abril': 4,
            'Maio': 5,
            'Junho': 6,
            'Julho': 7,
            'Agosto': 8,
            'Setembro': 9,
            'Outubro': 10,
            'Novembro': 11,
            'Dezembro': 12
        }


        return datetime.strptime('{}/{}/{}'.format(day, m2n[month], year), '%d/%m/%Y')