bankscrap-bbva-net-cash 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fbcd07b15419ce680a0c2829917d370dd832419f
4
+ data.tar.gz: 900676d73e0aaa89036775d15f3b2a80110c522e
5
+ SHA512:
6
+ metadata.gz: 7a818e4de058a58b831613dd7c7ec00904b02f8c1eab4b1bdb5bc166521ff0dbf08661136257d9adcd5e24c706b9971c9a7527af6c750c640471e5297ac6567c
7
+ data.tar.gz: 879692f2eb09c00a1b05c5baf8d7dede32097aac6b88c2887a4884b05aff44d1f70012ec001e1655831270a4155c32f458f35ab3185015a09d4d0fd390aa3ad4
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .byebug_history
@@ -0,0 +1,5 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.1
3
+
4
+ Metrics/LineLength:
5
+ Max: 120
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bankscrap-bbva-net-cash.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Raúl Marcos
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,55 @@
1
+ # Bankscrap::BBVANetCash
2
+
3
+ Bankscrap adapter for the API behind BBVA's [Net Cash mobile app](https://play.google.com/store/apps/details?id=com.bbva.netcash).
4
+
5
+ This adapter is only valid for **company accounts** (the ones that have access to Net Cash). For personal accounts
6
+ you should use [bankscrap-bbva](https://github.com/bankscrap/bankscrap-bbva).
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'bankscrap-bbva-net-cash'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install bankscrap-bbva-net-cash
23
+
24
+ ## Usage
25
+
26
+ ### From terminal
27
+ #### Bank account balance
28
+
29
+ $ bankscrap balance BBVANetCash --user YOUR_USER --password YOUR_PASSWORD --extra=company_code:YOUR_COMPANY_CODE
30
+
31
+
32
+ #### Transactions
33
+
34
+ $ bankscrap transactions BBVANetCash --user YOUR_USER --password YOUR_PASSWORD --extra=company_code:YOUR_COMPANY_CODE
35
+
36
+ ---
37
+
38
+ For more details on usage instructions please read [Bankscrap readme](https://github.com/bankscrap/bankscrap/#usage).
39
+
40
+ ### From Ruby code
41
+
42
+
43
+ ```ruby
44
+ require 'bankscrap-bbva-net-cash'
45
+ bbva_net_cash = Bankscrap::BBVANetCash::Bank.new(YOUR_USER, YOUR_PASSWORD, extra_args: {company_code: YOUR_COMPANY_CODE})
46
+ ```
47
+
48
+
49
+ ## Contributing
50
+
51
+ 1. Fork it ( https://github.com/bankscrap/bankscrap-bbva-net-cash/fork )
52
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
53
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
54
+ 4. Push to the branch (`git push origin my-new-feature`)
55
+ 5. Create a new Pull Request
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bankscrap/bbva-net-cash/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'bankscrap-bbva-net-cash'
8
+ spec.version = Bankscrap::BBVANetCash::VERSION
9
+ spec.authors = ['Javier Cuevas']
10
+ spec.email = ['javier@diacode.com']
11
+ spec.summary = 'BBVA Net Cash adapter for Bankscrap'
12
+ spec.homepage = ''
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_runtime_dependency 'bankscrap', '~> 1.0.2'
21
+ spec.add_development_dependency 'bundler', '~> 1.7'
22
+ spec.add_development_dependency 'rake', '~> 10.0'
23
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'bankscrap/bbva-net-cash/bank'
2
+ require_relative 'bankscrap/bbva-net-cash/version'
@@ -0,0 +1,244 @@
1
+ require 'bankscrap'
2
+ require 'securerandom'
3
+
4
+ module Bankscrap
5
+ module BBVANetCash
6
+ class Bank < ::Bankscrap::Bank
7
+
8
+ BASE_ENDPOINT = 'https://www.bbvanetcash.mobi'.freeze
9
+ LOGIN_ENDPOINT = '/DFAUTH/slod_mult_mult/EAILServlet'.freeze
10
+ ACCOUNTS_ENDPOINT = '/SESKYOS/kyos_mult_web_servicios_02/services/rest/CuentasServiceREST/getDatosCuentas'.freeze
11
+ TRANSACTIONS_ENDPOINT = '/SESKYOS/kyos_mult_web_servicios_02/services/rest/CuentasServiceREST/getMovimientos'.freeze
12
+
13
+ def initialize(user, password, log: false, debug: false, extra_args: nil)
14
+ @company_code = extra_args.with_indifferent_access['company_code']
15
+ @user = format_user(user.dup, @company_code.to_s.dup)
16
+ @password = password.upcase
17
+ @log = log
18
+ @debug = debug
19
+
20
+ initialize_connection
21
+
22
+ # Create a user_agent with a random string for privacy
23
+ user_agent = SecureRandom.hex(32).upcase + ';Android;LGE;Nexus 5;1080x1776;Android;5.1.1;BMES;4.4;xxhd'
24
+
25
+ add_headers(
26
+ 'User-Agent' => user_agent,
27
+ 'Accept' => 'application/json',
28
+ 'Accept-Charset' => 'UTF-8',
29
+ 'Connection' => 'Keep-Alive',
30
+ 'Host' => 'www.bbvanetcash.mobi'
31
+ )
32
+
33
+ login
34
+ super
35
+ end
36
+
37
+ # Fetch all the accounts for the given user
38
+ # Returns an array of Bankscrap::Account objects
39
+ def fetch_accounts
40
+ log 'fetch_accounts'
41
+
42
+ custom_headers = {
43
+ 'Content-Type' => 'application/json; charset=UTF-8',
44
+ 'Contexto' => get_context
45
+ }
46
+
47
+ params = {
48
+ "peticionCuentasKYOSPaginadas" => {
49
+ "favoritos" => false,
50
+ "paginacion" => "0"
51
+ }
52
+ }
53
+
54
+ response = with_headers(custom_headers) do
55
+ post(BASE_ENDPOINT + ACCOUNTS_ENDPOINT, fields: params.to_json)
56
+ end
57
+
58
+ json = JSON.parse(response)
59
+
60
+ if json['respuestacuentas']['cuentas'].is_a? Array
61
+ # TODO: test this with a user with multiple accounts
62
+ json['respuestacuentas']['cuentas'].map { |data| build_account(data) }
63
+ else
64
+ [build_account(json['respuestacuentas']['cuentas'])]
65
+ end
66
+ end
67
+
68
+ # Fetch transactions for the given account.
69
+ # By default it fetches transactions for the last month,
70
+ # The maximum allowed by the BBVA API is the last 3 years.
71
+ #
72
+ # Account should be a Bankscrap::Account object
73
+ # Returns an array of Bankscrap::Transaction objects
74
+ def fetch_transactions_for(account, start_date: Date.today - 1.month, end_date: Date.today)
75
+ from_date = start_date.strftime('%Y-%m-%d')
76
+
77
+ custom_headers = {
78
+ 'Content-Type' => 'application/json; charset=UTF-8',
79
+ 'Contexto' => get_context
80
+ }
81
+
82
+ params = {
83
+ "peticionMovimientosKYOS" => {
84
+ "numAsunto" => account.iban,
85
+ "bancoAsunto" => "BANCO BILBAO VIZCAYA ARGENTARIA S.A",
86
+ "fechaDesde" => start_date.strftime("%Y%m%d"),
87
+ "fechaHasta" => end_date.strftime("%Y%m%d"),
88
+ "concepto" => [],
89
+ "importe_Desde" => "",
90
+ "importe_Hasta" => "",
91
+ "divisa" => "EUR",
92
+ "paginacionTLSMT017" => "N000000000000+0000000000000000000",
93
+ "paginacionTLSMT016" => "N00000000000+0000000000000000",
94
+ "descargaInformes" => false,
95
+ "numElem" => 0,
96
+ "banco" => "1",
97
+ "idioma" => "51",
98
+ "formatoFecha" => "dd\/MM\/yyyy",
99
+ "paginacionMOVDIA" => "1",
100
+ "ultimaFechaPaginacionAnterior" => "",
101
+ "ordenacion" => "DESC"
102
+ }
103
+ }
104
+
105
+ url = BASE_ENDPOINT + TRANSACTIONS_ENDPOINT
106
+
107
+ transactions = []
108
+ with_headers(custom_headers) do
109
+ # Loop over pagination
110
+ loop do
111
+ json = JSON.parse(post(url, fields: params.to_json))['respuestamovimientos']
112
+
113
+ unless json['movimientos'].blank?
114
+ transactions += json['movimientos'].map do |data|
115
+ build_transaction(data, account)
116
+ end
117
+
118
+ params['peticionMovimientosKYOS']['paginacionMOVDIA'] = json['paginacionMOVDIA']
119
+ params['peticionMovimientosKYOS']['paginacionTLSMT016'] = json['paginacionTLSMT016']
120
+ params['peticionMovimientosKYOS']['paginacionTLSMT017'] = json['paginacionTLSMT017']
121
+ end
122
+
123
+ break unless json['descripcion'] == 'More records available'
124
+ end
125
+ end
126
+
127
+ transactions
128
+ end
129
+
130
+ private
131
+
132
+ # The user that gets sent to the API is a string composed by 3 items:
133
+ # 00230001 <- no idea why this number ¯\_(ツ)_/¯
134
+ # Company code
135
+ # User <- always in upcase
136
+ def format_user(user, company_code)
137
+ '00230001' + company_code + user.upcase
138
+ end
139
+
140
+ def login
141
+ log 'login'
142
+ params = {
143
+ 'origen' => 'pibeemovil',
144
+ 'eai_tipoCP' => 'up',
145
+ 'eai_URLDestino' => 'success_eail_CAS.jsp',
146
+ 'eai_user' => @user,
147
+ 'eai_password' => @password
148
+ }
149
+ post(BASE_ENDPOINT + LOGIN_ENDPOINT, fields: params)
150
+ end
151
+
152
+ # Build an Account object from API data
153
+ def build_account(data)
154
+ Account.new(
155
+ bank: self,
156
+ id: data['referencia'],
157
+ name: data['empresaDes'],
158
+ available_balance: data['saldoValor'].to_f,
159
+ balance: data['saldoContable'],
160
+ currency: data['divisa'],
161
+ iban: data['numeroAsunto'],
162
+ description: "#{data['bancoDes']} #{data['numeroAsuntoMostrar']}"
163
+ )
164
+ end
165
+
166
+ # Build a transaction object from API data
167
+ def build_transaction(data, account)
168
+ Transaction.new(
169
+ account: account,
170
+ id: data['codRmsoperS'],
171
+ amount: transaction_amount(data),
172
+ description: data['concepto'] || data['descConceptoTx'],
173
+ effective_date: Date.strptime(data['fechaContable'], '%d/%m/%Y'),
174
+ currency: data['divisa'],
175
+ balance: Money.new(data['saldoContable'].to_f * 100, data['currency'])
176
+ )
177
+ end
178
+
179
+ def transaction_amount(data)
180
+ Money.new(data['importe'].to_f * 100, data['divisa'])
181
+ end
182
+
183
+ # This API has a custom header called 'Contexto' that is required for every
184
+ # request after login. Some of the data has been anonymized.
185
+ def get_context
186
+ {
187
+ "perfil" => {
188
+ "usuario" => @user,
189
+ "nombre" => "",
190
+ "apellido1" => "",
191
+ "apellido2" => "",
192
+ "dni" => "",
193
+ "cargoFun" => "",
194
+ "centroCoste" => "",
195
+ "matricula" => "",
196
+ "bancoOperativo" => "",
197
+ "oficinaOperativa" => "",
198
+ "bancoFisico" => "",
199
+ "oficinaFisica" => "",
200
+ "paisOficina" => "",
201
+ "idioma" => "1",
202
+ "idiomaIso" => "1",
203
+ "divisaBase" => "ZZZ",
204
+ "divisaSecundaria" => "",
205
+ "xtiOfiFisica" => "",
206
+ "xtiOfiOperati" => "",
207
+ "listaAutorizaciones" => [
208
+ "AAAA",
209
+ "BBBB"
210
+ ]
211
+ },
212
+ "puesto" => {
213
+ "puestoLogico" => "3"
214
+ },
215
+ "transacciones" => {
216
+ "canalLlamante" => "4",
217
+ "medioAcceso" => "7",
218
+ "secuencia" => nil,
219
+ "servicioProducto" => "27",
220
+ "tipoIdentificacionCliente" => "6",
221
+ "identificacionCliente" => "",
222
+ "modoProceso" => nil,
223
+ "autorizacion" => nil,
224
+ "origenFisico" => nil
225
+ },
226
+ "datosTecnicos" => {
227
+ "idPeticion" => nil,
228
+ "UUAARemitente" => nil,
229
+ "usuarioLogico" => "",
230
+ "cabecerasHttp" => {
231
+ "aap" => "00000034",
232
+ "iv-user" => @user
233
+ }
234
+ },
235
+ "codigoCliente" => "1",
236
+ "tipoAutenticacion" => "1",
237
+ "identificacionCliente" => "",
238
+ "tipoIdentificacionCliente" => "6",
239
+ "propiedades" => nil
240
+ }
241
+ end
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,5 @@
1
+ module Bankscrap
2
+ module BBVANetCash
3
+ VERSION = '1.0.0'.freeze
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bankscrap-bbva-net-cash
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Javier Cuevas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bankscrap
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ description:
56
+ email:
57
+ - javier@diacode.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".rubocop.yml"
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - bankscrap-bbva.gemspec
69
+ - lib/bankscrap-bbva-net-cash.rb
70
+ - lib/bankscrap/bbva-net-cash/bank.rb
71
+ - lib/bankscrap/bbva-net-cash/version.rb
72
+ homepage: ''
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.6.4
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: BBVA Net Cash adapter for Bankscrap
96
+ test_files: []