bankscrap-openbank 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/bankscrap/openbank/account.rb +16 -47
- data/lib/bankscrap/openbank/bank.rb +63 -90
- data/lib/bankscrap/openbank/card.rb +22 -44
- data/lib/bankscrap/openbank/utils.rb +18 -7
- data/lib/bankscrap/openbank/version.rb +1 -1
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 7ecc804e009d7b76359f51dddb7fcf92bd1cf48f
         | 
| 4 | 
            +
              data.tar.gz: 878ed70101cccb3a52f9a76068ac96a368269147
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c9ef1956b469746dc95cabc64051a824018ff3e24655b553fe315b174dfe1d1dfb4cefc31c66ddc2ab028c4492f1cd55578d455ba88f9c1555d57f823c18bacf
         | 
| 7 | 
            +
              data.tar.gz: 38274e655d05e2ba0f6a103d38cfc4e597c7e0101d88a02b0028921131473d607f3cdf2bfe0400b1380c9be8e72525f4fb5658954dd47a526c362870de1cad2c
         | 
| @@ -7,7 +7,7 @@ module Bankscrap | |
| 7 7 |  | 
| 8 8 | 
             
                  attr_accessor :contract_id
         | 
| 9 9 |  | 
| 10 | 
            -
                  ACCOUNT_ENDPOINT = '/ | 
| 10 | 
            +
                  ACCOUNT_ENDPOINT = '/my-money/cuentas/movimientos'.freeze
         | 
| 11 11 |  | 
| 12 12 | 
             
                  # Fetch transactions for the given account.
         | 
| 13 13 | 
             
                  # By default it fetches transactions for the last month,
         | 
| @@ -15,63 +15,32 @@ module Bankscrap | |
| 15 15 | 
             
                  # Returns an array of BankScrap::Transaction objects
         | 
| 16 16 | 
             
                  def fetch_transactions_for(connection, start_date: Date.today - 1.month, end_date: Date.today)
         | 
| 17 17 | 
             
                    transactions = []
         | 
| 18 | 
            -
                    end_page = false
         | 
| 19 | 
            -
                    repo = nil
         | 
| 20 | 
            -
                    importe_cta = nil
         | 
| 21 18 |  | 
| 19 | 
            +
                    fields = { producto: contract_id,
         | 
| 20 | 
            +
                               numeroContrato: id,
         | 
| 21 | 
            +
                               fechaDesde: format_date(start_date),
         | 
| 22 | 
            +
                               fechaHasta: format_date(end_date),
         | 
| 23 | 
            +
                               concepto: '000' }
         | 
| 22 24 | 
             
                    # Loop over pagination
         | 
| 23 | 
            -
                    until  | 
| 24 | 
            -
                       | 
| 25 | 
            -
             | 
| 26 | 
            -
                       | 
| 27 | 
            -
             | 
| 28 | 
            -
                      repo = document.at_xpath('//methodResult/repo')
         | 
| 29 | 
            -
                      importe_cta = document.at_xpath('//methodResult/importeCta')
         | 
| 30 | 
            -
                      end_page = value_at_xpath(document, '//methodResult/finLista') != 'N'
         | 
| 25 | 
            +
                    until fields.empty?
         | 
| 26 | 
            +
                      data = connection.get(ACCOUNT_ENDPOINT, fields: fields)
         | 
| 27 | 
            +
                      transactions += data['movimientos'].map { |item| build_transaction(item) }
         | 
| 28 | 
            +
                      fields = next_page_fields(data)
         | 
| 31 29 | 
             
                    end
         | 
| 32 30 |  | 
| 33 31 | 
             
                    transactions
         | 
| 34 32 | 
             
                  end
         | 
| 35 33 |  | 
| 36 | 
            -
                  def xml_account(connection, from_date, to_date, repo, importe_cta)
         | 
| 37 | 
            -
                    is_pagination = repo ? 'S' : 'N'
         | 
