barzahlen 1.0.0 → 2.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/barzahlen.rb +7 -0
- data/lib/barzahlen/configuration.rb +32 -0
- data/lib/barzahlen/error.rb +116 -0
- data/lib/barzahlen/middleware.rb +69 -0
- data/lib/barzahlen/slip.rb +113 -0
- data/lib/barzahlen/version.rb +3 -0
- metadata +28 -77
- data/Gemfile +0 -3
- data/README.md +0 -207
- data/Rakefile +0 -3
- data/bin/test.rb +0 -30
- data/lib/barzahlen/api/online.rb +0 -58
- data/lib/barzahlen/api/online/api.rb +0 -67
- data/lib/barzahlen/api/online/hash_builder.rb +0 -43
- data/lib/barzahlen/api/online/http.rb +0 -31
- data/lib/barzahlen/api/online/notification_handler.rb +0 -50
- data/lib/barzahlen/api/online/response_parser.rb +0 -26
- data/lib/barzahlen/api/online/transaction.rb +0 -57
- data/lib/barzahlen/api/online/version.rb +0 -9
- data/lib/ruby_sdk.rb +0 -5
- data/lib/ruby_sdk/version.rb +0 -3
- data/spec/barzahlen/api/online/api_spec.rb +0 -86
- data/spec/barzahlen/api/online/hash_builder_spec.rb +0 -15
- data/spec/barzahlen/api/online/http_spec.rb +0 -13
- data/spec/barzahlen/api/online/notification_handler_spec.rb +0 -240
- data/spec/barzahlen/api/online/response_parser_spec.rb +0 -99
- data/spec/barzahlen/api/online/transaction_spec.rb +0 -108
- data/spec/barzahlen/api/online_spec.rb +0 -34
- data/spec/spec_helper.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba4379a6be0c31f8284c55d814bf82c97aa4a011
|
4
|
+
data.tar.gz: 9f28715903860a7685dc5fc32c0e734322b376ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 399821910a344a8568298987061ba410fc5a4917c89f0dcad08c8e395570546c2eca6f3f2abd5c99186221d7ae0e1db5fef121354f3cd0f7504ad3d8c8c671f0
|
7
|
+
data.tar.gz: 671aa7a285cbda33132585721adcee37c8002067dc18e2d7da076d8266ca518d41af087b0c9d74a22dfc9b47ea5080aa0f1df0fec618afd46a93ea4dfbc0ff1a
|
data/lib/barzahlen.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Barzahlen
|
2
|
+
class Configuration
|
3
|
+
API_HOST = "https://api.barzahlen.de/v2"
|
4
|
+
API_HOST_SANDBOX = "https://api-sandbox.barzahlen.de/v2"
|
5
|
+
|
6
|
+
attr_accessor :sandbox
|
7
|
+
attr_accessor :division_id
|
8
|
+
attr_accessor :payment_key
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@sandbox = false
|
12
|
+
@division_id = "not_valid_division_id"
|
13
|
+
@payment_key = "not_valid_payment_key"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
attr_accessor :configuration
|
19
|
+
|
20
|
+
def configuration
|
21
|
+
@configuration ||= Configuration.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def reset
|
25
|
+
@configuration = Configuration.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def configure
|
29
|
+
yield(configuration)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Barzahlen
|
4
|
+
module Error
|
5
|
+
class ClientError < StandardError
|
6
|
+
attr_reader :error_message
|
7
|
+
|
8
|
+
def initialize(error_message)
|
9
|
+
@error_message = error_message
|
10
|
+
end
|
11
|
+
|
12
|
+
def message
|
13
|
+
return @error_message
|
14
|
+
end
|
15
|
+
|
16
|
+
alias_method :to_s, :message
|
17
|
+
end
|
18
|
+
|
19
|
+
class SignatureError < ClientError; end
|
20
|
+
|
21
|
+
class ApiError < StandardError
|
22
|
+
attr_reader :error_class
|
23
|
+
attr_reader :error_code
|
24
|
+
attr_reader :error_message
|
25
|
+
attr_reader :documentation_url
|
26
|
+
attr_reader :request_id
|
27
|
+
|
28
|
+
def initialize(error_hash = {})
|
29
|
+
@error_class = error_hash[:error_class]
|
30
|
+
@error_code = error_hash[:error_code]
|
31
|
+
@error_message = error_hash[:message]
|
32
|
+
@documentation_url = error_hash[:documentation_url]
|
33
|
+
@request_id = error_hash[:request_id]
|
34
|
+
end
|
35
|
+
|
36
|
+
def message
|
37
|
+
return "Error occurred with: #{@error_message}"
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method :to_s, :message
|
41
|
+
end
|
42
|
+
|
43
|
+
class AuthError < ApiError; end
|
44
|
+
class TransportError < ApiError; end
|
45
|
+
class IdempotencyError < ApiError; end
|
46
|
+
class RateLimitError < ApiError; end
|
47
|
+
class InvalidFormatError < ApiError; end
|
48
|
+
class InvalidStateError < ApiError; end
|
49
|
+
class InvalidParameterError < ApiError; end
|
50
|
+
class NotAllowedError < ApiError; end
|
51
|
+
class ServerError < ApiError; end
|
52
|
+
class UnexpectedError < ApiError; end
|
53
|
+
|
54
|
+
# This generates ApiErrors based on the response error classes of CPS
|
55
|
+
def self.generate_error_from_response(response_body)
|
56
|
+
error_hash = generate_error_hash_with_symbols(response_body)
|
57
|
+
|
58
|
+
case error_hash[:error_class]
|
59
|
+
when "auth"
|
60
|
+
return AuthError.new( error_hash )
|
61
|
+
when "transport"
|
62
|
+
return TransportError.new( error_hash )
|
63
|
+
when "idempotency"
|
64
|
+
return IdempotencyError.new( error_hash )
|
65
|
+
when "rate_limit"
|
66
|
+
return RateLimitError.new( error_hash )
|
67
|
+
when "invalid_format"
|
68
|
+
return InvalidFormatError.new( error_hash )
|
69
|
+
when "invalid_state"
|
70
|
+
return InvalidStateError.new( error_hash )
|
71
|
+
when "invalid_parameter"
|
72
|
+
return InvalidParameterError.new( error_hash )
|
73
|
+
when "not_allowed"
|
74
|
+
return NotAllowedError.new( error_hash )
|
75
|
+
when "server_error"
|
76
|
+
return ServerError.new( error_hash )
|
77
|
+
else
|
78
|
+
return UnexpectedError.new( error_hash )
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def self.parse_json(json)
|
86
|
+
begin
|
87
|
+
hash = JSON.parse(json)
|
88
|
+
rescue JSON::ParserError => e
|
89
|
+
return nil
|
90
|
+
end
|
91
|
+
self.symbolize_keys(hash)
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.generate_error_hash_with_symbols(body)
|
95
|
+
if body.is_a?(Hash)
|
96
|
+
error_hash = self.symbolize_keys(body)
|
97
|
+
elsif body.is_a?(String)
|
98
|
+
error_hash = parse_json(body) || {}
|
99
|
+
else
|
100
|
+
error_hash = Hash.new
|
101
|
+
end
|
102
|
+
|
103
|
+
error_hash[:error_class] ||= "Unexpected_Error"
|
104
|
+
error_hash[:error_code] ||= "Unknown error code (body): \"#{body.to_s}\""
|
105
|
+
error_hash[:message] ||= "Please contact CPS to help us fix that as soon as possible."
|
106
|
+
error_hash[:documentation_url] ||= "https://www.cashpaymentsolutions.com/de/geschaeftskunden/kontakt"
|
107
|
+
error_hash[:request_id] ||= "not_available"
|
108
|
+
|
109
|
+
error_hash
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.symbolize_keys(hash)
|
113
|
+
Hash[hash.map{ |k, v| [k.to_sym, v] }]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "openssl"
|
2
|
+
require "uri"
|
3
|
+
require "time"
|
4
|
+
|
5
|
+
module Barzahlen
|
6
|
+
module Middleware
|
7
|
+
class Signature
|
8
|
+
def initialize(request, config)
|
9
|
+
@request = request
|
10
|
+
@config = config
|
11
|
+
end
|
12
|
+
|
13
|
+
def call (opts, request_uri, method, params, body)
|
14
|
+
parsed_uri = URI.parse(request_uri)
|
15
|
+
request_host_header = parsed_uri.host + ":" + parsed_uri.port.to_s
|
16
|
+
request_method = method
|
17
|
+
request_host_path = parsed_uri.path
|
18
|
+
request_query_string = URI.encode_www_form(params)
|
19
|
+
request_idempotency_key = opts[:headers]["Idempotency-Key"]
|
20
|
+
request_date_header = Time.now.utc.strftime("%a, %d %b %Y %H:%M:%S GMT")
|
21
|
+
|
22
|
+
signature = Barzahlen::Middleware.generate_bz_signature(
|
23
|
+
@config.payment_key,
|
24
|
+
request_host_header,
|
25
|
+
request_method,
|
26
|
+
request_date_header,
|
27
|
+
request_host_path,
|
28
|
+
request_query_string,
|
29
|
+
body,
|
30
|
+
request_idempotency_key
|
31
|
+
)
|
32
|
+
|
33
|
+
# Attach the Date, Authorization and Host to the request
|
34
|
+
new_headers = opts[:headers].merge(
|
35
|
+
{
|
36
|
+
Date: request_date_header,
|
37
|
+
Authorization: "BZ1-HMAC-SHA256 DivisionId=#{@config.division_id}, Signature=#{signature}",
|
38
|
+
Host: request_host_header,
|
39
|
+
}
|
40
|
+
)
|
41
|
+
|
42
|
+
return @request.call({headers: new_headers}, request_uri, method, params, body)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.generate_bz_signature(
|
47
|
+
payment_key,
|
48
|
+
request_host_header,
|
49
|
+
request_method,
|
50
|
+
request_date_header,
|
51
|
+
request_host_path = "",
|
52
|
+
request_query_string = "",
|
53
|
+
request_body = "",
|
54
|
+
request_idempotency_key = "")
|
55
|
+
|
56
|
+
request_body_digest = OpenSSL::Digest.hexdigest("SHA256", request_body.to_s || "")
|
57
|
+
|
58
|
+
raw_signature = "#{request_host_header}\n"\
|
59
|
+
"#{request_method.upcase}\n"\
|
60
|
+
"#{request_host_path}\n"\
|
61
|
+
"#{request_query_string}\n"\
|
62
|
+
"#{request_date_header}\n"\
|
63
|
+
"#{request_idempotency_key}\n"\
|
64
|
+
"#{request_body_digest}"
|
65
|
+
|
66
|
+
OpenSSL::HMAC.hexdigest("SHA256", payment_key, raw_signature)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require "securerandom"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module Barzahlen
|
5
|
+
IDEMPOTENCY_ENABLED = true
|
6
|
+
|
7
|
+
# For idempotency purposes a class takes care of refund and payment
|
8
|
+
|
9
|
+
class CreateSlipRequest
|
10
|
+
def initialize(opts = {})
|
11
|
+
@request = Barzahlen.get_grac_client(Barzahlen::IDEMPOTENCY_ENABLED)
|
12
|
+
@request_hash = opts
|
13
|
+
end
|
14
|
+
|
15
|
+
def send
|
16
|
+
@request_hash.freeze
|
17
|
+
@request_hash.each do |key, value|
|
18
|
+
@request_hash[key].freeze
|
19
|
+
end
|
20
|
+
Barzahlen.execute_with_error_handling do
|
21
|
+
@request.path("/slips").post(@request_hash)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# If idempotency is not important a simple request is more than enough
|
27
|
+
|
28
|
+
def self.retrieve_slip(slip_id)
|
29
|
+
self.execute_with_error_handling do
|
30
|
+
self.get_grac_client.path("/slips/{id}", id: slip_id.to_s).get
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.update_slip(slip_id, opts = {})
|
35
|
+
self.execute_with_error_handling do
|
36
|
+
self.get_grac_client.path("/slips/{id}", id: slip_id.to_s).patch(opts)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.resend_email(slip_id)
|
41
|
+
self.execute_with_error_handling do
|
42
|
+
self.get_grac_client.path("/slips/{id}/resend/email", id: slip_id.to_s).post
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.resend_text_message(slip_id)
|
47
|
+
self.execute_with_error_handling do
|
48
|
+
self.get_grac_client.path("/slips/{id}/resend/text_message", id: slip_id.to_s).post
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.invalidate_slip(slip_id)
|
53
|
+
self.execute_with_error_handling do
|
54
|
+
self.get_grac_client.path("/slips/{id}/invalidate", id: slip_id.to_s).post
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Handle a webhook request
|
59
|
+
|
60
|
+
def self.webhook_request(request)
|
61
|
+
bz_hook_format = request["Bz-Hook-Format"]
|
62
|
+
|
63
|
+
#stop processing when bz-hook-format = v1 because it will be or was send as v2
|
64
|
+
if bz_hook_format.include? "v1"
|
65
|
+
return nil
|
66
|
+
end
|
67
|
+
|
68
|
+
signature = Barzahlen::Middleware.generate_bz_signature(
|
69
|
+
Barzahlen.configuration.payment_key,
|
70
|
+
request["Host"] + ":" + (request["Port"] || "443"),
|
71
|
+
request["Method"] ? request["Method"].upcase : "POST",
|
72
|
+
request["Date"],
|
73
|
+
request["Path"].split("?")[0] || request["Path"],
|
74
|
+
request["Path"].split("?")[1] || "",
|
75
|
+
request["Body"]
|
76
|
+
)
|
77
|
+
|
78
|
+
if request["Bz-Signature"].include? signature
|
79
|
+
return JSON.parse(request["Body"])
|
80
|
+
else
|
81
|
+
raise Barzahlen::Error::SignatureError.new("Signature not valid")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
@@grac_client = nil
|
89
|
+
|
90
|
+
def self.get_grac_client(idempotency = false)
|
91
|
+
@@grac_client ||= Grac::Client.new(
|
92
|
+
Barzahlen.configuration.sandbox ?
|
93
|
+
Barzahlen::Configuration::API_HOST_SANDBOX : Barzahlen::Configuration::API_HOST,
|
94
|
+
middleware: [ [ Barzahlen::Middleware::Signature, Barzahlen.configuration ] ]
|
95
|
+
)
|
96
|
+
|
97
|
+
if idempotency
|
98
|
+
return @@grac_client.set( headers: { "Idempotency-Key" => SecureRandom.uuid} )
|
99
|
+
else
|
100
|
+
return @@grac_client
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.execute_with_error_handling
|
105
|
+
begin
|
106
|
+
yield
|
107
|
+
rescue Grac::Exception::RequestFailed => e
|
108
|
+
raise Barzahlen::Error.generate_error_from_response("")
|
109
|
+
rescue Grac::Exception::ClientException => e
|
110
|
+
raise Barzahlen::Error.generate_error_from_response(e.body)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
metadata
CHANGED
@@ -1,126 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: barzahlen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- David Leib
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 1.3.5
|
19
|
+
version: 10.4.1
|
23
20
|
type: :development
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
-
- - ">="
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 1.3.5
|
26
|
+
version: 10.4.1
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
28
|
+
name: rspec
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
30
|
requirements:
|
37
31
|
- - "~>"
|
38
32
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
40
|
-
- - ">="
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: 10.0.4
|
33
|
+
version: 3.2.0
|
43
34
|
type: :development
|
44
35
|
prerelease: false
|
45
36
|
version_requirements: !ruby/object:Gem::Requirement
|
46
37
|
requirements:
|
47
38
|
- - "~>"
|
48
39
|
- !ruby/object:Gem::Version
|
49
|
-
version:
|
50
|
-
- - ">="
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: 10.0.4
|
40
|
+
version: 3.2.0
|
53
41
|
- !ruby/object:Gem::Dependency
|
54
|
-
name:
|
42
|
+
name: rack-test
|
55
43
|
requirement: !ruby/object:Gem::Requirement
|
56
44
|
requirements:
|
57
45
|
- - "~>"
|
58
46
|
- !ruby/object:Gem::Version
|
59
|
-
version:
|
60
|
-
- - ">="
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
version: 2.14.1
|
47
|
+
version: 0.6.3
|
63
48
|
type: :development
|
64
49
|
prerelease: false
|
65
50
|
version_requirements: !ruby/object:Gem::Requirement
|
66
51
|
requirements:
|
67
52
|
- - "~>"
|
68
53
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
70
|
-
- - ">="
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
version: 2.14.1
|
54
|
+
version: 0.6.3
|
73
55
|
- !ruby/object:Gem::Dependency
|
74
|
-
name:
|
56
|
+
name: grac
|
75
57
|
requirement: !ruby/object:Gem::Requirement
|
76
58
|
requirements:
|
77
59
|
- - "~>"
|
78
60
|
- !ruby/object:Gem::Version
|
79
|
-
version:
|
80
|
-
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: 3.0.0
|
83
|
-
type: :development
|
61
|
+
version: 2.2.1
|
62
|
+
type: :runtime
|
84
63
|
prerelease: false
|
85
64
|
version_requirements: !ruby/object:Gem::Requirement
|
86
65
|
requirements:
|
87
66
|
- - "~>"
|
88
67
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
90
|
-
|
91
|
-
- !ruby/object:Gem::Version
|
92
|
-
version: 3.0.0
|
93
|
-
description: The official Ruby-SDK for accessing the Barzalen Payment Service
|
68
|
+
version: 2.2.1
|
69
|
+
description: This is a ruby gem to access the Barzahlen API v2.
|
94
70
|
email:
|
95
|
-
-
|
96
|
-
executables:
|
97
|
-
- test.rb
|
71
|
+
- david.leib@barzahlen.de
|
72
|
+
executables: []
|
98
73
|
extensions: []
|
99
74
|
extra_rdoc_files: []
|
100
75
|
files:
|
101
|
-
-
|
102
|
-
-
|
103
|
-
-
|
104
|
-
-
|
105
|
-
- lib/barzahlen/
|
106
|
-
- lib/barzahlen/
|
107
|
-
|
108
|
-
- lib/barzahlen/api/online/http.rb
|
109
|
-
- lib/barzahlen/api/online/notification_handler.rb
|
110
|
-
- lib/barzahlen/api/online/response_parser.rb
|
111
|
-
- lib/barzahlen/api/online/transaction.rb
|
112
|
-
- lib/barzahlen/api/online/version.rb
|
113
|
-
- lib/ruby_sdk.rb
|
114
|
-
- lib/ruby_sdk/version.rb
|
115
|
-
- spec/barzahlen/api/online/api_spec.rb
|
116
|
-
- spec/barzahlen/api/online/hash_builder_spec.rb
|
117
|
-
- spec/barzahlen/api/online/http_spec.rb
|
118
|
-
- spec/barzahlen/api/online/notification_handler_spec.rb
|
119
|
-
- spec/barzahlen/api/online/response_parser_spec.rb
|
120
|
-
- spec/barzahlen/api/online/transaction_spec.rb
|
121
|
-
- spec/barzahlen/api/online_spec.rb
|
122
|
-
- spec/spec_helper.rb
|
123
|
-
homepage: https://www.barzahlen.de/
|
76
|
+
- lib/barzahlen.rb
|
77
|
+
- lib/barzahlen/configuration.rb
|
78
|
+
- lib/barzahlen/error.rb
|
79
|
+
- lib/barzahlen/middleware.rb
|
80
|
+
- lib/barzahlen/slip.rb
|
81
|
+
- lib/barzahlen/version.rb
|
82
|
+
homepage: ''
|
124
83
|
licenses:
|
125
84
|
- MIT
|
126
85
|
metadata: {}
|
@@ -143,13 +102,5 @@ rubyforge_project:
|
|
143
102
|
rubygems_version: 2.2.2
|
144
103
|
signing_key:
|
145
104
|
specification_version: 4
|
146
|
-
summary: Barzahlen
|
147
|
-
test_files:
|
148
|
-
- spec/barzahlen/api/online/api_spec.rb
|
149
|
-
- spec/barzahlen/api/online/hash_builder_spec.rb
|
150
|
-
- spec/barzahlen/api/online/http_spec.rb
|
151
|
-
- spec/barzahlen/api/online/notification_handler_spec.rb
|
152
|
-
- spec/barzahlen/api/online/response_parser_spec.rb
|
153
|
-
- spec/barzahlen/api/online/transaction_spec.rb
|
154
|
-
- spec/barzahlen/api/online_spec.rb
|
155
|
-
- spec/spec_helper.rb
|
105
|
+
summary: Client gem for API Barzahlen v2.
|
106
|
+
test_files: []
|