hibiscus-ruby 0.1.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +90 -0
- data/README.markdown +63 -0
- data/Rakefile +61 -0
- data/doc/hibiscus api.txt +117 -0
- data/hibiscus-ruby.gemspec +21 -0
- data/lib/hibiscus-ruby.rb +7 -0
- data/lib/hibiscus/account.rb +18 -0
- data/lib/hibiscus/client.rb +58 -0
- data/lib/hibiscus/client_config.rb +51 -0
- data/lib/hibiscus/jobs.rb +14 -0
- data/lib/hibiscus/resource.rb +17 -0
- data/lib/hibiscus/statement_lines.rb +19 -0
- data/lib/hibiscus/transfer.rb +25 -0
- data/lib/hibiscus/version.rb +3 -0
- data/spec/hibiscus/client_config_spec.rb +92 -0
- data/spec/hibiscus/client_spec.rb +78 -0
- data/spec/spec_helper.rb +1 -0
- metadata +108 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MmQ5NTBkODg3NThkYmIzMjYyN2Y4ZDA5OGVkODdiYjYzOWQxZjI4NA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OGE3YjdkYmQwNmVjMTMxZWI2MDUyMDdkM2I4MzkxMWEzY2FmYTMxYw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZGI2NmIxNGY1ZWYyOThmMmY4NzQ5ODJkMmUyNzg1NTRkYzc0OWJkNTJmZDgy
|
10
|
+
MzIwY2NiYjczNWYyYjBhNjRkOGE2ZmYwZWIxMzJiN2NlOGFhMmRlNGFkMjky
|
11
|
+
OTEyN2IxN2U1MWI2ZjljMTBjZDc0ODRhZmUzMGZlYmRlM2Q2MjM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MjE4MDkyMzU0MzNlZmMxZWJkZjc3MjA2NzRiOTc5MjNkYTJhNWUxZTVlM2Ji
|
14
|
+
OGZjNTZkZDExMzdmNDEyZDk2Y2VjODRhYmYxNzJlNWUwNTI3NmQyMzQzMjI2
|
15
|
+
OTM4OWFiNTYwNzkxYTdlMzM1MTgxYTJjMTdlNDYzMjQ1ZTVjNzU=
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
hibiscus-ruby (0.1.0.pre)
|
5
|
+
httparty
|
6
|
+
rake
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
abstract_type (0.0.7)
|
12
|
+
adamantium (0.2.0)
|
13
|
+
ice_nine (~> 0.11.0)
|
14
|
+
memoizable (~> 0.4.0)
|
15
|
+
anima (0.2.0)
|
16
|
+
abstract_type (~> 0.0.7)
|
17
|
+
adamantium (~> 0.1)
|
18
|
+
equalizer (~> 0.0.8)
|
19
|
+
ast (1.1.0)
|
20
|
+
concord (0.1.4)
|
21
|
+
adamantium (~> 0.1)
|
22
|
+
equalizer (~> 0.0.7)
|
23
|
+
diff-lcs (1.2.5)
|
24
|
+
equalizer (0.0.9)
|
25
|
+
httparty (0.13.1)
|
26
|
+
json (~> 1.8)
|
27
|
+
multi_xml (>= 0.5.2)
|
28
|
+
ice_nine (0.11.0)
|
29
|
+
inflecto (0.0.2)
|
30
|
+
json (1.8.1)
|
31
|
+
memoizable (0.4.2)
|
32
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
33
|
+
morpher (0.2.2)
|
34
|
+
abstract_type (~> 0.0.7)
|
35
|
+
adamantium (~> 0.2.0)
|
36
|
+
anima (~> 0.2.0)
|
37
|
+
ast (~> 1.1.0)
|
38
|
+
concord (~> 0.1.4)
|
39
|
+
equalizer (~> 0.0.9)
|
40
|
+
ice_nine (~> 0.11.0)
|
41
|
+
procto (~> 0.0.2)
|
42
|
+
multi_xml (0.5.5)
|
43
|
+
mutant (0.5.10)
|
44
|
+
abstract_type (~> 0.0.7)
|
45
|
+
adamantium (~> 0.2.0)
|
46
|
+
anima (~> 0.2.0)
|
47
|
+
concord (~> 0.1.4)
|
48
|
+
diff-lcs (~> 1.2)
|
49
|
+
equalizer (~> 0.0.9)
|
50
|
+
ice_nine (~> 0.11.0)
|
51
|
+
inflecto (~> 0.0.2)
|
52
|
+
memoizable (~> 0.4.2)
|
53
|
+
morpher (~> 0.2.1)
|
54
|
+
parser (~> 2.1)
|
55
|
+
procto (~> 0.0.2)
|
56
|
+
unparser (~> 0.1.10)
|
57
|
+
mutant-rspec (0.5.10)
|
58
|
+
mutant (~> 0.5.10)
|
59
|
+
rspec-core (>= 2.14.1, <= 3.0.0.beta2)
|
60
|
+
parser (2.1.7)
|
61
|
+
ast (~> 1.1)
|
62
|
+
slop (~> 3.4, >= 3.4.5)
|
63
|
+
procto (0.0.2)
|
64
|
+
rake (10.2.2)
|
65
|
+
rspec (2.14.1)
|
66
|
+
rspec-core (~> 2.14.0)
|
67
|
+
rspec-expectations (~> 2.14.0)
|
68
|
+
rspec-mocks (~> 2.14.0)
|
69
|
+
rspec-core (2.14.8)
|
70
|
+
rspec-expectations (2.14.5)
|
71
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
72
|
+
rspec-mocks (2.14.6)
|
73
|
+
slop (3.5.0)
|
74
|
+
thread_safe (0.3.3)
|
75
|
+
unparser (0.1.12)
|
76
|
+
abstract_type (~> 0.0.7)
|
77
|
+
adamantium (~> 0.2.0)
|
78
|
+
concord (~> 0.1.4)
|
79
|
+
equalizer (~> 0.0.9)
|
80
|
+
parser (~> 2.1)
|
81
|
+
procto (~> 0.0.2)
|
82
|
+
|
83
|
+
PLATFORMS
|
84
|
+
ruby
|
85
|
+
|
86
|
+
DEPENDENCIES
|
87
|
+
hibiscus-ruby!
|
88
|
+
mutant-rspec
|
89
|
+
rspec
|
90
|
+
rspec-core (= 2.14.8)
|
data/README.markdown
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
### Introduction
|
2
|
+
|
3
|
+
hibiscus-ruby is a Ruby API client for the HBCI-compliant [Hibiscus payment server](http://www.willuhn.de/products/hibiscus-server).
|
4
|
+
|
5
|
+
### Requirements
|
6
|
+
|
7
|
+
- Ruby 1.9 or higher
|
8
|
+
- a running instance of [hibiscus-server](http://www.willuhn.de/products/hibiscus-server/), configured for your HBCI-accessible bank accounts.
|
9
|
+
**For security reasons, it is highly recommended to run the server locally!**
|
10
|
+
|
11
|
+
### How to use
|
12
|
+
|
13
|
+
> irb -Ilib
|
14
|
+
|
15
|
+
require 'hibiscus-ruby'
|
16
|
+
|
17
|
+
# configure the client
|
18
|
+
Hibiscus::Client.config = {
|
19
|
+
password: 'your hibiscus server password'
|
20
|
+
}
|
21
|
+
# get the list known accounts
|
22
|
+
p Hibiscus::Account.new.all
|
23
|
+
|
24
|
+
Options you can pass to `Hibiscus::Client.config`:
|
25
|
+
|
26
|
+
* username (defaults to `admin`)
|
27
|
+
* password (is unset by default)
|
28
|
+
* base_uri (defaults to `https://localhost:8080/webadmin/rest/hibiscus`)
|
29
|
+
* verify_ssl (defaults to `false`. hibiscus-server uses an invalid SSL Certificate, which should be fine in 99% of it's use cases)
|
30
|
+
|
31
|
+
### API Documentation
|
32
|
+
|
33
|
+
For now, please have a look at the classes in `lib/hibiscus` to find out what they can do.
|
34
|
+
The specs should be helpful documentation as well.
|
35
|
+
|
36
|
+
### Running the tests
|
37
|
+
|
38
|
+
rspec unit tests:
|
39
|
+
|
40
|
+
> rake
|
41
|
+
|
42
|
+
Mutation tests (using [mutant](https://github.com/mbj/mutant)):
|
43
|
+
|
44
|
+
> rake spec:mutation
|
45
|
+
|
46
|
+
### Travis build status
|
47
|
+
|
48
|
+
[![Build Status](https://travis-ci.org/phillipoertel/hibiscus-ruby.svg)](https://travis-ci.org/phillipoertel/hibiscus-ruby)
|
49
|
+
|
50
|
+
### Todos
|
51
|
+
|
52
|
+
- make it a gem
|
53
|
+
- clean up resources and write unit tests
|
54
|
+
- write integration tests against the Hibiscus server
|
55
|
+
- set up nice references, like Account.find(1).statement_lines
|
56
|
+
- make Transfer#create nicer (Terminüberweisung)
|
57
|
+
- add sanity checks to Transfer#create
|
58
|
+
- convert server errors (Java Exceptions) into corresponding Ruby exceptions
|
59
|
+
|
60
|
+
### Done
|
61
|
+
|
62
|
+
- figure out why Transfer#create doesn't work yet (Hibiscus Server doesn't do them with PIN/TAN)
|
63
|
+
- document how to use the client and set default config
|
data/Rakefile
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
$LOAD_PATH << 'lib'
|
2
|
+
|
3
|
+
require 'hibiscus-ruby'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
task :default => "spec:rspec"
|
7
|
+
|
8
|
+
namespace "spec" do
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new(:rspec)
|
11
|
+
|
12
|
+
desc "does mutation testing for selected classes"
|
13
|
+
task :mutation do
|
14
|
+
# find the classes we have specs for
|
15
|
+
classes_with_specs = Dir.glob('spec/hibiscus/*_spec.rb')
|
16
|
+
# create a hash of the form {'Ruby class name' => 'class file name'}
|
17
|
+
classes_and_specs = classes_with_specs.inject({}) do |hash, spec_path|
|
18
|
+
klass = spec_path.match(%r{/([a-z]+)_spec.rb})[1]
|
19
|
+
klass_constant = "Hibiscus::#{klass.capitalize}"
|
20
|
+
klass_path = spec_path.sub(%r{\Aspec/}, '').sub('_spec.rb', '.rb')
|
21
|
+
hash[klass_constant] = klass_path
|
22
|
+
hash
|
23
|
+
end
|
24
|
+
cmd_template = "bundle exec mutant --include lib --use rspec --fail-fast --require SPEC CLASS"
|
25
|
+
classes_and_specs.each do |klass, spec|
|
26
|
+
cmd = cmd_template.sub("CLASS", klass).sub("SPEC", spec)
|
27
|
+
system(cmd)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
namespace :examples do
|
34
|
+
|
35
|
+
task :configure_client do
|
36
|
+
Hibiscus::Client.config = { password: ENV['PASSWORD'] }
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "An example GET request"
|
40
|
+
task get: :configure_client do
|
41
|
+
#p Hibiscus::Account.new.all
|
42
|
+
#p Hibiscus::Jobs.new.pending
|
43
|
+
#p Hibiscus::Transfer.new.delete(2) # interne überweisungs-id verwenden
|
44
|
+
#p Hibiscus::Transfer.new.pending
|
45
|
+
#p Hibiscus::StatementLines.new.search('paypal')
|
46
|
+
p Hibiscus::StatementLines.new.latest(2, 5)
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "An example POST request"
|
50
|
+
task post: :configure_client do
|
51
|
+
data = {
|
52
|
+
betrag: "0,01",
|
53
|
+
blz: "38070724", # Bankleitzahl des Gegenkontos
|
54
|
+
konto: "321487100", # Kontonummer des Gegenkontos
|
55
|
+
name: "Phillip Oertel", # Inhaber-Name des Gegenkontos
|
56
|
+
konto_id: "2", # ID des eigenen Kontos
|
57
|
+
zweck: "Hibiscus Test", # Verwendungszweck Zeile 1
|
58
|
+
}
|
59
|
+
p Hibiscus::Transfer.new.create(data)
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
##
|
2
|
+
## Allgemeines
|
3
|
+
##
|
4
|
+
|
5
|
+
- API Doku: https://localhost:8080/webadmin/rest.html
|
6
|
+
- Request base: /webadmin/rest/hibiscus
|
7
|
+
- curl -k -u 'admin:PASSWORD' https://localhost:8080/webadmin/rest/PATH
|
8
|
+
|
9
|
+
|
10
|
+
##
|
11
|
+
## Ressourcen
|
12
|
+
##
|
13
|
+
/jobs/list aktuelle Sync-Aufgaben
|
14
|
+
/konto/list Informationen über die Konten
|
15
|
+
/ueberweisung/delete/{id} lösche Überweisung mit +id+
|
16
|
+
/ueberweisung/list/open offene Überweisungen
|
17
|
+
/ueberweisung/create Überweisung erstellen (GET oder POST). Parameter siehe Überweisung unten
|
18
|
+
/umsaetze/query/{term} Umsätze mit +term+ suchen
|
19
|
+
/konto/{konto-id}/umsaetze/days/{days} Umsätze für Hibiscus {konto-id} in den letzten {days} Tagen
|
20
|
+
|
21
|
+
# Ruby API Draft
|
22
|
+
Jobs#unsynched
|
23
|
+
Account#all
|
24
|
+
Transfer
|
25
|
+
#delete
|
26
|
+
#pending
|
27
|
+
#create
|
28
|
+
StatementLines
|
29
|
+
#search
|
30
|
+
#latest(account, days)
|
31
|
+
|
32
|
+
Account
|
33
|
+
#info
|
34
|
+
-> transfer(s)
|
35
|
+
-> statement_line(s)
|
36
|
+
|
37
|
+
##
|
38
|
+
## Datenstrukturen
|
39
|
+
##
|
40
|
+
|
41
|
+
# Buchung
|
42
|
+
|
43
|
+
{
|
44
|
+
"art": "Lastschrifteinzug",
|
45
|
+
"betrag": "-453.14",
|
46
|
+
"checksum": "2135929106",
|
47
|
+
"customerref": "NONREF",
|
48
|
+
"datum": "2014-03-27",
|
49
|
+
"empfaenger_blz": "BYLADEM1001",
|
50
|
+
"empfaenger_konto": "DE63120300009005290334",
|
51
|
+
"empfaenger_name": "ABRECHNUNG LUFTHANSA CARD",
|
52
|
+
"gvcode": "005",
|
53
|
+
"id": "127",
|
54
|
+
"konto_id": "2",
|
55
|
+
"primanota": "006220",
|
56
|
+
"saldo": "3952.99",
|
57
|
+
"valuta": "2014-03-27",
|
58
|
+
"zweck": "EREF+992005594515214",
|
59
|
+
"zweck2": "MREF+DKBLHPO0000000172466",
|
60
|
+
"zweck3": "CRED+DE98DKB00000000048\nSVWZ+KARTEN NR. 99200559451\n5214 LH57538284 453,14\n"
|
61
|
+
},
|
62
|
+
|
63
|
+
# Überweisung (POST-Daten)
|
64
|
+
|
65
|
+
betrag: Betrag im Format 000,00 (Komma als Dezimaltrennzeichen)
|
66
|
+
blz: Bankleitzahl des Gegenkontos
|
67
|
+
name: Inhaber-Name des Gegenkontos
|
68
|
+
konto: Kontonummer des Gegenkontos
|
69
|
+
konto_id: ID des eigenen Kontos
|
70
|
+
zweck: Verwendungszweck Zeile 1
|
71
|
+
--- optional: ---
|
72
|
+
zweck2: optional: Verwendungszweck Zeile 2
|
73
|
+
zweck3: optional: Verwendungszweck Zeile 3
|
74
|
+
zweck{nr}: optional: Weitere Verwendungszweck-Zeilen
|
75
|
+
termin: optional: "true" wenn die Überweisung als Termin-Überweisung ausgeführt werden soll
|
76
|
+
textschluessel: optional: Textschlüssel (Nummer)
|
77
|
+
umbuchung: optional: "true" wenn der Auftrag als Bank-interne Umbuchung ausgeführt werden soll
|
78
|
+
datum: optional: Ausführungstermin im Format TT.MM.JJJJ
|
79
|
+
|
80
|
+
# Konto
|
81
|
+
|
82
|
+
{
|
83
|
+
"bezeichnung": "XY-Konto",
|
84
|
+
"bic": "...",
|
85
|
+
"blz": "...",
|
86
|
+
"iban": "...",
|
87
|
+
"id": "1",
|
88
|
+
"kontonummer": "...",
|
89
|
+
"kundennummer": "...",
|
90
|
+
"name": "NACHNAME, VORNAME",
|
91
|
+
"passport_class": "de.willuhn.jameica.hbci.passports.pintan.server.PassportImpl",
|
92
|
+
"saldo": "42.42",
|
93
|
+
"saldo_datum": "2014-04-11 23:36:59.0",
|
94
|
+
"waehrung": "EUR"
|
95
|
+
}
|
96
|
+
|
97
|
+
# Sync-Job
|
98
|
+
|
99
|
+
{
|
100
|
+
"class": "class de.willuhn.jameica.hbci.synchronize.hbci.HBCISynchronizeJobKontoauszug",
|
101
|
+
"konto": "1",
|
102
|
+
"name": "Extra-Konto, Kto. 554xxx [Bankname]: Ums�tze/Salden abrufen"
|
103
|
+
}
|
104
|
+
|
105
|
+
# Create Überweisung response
|
106
|
+
|
107
|
+
{
|
108
|
+
"ausgefuehrt"=>"0",
|
109
|
+
"betrag"=>"0.01",
|
110
|
+
"empfaenger_blz"=>"50010517",
|
111
|
+
"empfaenger_konto"=>"5546169034",
|
112
|
+
"empfaenger_name"=>"Phillip Oertel",
|
113
|
+
"id"=>"1",
|
114
|
+
"konto_id"=>"2",
|
115
|
+
"termin"=>"Sat Apr 12 00:41:45 CEST 2014",
|
116
|
+
"zweck"=>"Hibiscus Test"
|
117
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path("../lib/hibiscus/version", __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = "hibiscus-ruby"
|
5
|
+
gem.version = Hibiscus::VERSION
|
6
|
+
gem.platform = Gem::Platform::RUBY
|
7
|
+
gem.authors = ["Phillip Oertel"]
|
8
|
+
gem.summary = %q{A Ruby client for the HBCI-compliant Hibiscus payment server.}
|
9
|
+
gem.license = "MIT"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($/)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(spec)/})
|
14
|
+
gem.require_path = "lib"
|
15
|
+
|
16
|
+
%w(rake httparty).each do |g|
|
17
|
+
gem.add_runtime_dependency g
|
18
|
+
end
|
19
|
+
|
20
|
+
gem.add_development_dependency 'rspec'
|
21
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'httparty'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Hibiscus
|
6
|
+
|
7
|
+
class Client
|
8
|
+
|
9
|
+
attr_reader :config
|
10
|
+
|
11
|
+
include Singleton
|
12
|
+
|
13
|
+
def get(path, options = {})
|
14
|
+
http_request(:get, path, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def post(path, body = {})
|
18
|
+
http_request(:post, path, {body: body})
|
19
|
+
end
|
20
|
+
|
21
|
+
def http_lib
|
22
|
+
HTTParty
|
23
|
+
end
|
24
|
+
|
25
|
+
def config=(options)
|
26
|
+
@config = Config.generate(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
# allows Hibiscus::Client.config = ...
|
30
|
+
def self.config=(config)
|
31
|
+
instance.config = config
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.config
|
35
|
+
instance.config
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def http_request(method, path, options)
|
41
|
+
uri = request_uri(path)
|
42
|
+
options = config.merge(options)
|
43
|
+
#puts "#{method.upcase} #{uri}" # TODO remove
|
44
|
+
json = http_lib.public_send(method, uri, options)
|
45
|
+
JSON.parse(json)
|
46
|
+
end
|
47
|
+
|
48
|
+
def request_uri(path)
|
49
|
+
if config[:base_uri]
|
50
|
+
# URI.join wasn't helpful here, unfortunately (it removes the path component on base_uri)
|
51
|
+
[config[:base_uri].sub(/\/?\Z/, ''), path.sub(/\A\/?/, '')].join('/')
|
52
|
+
else
|
53
|
+
path
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Hibiscus
|
2
|
+
class Client
|
3
|
+
class Config
|
4
|
+
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def self.generate(options = {})
|
8
|
+
new.generate(options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate(options)
|
12
|
+
@options = options
|
13
|
+
config = { basic_auth: {} }
|
14
|
+
config[:basic_auth].merge!(username_config)
|
15
|
+
config[:basic_auth].merge!(password_config)
|
16
|
+
config.merge!(verify_ssl_config)
|
17
|
+
config.merge!(base_uri_config)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def verify_ssl_config
|
23
|
+
verify = options.has_key?(:verify_ssl) ? !!options[:verify_ssl] : defaults[:verify]
|
24
|
+
{ verify: verify }
|
25
|
+
end
|
26
|
+
|
27
|
+
def username_config
|
28
|
+
username = options.has_key?(:username) ? options[:username] : defaults[:basic_auth][:username]
|
29
|
+
{ username: username }
|
30
|
+
end
|
31
|
+
|
32
|
+
def password_config
|
33
|
+
options.has_key?(:password) ? { password: options[:password] } : {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def base_uri_config
|
37
|
+
uri = options.has_key?(:base_uri) ? options[:base_uri] : defaults[:base_uri]
|
38
|
+
{ base_uri: uri }
|
39
|
+
end
|
40
|
+
|
41
|
+
def defaults
|
42
|
+
{
|
43
|
+
basic_auth: { username: 'admin' },
|
44
|
+
verify: false,
|
45
|
+
base_uri: 'https://localhost:8080/webadmin/rest/hibiscus'
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Hibiscus
|
2
|
+
|
3
|
+
class StatementLines < Resource
|
4
|
+
|
5
|
+
PATHS = {
|
6
|
+
search: '/umsaetze/query/{term}',
|
7
|
+
latest: '/konto/{account-id}/umsaetze/days/{days}'
|
8
|
+
}
|
9
|
+
|
10
|
+
def search(term)
|
11
|
+
get(PATHS[:search].gsub('{term}', term.to_s))
|
12
|
+
end
|
13
|
+
|
14
|
+
def latest(account_id, days = 30)
|
15
|
+
get(PATHS[:latest].gsub('{account-id}', account_id.to_s).gsub('{days}', days.to_s))
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Hibiscus
|
2
|
+
|
3
|
+
class Transfer < Resource
|
4
|
+
|
5
|
+
PATHS = {
|
6
|
+
delete: '/ueberweisung/delete/{id}',
|
7
|
+
pending: '/ueberweisung/list/open',
|
8
|
+
create: '/ueberweisung/create'
|
9
|
+
}
|
10
|
+
|
11
|
+
def delete(id)
|
12
|
+
get(PATHS[:delete].gsub('{id}', id.to_s))
|
13
|
+
end
|
14
|
+
|
15
|
+
def pending
|
16
|
+
get(PATHS[:pending])
|
17
|
+
end
|
18
|
+
|
19
|
+
# FIXME does not work yet
|
20
|
+
def create(data)
|
21
|
+
post(PATHS[:create], data)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'hibiscus/client_config'
|
3
|
+
|
4
|
+
module Hibiscus
|
5
|
+
describe Client::Config do
|
6
|
+
|
7
|
+
def config_for_options(options = {})
|
8
|
+
Hibiscus::Client::Config.generate(options)
|
9
|
+
end
|
10
|
+
|
11
|
+
context "defaults" do
|
12
|
+
it "is initialized with default values" do
|
13
|
+
config = config_for_options
|
14
|
+
config[:basic_auth][:username].should == 'admin'
|
15
|
+
config[:basic_auth][:password].should == nil
|
16
|
+
config[:verify].should == false
|
17
|
+
config[:base_uri].should == 'https://localhost:8080/webadmin/rest/hibiscus'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "setting username" do
|
22
|
+
|
23
|
+
it "defaults to 'admin'" do
|
24
|
+
config = config_for_options(password: 'foo')
|
25
|
+
config[:basic_auth][:username].should == 'admin'
|
26
|
+
config[:basic_auth][:password].should == 'foo'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can be set to an other value" do
|
30
|
+
config = config_for_options(password: 'foo', username: 'fritz')
|
31
|
+
config[:basic_auth][:username].should == 'fritz'
|
32
|
+
config[:basic_auth][:password].should == 'foo'
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
context "setting password" do
|
38
|
+
|
39
|
+
it "has no default" do
|
40
|
+
config = config_for_options
|
41
|
+
config[:basic_auth].should_not have_key(:password)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "can be set" do
|
45
|
+
config = config_for_options(password: '123456')
|
46
|
+
config[:basic_auth][:password].should == '123456'
|
47
|
+
config[:basic_auth][:username].should == 'admin'
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
context "setting verify_ssl" do
|
53
|
+
|
54
|
+
it "is set to false by default" do
|
55
|
+
config = config_for_options
|
56
|
+
config[:verify].should == false
|
57
|
+
end
|
58
|
+
|
59
|
+
it "verify_ssl true sets true" do
|
60
|
+
config = config_for_options(verify_ssl: true)
|
61
|
+
config[:verify].should == true
|
62
|
+
end
|
63
|
+
|
64
|
+
it "verify_ssl nil sets false" do
|
65
|
+
config = config_for_options(verify_ssl: nil)
|
66
|
+
config[:verify].should == false
|
67
|
+
end
|
68
|
+
|
69
|
+
it "verify_ssl: false sets false" do
|
70
|
+
config = config_for_options(verify_ssl: false)
|
71
|
+
config[:verify].should == false
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
context "setting base_uri" do
|
77
|
+
|
78
|
+
it "defaults to https://localhost:8080/webadmin/rest/hibiscus" do
|
79
|
+
config = config_for_options
|
80
|
+
config[:base_uri].should == 'https://localhost:8080/webadmin/rest/hibiscus'
|
81
|
+
end
|
82
|
+
|
83
|
+
it "can be set to an other value" do
|
84
|
+
base_uri_double = double('Some base URI')
|
85
|
+
config = config_for_options(base_uri: base_uri_double)
|
86
|
+
config[:base_uri].should == base_uri_double
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'hibiscus/client'
|
3
|
+
|
4
|
+
module Hibiscus
|
5
|
+
describe Client do
|
6
|
+
|
7
|
+
let(:klass) { Hibiscus::Client }
|
8
|
+
let(:instance) { Hibiscus::Client.instance }
|
9
|
+
|
10
|
+
it "is a singleton" do
|
11
|
+
Hibiscus::Client.instance.should == Hibiscus::Client.instance
|
12
|
+
expect { klass.new }.to raise_error(NoMethodError, /private method/)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "configuration" do
|
16
|
+
|
17
|
+
it "can be set on the class" do
|
18
|
+
klass.config = {password: "123456"}
|
19
|
+
instance.config[:basic_auth][:password].should == "123456"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "uses Hibiscus::Client::Config to generate config" do
|
23
|
+
options = double('User given config')
|
24
|
+
config = double('Parsed hibiscus config')
|
25
|
+
Hibiscus::Client::Config.should_receive(:generate).with(options).and_return(config)
|
26
|
+
klass.config = options
|
27
|
+
klass.config.should == config
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "response parsing" do
|
32
|
+
|
33
|
+
before { instance.stub(:config) { {} } }
|
34
|
+
|
35
|
+
it "returns JSON responses parsed" do
|
36
|
+
instance.http_lib.stub(:get) { '{"hello": "world"}' }
|
37
|
+
instance.get('/path').should == {"hello" => "world"}
|
38
|
+
end
|
39
|
+
|
40
|
+
it "raises an exception when JSON can't be parsed" do
|
41
|
+
instance.http_lib.stub(:get) { '{hello: "world"}' } # JSON requires double quotes everywhere
|
42
|
+
expect { instance.get('/path') }.to raise_error(JSON::ParserError, /unexpected token/)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "requests" do
|
47
|
+
|
48
|
+
before { instance.stub(:config) { {} } }
|
49
|
+
|
50
|
+
describe "get" do
|
51
|
+
context "path /path requested" do
|
52
|
+
it "does a get on the http_lib" do
|
53
|
+
instance.http_lib.should_receive(:get).with('/path', {}).and_return('{}')
|
54
|
+
instance.get('/path')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "post" do
|
60
|
+
context "no POST data given" do
|
61
|
+
it "doesen't pass body" do
|
62
|
+
instance.http_lib.should_receive(:post).with('/path', {body: {}}).and_return('{}')
|
63
|
+
instance.post('/path')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
context "POST data given" do
|
67
|
+
it "passes data as body" do
|
68
|
+
data = {hello: "world"}
|
69
|
+
instance.http_lib.should_receive(:post).with('/path', {body: data}).and_return('{}')
|
70
|
+
instance.post('/path', data)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# nothing here to see yet!
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hibiscus-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.pre
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Phillip Oertel
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
type: :runtime
|
15
|
+
prerelease: false
|
16
|
+
name: rake
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
type: :runtime
|
29
|
+
prerelease: false
|
30
|
+
name: httparty
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ! '>='
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
type: :development
|
43
|
+
prerelease: false
|
44
|
+
name: rspec
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- .gitignore
|
62
|
+
- .travis.yml
|
63
|
+
- Gemfile
|
64
|
+
- Gemfile.lock
|
65
|
+
- README.markdown
|
66
|
+
- Rakefile
|
67
|
+
- doc/hibiscus api.txt
|
68
|
+
- hibiscus-ruby.gemspec
|
69
|
+
- lib/hibiscus-ruby.rb
|
70
|
+
- lib/hibiscus/account.rb
|
71
|
+
- lib/hibiscus/client.rb
|
72
|
+
- lib/hibiscus/client_config.rb
|
73
|
+
- lib/hibiscus/jobs.rb
|
74
|
+
- lib/hibiscus/resource.rb
|
75
|
+
- lib/hibiscus/statement_lines.rb
|
76
|
+
- lib/hibiscus/transfer.rb
|
77
|
+
- lib/hibiscus/version.rb
|
78
|
+
- spec/hibiscus/client_config_spec.rb
|
79
|
+
- spec/hibiscus/client_spec.rb
|
80
|
+
- spec/spec_helper.rb
|
81
|
+
homepage:
|
82
|
+
licenses:
|
83
|
+
- MIT
|
84
|
+
metadata: {}
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ! '>'
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 1.3.1
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 2.1.9
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: A Ruby client for the HBCI-compliant Hibiscus payment server.
|
105
|
+
test_files:
|
106
|
+
- spec/hibiscus/client_config_spec.rb
|
107
|
+
- spec/hibiscus/client_spec.rb
|
108
|
+
- spec/spec_helper.rb
|