| 38 | 
            -
                    xml_from_date = xml_date(from_date)
         | 
| 39 | 
            -
                    xml_to_date = xml_date(to_date)
         | 
| 40 | 
            -
                    <<-account
         | 
| 41 | 
            -
                  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"   xmlns:v1="http://www.isban.es/webservices/BAMOBI/Cuentas/F_bamobi_cuentas_lip/internet/BAMOBICTA/v1">
         | 
| 42 | 
            -
                    #{connection.xml_security_header}
         | 
| 43 | 
            -
                    <soapenv:Body>
         | 
| 44 | 
            -
                      <v1:listaMovCuentasFechas_LIP facade="BAMOBICTA">
         | 
| 45 | 
            -
                        <entrada>
         | 
| 46 | 
            -
                    #{connection.xml_datos_cabecera}
         | 
| 47 | 
            -
                          <datosConexion>#{connection.user_data.children}</datosConexion>
         | 
| 48 | 
            -
                          <contratoID>#{contract_id}</contratoID>
         | 
| 49 | 
            -
                          <fechaDesde>#{xml_from_date}</fechaDesde>
         | 
| 50 | 
            -
                          <fechaHasta>#{xml_to_date}</fechaHasta>
         | 
| 51 | 
            -
                    #{importe_cta}
         | 
| 52 | 
            -
                          <esUnaPaginacion>#{is_pagination}</esUnaPaginacion>
         | 
| 53 | 
            -
                    #{repo}
         | 
| 54 | 
            -
                        </entrada>
         | 
| 55 | 
            -
                      </v1:listaMovCuentasFechas_LIP>
         | 
| 56 | 
            -
                    </soapenv:Body>
         | 
| 57 | 
            -
                  </soapenv:Envelope>
         | 
| 58 | 
            -
                    account
         | 
| 59 | 
            -
                  end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                  def xml_date(date)
         | 
| 62 | 
            -
                    "<dia>#{date.day}</dia><mes>#{date.month}</mes><anyo>#{date.year}</anyo>"
         | 
| 63 | 
            -
                  end
         | 
| 64 | 
            -
             | 
| 65 34 | 
             
                  # Build a transaction object from API data
         | 
| 66 35 | 
             
                  def build_transaction(data)
         | 
| 67 36 | 
             
                    Transaction.new(
         | 
| 68 37 | 
             
                      account: self,
         | 
| 69 | 
            -
                      id:  | 
| 70 | 
            -
                      amount: money(data | 
| 71 | 
            -
                      description:  | 
| 72 | 
            -
                      effective_date:  | 
| 73 | 
            -
                       | 
| 74 | 
            -
                      balance: money(data | 
| 38 | 
            +
                      id: data['nummov'],
         | 
| 39 | 
            +
                      amount: money(data['importe']),
         | 
| 40 | 
            +
                      description: data['conceptoTabla'],
         | 
| 41 | 
            +
                      effective_date: parse_date(data['fechaValor']),
         | 
| 42 | 
            +
                      operation_date: parse_date(data['fechaOperacion']),
         | 
| 43 | 
            +
                      balance: money(data['saldo'])
         | 
| 75 44 | 
             
                    )
         | 
| 76 45 | 
             
                  end
         | 
| 77 46 | 
             
                end
         | 
| @@ -1,5 +1,6 @@ | |
| 1 1 | 
             
            require 'bankscrap'
         | 
| 2 2 | 
             
            require 'securerandom'
         | 
| 3 | 
            +
            require 'json'
         | 
| 3 4 | 
             
            require 'byebug'
         | 
| 4 5 | 
             
            require_relative 'account.rb'
         | 
| 5 6 | 
             
            require_relative 'card.rb'
         | 
| @@ -10,20 +11,18 @@ module Bankscrap | |
| 10 11 | 
             
                class Bank < ::Bankscrap::Bank
         | 
| 11 12 | 
             
                  include Utils
         | 
| 12 13 |  | 
| 13 | 
            -
                  attr_accessor :user_data
         | 
| 14 | 
            -
             | 
| 15 14 | 
             
                  # Define the endpoints for the Bank API here
         | 
| 16 | 
            -
                  BASE_ENDPOINT     = 'https:// | 
| 17 | 
            -
                  LOGIN_ENDPOINT    = '/ | 
| 18 | 
            -
                  PRODUCTS_ENDPOINT = '/ | 
| 19 | 
            -
                  USER_AGENT        = ' | 
| 15 | 
            +
                  BASE_ENDPOINT     = 'https://api.openbank.es'.freeze
         | 
| 16 | 
            +
                  LOGIN_ENDPOINT    = '/authenticationcomposite/login'.freeze
         | 
| 17 | 
            +
                  PRODUCTS_ENDPOINT = '/posicion-global-total'.freeze
         | 
| 18 | 
            +
                  USER_AGENT        = 'okhttp/3.9.1'.freeze
         | 
| 20 19 |  | 
| 21 20 | 
             
                  def initialize(credentials = {})
         | 
| 21 | 
            +
                    @token_credential = nil
         | 
| 22 22 | 
             
                    super do
         | 
| 23 23 | 
             
                      add_headers(
         | 
| 24 | 
            -
                        'Content-Type'     => ' | 
| 24 | 
            +
                        'Content-Type'     => 'application/json; charset=utf-8',
         | 
| 25 25 | 
             
                        'User-Agent'       => USER_AGENT,
         | 
| 26 | 
            -
                        'Host'             => 'www.openbank.mobi',
         | 
| 27 26 | 
             
                        'Connection'       => 'Keep-Alive',
         | 
| 28 27 | 
             
                        'Accept-Encoding'  => 'gzip'
         | 
| 29 28 | 
             
                      )
         | 
| @@ -32,7 +31,20 @@ module Bankscrap | |
| 32 31 |  | 
| 33 32 | 
             
                  def login
         | 
| 34 33 | 
             
                    log 'login'
         | 
| 35 | 
            -
                     | 
| 34 | 
            +
                    login_data = {
         | 
| 35 | 
            +
                        document: @user,
         | 
| 36 | 
            +
                        documentType: "N",
         | 
| 37 | 
            +
                        password: @password,
         | 
| 38 | 
            +
                        force: true,
         | 
| 39 | 
            +
                        osVersion: "8.1.0",
         | 
| 40 | 
            +
                        uuid: "#{SecureRandom.hex(10)[0..2]}-#{SecureRandom.hex(10)[0..6]}",
         | 
| 41 | 
            +
                        mobileDeviceInfo: { pushEnabled:false,
         | 
| 42 | 
            +
                                            rooted: false,
         | 
| 43 | 
            +
                                            version: "1.1.16",
         | 
| 44 | 
            +
                                            device: "SAMSUNG",
         | 
| 45 | 
            +
                                            platform: "ANDROID" }
         | 
| 46 | 
            +
                        }
         | 
| 47 | 
            +
                    post(LOGIN_ENDPOINT, fields: login_data)
         | 
| 36 48 | 
             
                  end
         | 
| 37 49 |  | 
| 38 50 | 
             
                  # Fetch all the accounts for the given user
         | 
| @@ -40,11 +52,19 @@ module Bankscrap | |
| 40 52 | 
             
                  # Should returns an array of Bankscrap::Account objects
         | 
| 41 53 | 
             
                  def fetch_accounts
         | 
| 42 54 | 
             
                    log 'fetch_accounts'
         | 
| 43 | 
            -
                     | 
| 44 | 
            -
                     | 
| 45 | 
            -
             | 
| 55 | 
            +
                    data = get(PRODUCTS_ENDPOINT, fields: { carteras: false,listaSolicitada: 'TODOS',indicadorSaldoPreTarj: false })
         | 
| 56 | 
            +
                    cuentas = data['datosSalidaCuentas']['cuentas'].zip(data['datosSalidaCodIban']['datosIban'])
         | 
| 57 | 
            +
                    cuentas.map{ |data| build_account(data) }
         | 
| 46 58 | 
             
                  end
         | 
| 47 59 |  | 
| 60 | 
            +
                  # Fetch all the cards for the given user
         | 
| 61 | 
            +
                  #
         | 
| 62 | 
            +
                  # Should returns an array of Bankscrap::Card objects
         | 
| 63 | 
            +
                  def fetch_cards
         | 
| 64 | 
            +
                     log 'fetch_cards'
         | 
| 65 | 
            +
                     data = get(PRODUCTS_ENDPOINT, fields: { carteras: false,listaSolicitada: 'TODOS',indicadorSaldoPreTarj: false })
         | 
| 66 | 
            +
                     data['datosSalidaTarjetas']['tarjetas'].map{ |data| build_card(data) }
         | 
| 67 | 
            +
                  end
         | 
| 48 68 | 
             
                  # Fetch transactions for the given account.
         | 
| 49 69 | 
             
                  #
         | 
| 50 70 | 
             
                  # Account should be a Bankscrap::Account object
         | 
| @@ -53,57 +73,32 @@ module Bankscrap | |
| 53 73 | 
             
                    product.fetch_transactions_for(self, start_date: start_date, end_date: end_date)
         | 
| 54 74 | 
             
                  end
         | 
| 55 75 |  | 
| 56 | 
            -
                  def  | 
| 57 | 
            -
                     | 
| 58 | 
            -
                     | 
| 59 | 
            -
             | 
| 60 | 
            -
                        <wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SSOToken" ValueType="esquema" EncodingType="hwsse:Base64Binary">#{@token_credential}</wsse:BinarySecurityToken>
         | 
| 61 | 
            -
                      </wsse:Security>
         | 
| 62 | 
            -
                    </soapenv:Header>
         | 
| 63 | 
            -
                    security
         | 
| 64 | 
            -
                  end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                  def xml_datos_cabecera
         | 
| 67 | 
            -
                    <<-datos
         | 
| 68 | 
            -
                    <datosCabecera>
         | 
| 69 | 
            -
                      <version>3.0.4</version>
         | 
| 70 | 
            -
                      <terminalID>Android</terminalID>
         | 
| 71 | 
            -
                      <idioma>es-ES</idioma>
         | 
| 72 | 
            -
                    </datosCabecera>
         | 
| 73 | 
            -
                    datos
         | 
| 76 | 
            +
                  def post(method, fields: {})
         | 
| 77 | 
            +
                    set_auth_headers()
         | 
| 78 | 
            +
                    response = super(BASE_ENDPOINT + method, fields: JSON.generate(fields))
         | 
| 79 | 
            +
                    parse_context(response)
         | 
| 74 80 | 
             
                  end
         | 
| 75 81 |  | 
| 76 | 
            -
                  def  | 
| 77 | 
            -
                     | 
| 82 | 
            +
                  def get(method, fields: {})
         | 
| 83 | 
            +
                    set_auth_headers()
         | 
| 84 | 
            +
                    response = super(BASE_ENDPOINT + method, params: fields)
         | 
| 78 85 | 
             
                    parse_context(response)
         | 
| 79 86 | 
             
                  end
         | 
| 80 87 |  | 
| 81 88 | 
             
                  private
         | 
| 82 89 |  | 
| 83 | 
            -
                  def xml_products
         | 
| 84 | 
            -
                    <<-products
         | 
| 85 | 
            -
                  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://www.isban.es/webservices/BAMOBI/Posglobal/F_bamobi_posicionglobal_lip/internet/BAMOBIPGL/v1">
         | 
| 86 | 
            -
                    #{xml_security_header}
         | 
| 87 | 
            -
                    <soapenv:Body>
         | 
| 88 | 
            -
                      <v1:obtenerPosGlobal_LIP facade="BAMOBIPGL">
         | 
| 89 | 
            -
                        <entrada>#{xml_datos_cabecera}</entrada>
         | 
| 90 | 
            -
                      </v1:obtenerPosGlobal_LIP>
         | 
| 91 | 
            -
                    </soapenv:Body>
         | 
| 92 | 
            -
                  </soapenv:Envelope>
         | 
| 93 | 
            -
                    products
         | 
| 94 | 
            -
                  end
         | 
| 95 | 
            -
             | 
| 96 90 | 
             
                  # Build an Account object from API data
         | 
| 97 91 | 
             
                  def build_account(data)
         | 
| 92 | 
            +
                    account, iban = data
         | 
| 98 93 | 
             
                    Account.new(
         | 
| 99 94 | 
             
                      bank: self,
         | 
| 100 | 
            -
                      id:  | 
| 101 | 
            -
                      name:  | 
| 102 | 
            -
                      available_balance: money( | 
| 103 | 
            -
                      balance: money( | 
| 104 | 
            -
                      iban:  | 
| 105 | 
            -
                      description:  | 
| 106 | 
            -
                      contract_id:  | 
| 95 | 
            +
                      id: account['cviejo']['numerodecontrato'],
         | 
| 96 | 
            +
                      name: account.fetch('descripcion', '').strip(),
         | 
| 97 | 
            +
                      available_balance: money(account['saldoActual']),
         | 
| 98 | 
            +
                      balance: money(account['saldoActual']),
         | 
| 99 | 
            +
                      iban: iban['codIban'].values().join.strip,
         | 
| 100 | 
            +
                      description: account.fetch('descripcion', '').strip(),
         | 
| 101 | 
            +
                      contract_id: account['cviejo']['subgrupo']
         | 
| 107 102 | 
             
                    )
         | 
| 108 103 | 
             
                  end
         | 
| 109 104 |  | 
| @@ -111,53 +106,31 @@ module Bankscrap | |
| 111 106 | 
             
                  def build_card(data)
         | 
| 112 107 | 
             
                    Card.new(
         | 
| 113 108 | 
             
                      bank: self,
         | 
| 114 | 
            -
                      id:  | 
| 115 | 
            -
                      name:  | 
| 116 | 
            -
                       | 
| 117 | 
            -
                       | 
| 118 | 
            -
                       | 
| 119 | 
            -
                      description:  | 
| 120 | 
            -
                      contract_id: data | 
| 109 | 
            +
                      id: data['contrato']['numerodecontrato'],
         | 
| 110 | 
            +
                      name: data['panmdp'],
         | 
| 111 | 
            +
                      avaliable: money(data['saldoDisponible']),
         | 
| 112 | 
            +
                      amount: money(data['saldoDispuesto']),
         | 
| 113 | 
            +
                      pan: data['panmdp'],
         | 
| 114 | 
            +
                      description: data['descripcion'],
         | 
| 115 | 
            +
                      contract_id: data['contrato']['producto'],
         | 
| 116 | 
            +
                      is_credit: data['tipoTarjeta'].to_s == "credit"
         | 
| 121 117 | 
             
                    )
         | 
| 122 118 | 
             
                  end
         | 
| 123 119 |  | 
| 124 | 
            -
                  def parse_context( | 
| 125 | 
            -
                     | 
| 126 | 
            -
                    @ | 
| 127 | 
            -
                     | 
| 128 | 
            -
                    self.user_data = document.at_xpath('//methodResult/datosUsuario') || user_data
         | 
| 129 | 
            -
                    document
         | 
| 130 | 
            -
                  end
         | 
| 131 | 
            -
             | 
| 132 | 
            -
                  def public_ip
         | 
| 133 | 
            -
                    log 'getting public ip'
         | 
| 134 | 
            -
                    ip = open('http://api.ipify.org').read
         | 
| 135 | 
            -
                    log "public ip: [#{ip}]"
         | 
| 136 | 
            -
                    ip
         | 
| 120 | 
            +
                  def parse_context(data)
         | 
| 121 | 
            +
                    context = JSON.parse(data)
         | 
| 122 | 
            +
                    @token_credential = context.fetch('tokenCredential', @token_credential)
         | 
| 123 | 
            +
                    context
         | 
| 137 124 | 
             
                  end
         | 
| 138 125 |  | 
| 139 126 | 
             
                  def format_user(user)
         | 
| 140 127 | 
             
                    user.upcase
         | 
| 141 128 | 
             
                  end
         | 
| 142 129 |  | 
| 143 | 
            -
                  def  | 
| 144 | 
            -
                     | 
| 145 | 
            -
             | 
| 146 | 
            -
                     | 
| 147 | 
            -
                    <v:Body>
         | 
| 148 | 
            -
                      <n0:authenticateCredential xmlns:n0="http://www.isban.es/webservices/TECHNICAL_FACADES/Security/F_facseg_security/internet/loginServicesNSegWS/v1" facade="loginServicesNSegWS">
         | 
| 149 | 
            -
                        <CB_AuthenticationData i:type=":CB_AuthenticationData">
         | 
| 150 | 
            -
                          <documento i:type=":documento">
         | 
| 151 | 
            -
                            <CODIGO_DOCUM_PERSONA_CORP i:type="d:string">#{@user}</CODIGO_DOCUM_PERSONA_CORP>
         | 
| 152 | 
            -
                            <TIPO_DOCUM_PERSONA_CORP i:type="d:string">N</TIPO_DOCUM_PERSONA_CORP>
         | 
| 153 | 
            -
                          </documento>
         | 
| 154 | 
            -
                          <password i:type="d:string">#{@password}</password>
         | 
| 155 | 
            -
                        </CB_AuthenticationData>
         | 
| 156 | 
            -
                        <userAddress i:type="d:string">#{public_ip}</userAddress>
         | 
| 157 | 
            -
                      </n0:authenticateCredential>
         | 
| 158 | 
            -
                    </v:Body>
         | 
| 159 | 
            -
                  </v:Envelope>
         | 
| 160 | 
            -
                    login
         | 
| 130 | 
            +
                  def set_auth_headers
         | 
| 131 | 
            +
                    headers = {}
         | 
| 132 | 
            +
                    headers['openbankauthtoken'] = @token_credential unless @token_credential.nil?
         | 
| 133 | 
            +
                    add_headers(headers) unless headers.empty?
         | 
| 161 134 | 
             
                  end
         | 
| 162 135 | 
             
                end
         | 
| 163 136 | 
             
              end
         | 
| @@ -2,10 +2,12 @@ require_relative 'utils.rb' | |
| 2 2 |  | 
| 3 3 | 
             
            module Bankscrap
         | 
| 4 4 | 
             
              module Openbank
         | 
| 5 | 
            -
                class Card <  | 
| 5 | 
            +
                class Card < ::Bankscrap::Card
         | 
| 6 6 | 
             
                  include Utils
         | 
| 7 7 |  | 
| 8 | 
            -
                   | 
| 8 | 
            +
                  attr_accessor :contract_id
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  CARD_ENDPOINT = '/my-money/tarjetas/movimientosCategoria'.freeze
         | 
| 9 11 |  | 
| 10 12 | 
             
                  # Fetch transactions for the given account.
         | 
| 11 13 | 
             
                  # By default it fetches transactions for the last month,
         | 
| @@ -13,60 +15,36 @@ module Bankscrap | |
| 13 15 | 
             
                  # Returns an array of BankScrap::Transaction objects
         | 
| 14 16 | 
             
                  def fetch_transactions_for(connection, start_date: Date.today - 1.month, end_date: Date.today)
         | 
| 15 17 | 
             
                    transactions = []
         | 
| 16 | 
            -
                     | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 18 | 
            +
                    fields = { producto: contract_id,
         | 
| 19 | 
            +
                               numeroContrato: id,
         | 
| 20 | 
            +
                               pan: pan,
         | 
| 21 | 
            +
                               fechaDesde: format_date(start_date),
         | 
| 22 | 
            +
                               fechaHasta: format_date(end_date)
         | 
| 23 | 
            +
                             }
         | 
| 19 24 | 
             
                    # Loop over pagination
         | 
| 20 | 
            -
                    until  | 
| 21 | 
            -
                       | 
| 22 | 
            -
             | 
| 23 | 
            -
                       | 
| 24 | 
            -
             | 
| 25 | 
            -
                      repos = document.at_xpath('//methodResult/repos')
         | 
| 26 | 
            -
                      end_page = value_at_xpath(document, '//methodResult/finLista') != 'N'
         | 
| 25 | 
            +
                    until fields.empty?
         | 
| 26 | 
            +
                      data = connection.get(CARD_ENDPOINT, fields: fields)
         | 
| 27 | 
            +
                      transactions += data['lista']['movimientos'].map { |data| build_transaction(data) }.compact
         | 
| 28 | 
            +
                      fields = next_page_fields(data)
         | 
| 27 29 | 
             
                    end
         | 
| 28 30 |  | 
| 29 31 | 
             
                    transactions
         | 
| 30 32 | 
             
                  end
         | 
| 31 33 |  | 
| 32 | 
            -
                  def  | 
| 33 | 
            -
                     | 
| 34 | 
            -
                    xml_from_date = xml_date(from_date)
         | 
| 35 | 
            -
                    xml_to_date = xml_date(to_date)
         | 
| 36 | 
            -
                    <<-card
         | 
| 37 | 
            -
                  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"   xmlns:v1="http://www.isban.es/webservices/BAMOBI/Tarjetas/F_bamobi_tarjetas_lip/internet/BAMOBITAJ/v1">
         | 
| 38 | 
            -
                    #{connection.xml_security_header}
         | 
| 39 | 
            -
                    <soapenv:Body>
         | 
| 40 | 
            -
                      <v1:listaMovTarjetasFechas_LIP facade="BAMOBITAJ">
         | 
| 41 | 
            -
                        <entrada>
         | 
| 42 | 
            -
                          <datosConexion>#{connection.user_data.children}</datosConexion>
         | 
| 43 | 
            -
                          #{connection.xml_datos_cabecera}
         | 
| 44 | 
            -
                          <contratoTarjeta>#{contract_id}</contratoTarjeta>
         | 
| 45 | 
            -
                          <numeroTarj>#{id}</numeroTarj>
         | 
| 46 | 
            -
                          <fechaDesde>#{xml_from_date}</fechaDesde>
         | 
| 47 | 
            -
                          <fechaHasta>#{xml_to_date}</fechaHasta>
         | 
| 48 | 
            -
                          <esUnaPaginacion>#{is_pagination}</esUnaPaginacion>
         | 
| 49 | 
            -
                          #{repos}
         | 
| 50 | 
            -
                        </entrada>
         | 
| 51 | 
            -
                      </v1:listaMovTarjetasFechas_LIP>
         | 
| 52 | 
            -
                    </soapenv:Body>
         | 
| 53 | 
            -
                  </soapenv:Envelope>
         | 
| 54 | 
            -
                    card
         | 
| 55 | 
            -
                  end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                  def xml_date(date)
         | 
| 58 | 
            -
                    "<dia>#{date.day}</dia><mes>#{date.month}</mes><anyo>#{date.year}</anyo>"
         | 
| 34 | 
            +
                  def fetch_transactions(start_date: Date.today - 2.years, end_date: Date.today)
         | 
| 35 | 
            +
                    fetch_transactions_for(bank, start_date: start_date, end_date: end_date)
         | 
| 59 36 | 
             
                  end
         | 
| 60 37 |  | 
| 61 38 | 
             
                  # Build a transaction object from API data
         | 
| 62 39 | 
             
                  def build_transaction(data)
         | 
| 40 | 
            +
                    return if data['estadoPeticion'] == 'L'
         | 
| 63 41 | 
             
                    Transaction.new(
         | 
| 64 42 | 
             
                      account: self,
         | 
| 65 | 
            -
                      id:  | 
| 66 | 
            -
                      amount: money(data | 
| 67 | 
            -
                      description:  | 
| 68 | 
            -
                      effective_date:  | 
| 69 | 
            -
                       | 
| 43 | 
            +
                      id: data['numeroMovimintoEnDia'],
         | 
| 44 | 
            +
                      amount: money(data['impOperacion']),
         | 
| 45 | 
            +
                      description: data['txtCajero'],
         | 
| 46 | 
            +
                      effective_date: parse_date(data['fechaAnotacionMovimiento']),
         | 
| 47 | 
            +
                      operation_date: parse_date(data['fechaMovimiento']),
         | 
| 70 48 | 
             
                      balance: Money.new(0, 'EUR') # TODO: Prepaid/debit cards don't have a Balance - maybe Credit ones do.
         | 
| 71 49 | 
             
                    )
         | 
| 72 50 | 
             
                  end
         | 
| @@ -1,17 +1,28 @@ | |
| 1 1 | 
             
            module Bankscrap
         | 
| 2 2 | 
             
              module Openbank
         | 
| 3 3 | 
             
                module Utils
         | 
| 4 | 
            -
                  def value_at_xpath(node, xpath, default = '')
         | 
| 5 | 
            -
                    value = node.at_xpath(xpath)
         | 
| 6 | 
            -
                    value ? value.content.strip : default
         | 
| 7 | 
            -
                  end
         | 
| 8 4 |  | 
| 9 | 
            -
                  def money(data | 
| 5 | 
            +
                  def money(data)
         | 
| 10 6 | 
             
                    Money.new(
         | 
| 11 | 
            -
                       | 
| 12 | 
            -
                       | 
| 7 | 
            +
                      data['importe'] * 100.0,
         | 
| 8 | 
            +
                      data['divisa'].presence || 'EUR'
         | 
| 13 9 | 
             
                    )
         | 
| 14 10 | 
             
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def parse_date(date)
         | 
| 13 | 
            +
                    Date.strptime(date, '%Y-%m-%d')
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def format_date(date)
         | 
| 17 | 
            +
                    "%04d-%02d-%02d" % [date.year, date.month, date.day]
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  def next_page_fields(data)
         | 
| 21 | 
            +
                    link = data&.fetch('_links', nil)&.fetch('nextPage', nil)&.fetch('href', nil)
         | 
| 22 | 
            +
                    return {} unless link
         | 
| 23 | 
            +
                    uri = URI.parse(link)
         | 
| 24 | 
            +
                    URI::decode_www_form(uri.query).to_h
         | 
| 25 | 
            +
                  end
         | 
| 15 26 | 
             
                end
         | 
| 16 27 | 
             
              end
         | 
| 17 28 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: bankscrap-openbank
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 3.0.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - zjuanma
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2018-08-08 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bankscrap
         | 
| @@ -104,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 104 104 | 
             
                  version: '0'
         | 
| 105 105 | 
             
            requirements: []
         | 
| 106 106 | 
             
            rubyforge_project: 
         | 
| 107 | 
            -
            rubygems_version: 2. | 
| 107 | 
            +
            rubygems_version: 2.6.14
         | 
| 108 108 | 
             
            signing_key: 
         | 
| 109 109 | 
             
            specification_version: 4
         | 
| 110 110 | 
             
            summary: Openbank adapter for Bankscrap
         |