buckaruby 1.0.2 → 1.1.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 +5 -5
- data/.rubocop.yml +20 -4
- data/.travis.yml +7 -3
- data/CHANGELOG.md +6 -0
- data/Gemfile +3 -1
- data/README.md +58 -4
- data/Rakefile +2 -0
- data/buckaruby.gemspec +1 -1
- data/lib/buckaruby.rb +3 -1
- data/lib/buckaruby/action.rb +3 -0
- data/lib/buckaruby/configuration.rb +73 -0
- data/lib/buckaruby/currency.rb +4 -0
- data/lib/buckaruby/exception.rb +26 -0
- data/lib/buckaruby/gateway.rb +99 -45
- data/lib/buckaruby/iban.rb +2 -0
- data/lib/buckaruby/ideal.rb +5 -2
- data/lib/buckaruby/language.rb +2 -0
- data/lib/buckaruby/operation.rb +4 -0
- data/lib/buckaruby/payment_method.rb +5 -1
- data/lib/buckaruby/request.rb +70 -27
- data/lib/buckaruby/response.rb +106 -37
- data/lib/buckaruby/signature.rb +8 -9
- data/lib/buckaruby/support/case_insensitive_hash.rb +2 -0
- data/lib/buckaruby/transaction_status.rb +2 -0
- data/lib/buckaruby/transaction_type.rb +2 -0
- data/lib/buckaruby/version.rb +3 -1
- data/spec/buckaruby/configuration_spec.rb +113 -0
- data/spec/buckaruby/gateway_spec.rb +165 -83
- data/spec/buckaruby/iban_spec.rb +2 -0
- data/spec/buckaruby/signature_spec.rb +38 -17
- data/spec/buckaruby/support/case_insensitive_hash_spec.rb +2 -0
- data/spec/fixtures/responses/callback_invalid_signature.txt +1 -0
- data/spec/fixtures/responses/callback_payment_cancelled.txt +1 -0
- data/spec/fixtures/responses/callback_payment_empty_transaction_type.txt +1 -0
- data/spec/fixtures/responses/callback_payment_failed.txt +1 -0
- data/spec/fixtures/responses/callback_payment_pending.txt +1 -0
- data/spec/fixtures/responses/callback_payment_rejected.txt +1 -0
- data/spec/fixtures/responses/callback_payment_sepa.txt +1 -0
- data/spec/fixtures/responses/callback_payment_success.txt +1 -0
- data/spec/fixtures/responses/callback_recurrent_sepa.txt +1 -0
- data/spec/fixtures/responses/callback_recurrent_visa.txt +1 -0
- data/spec/fixtures/responses/callback_refund_ideal.txt +1 -0
- data/spec/fixtures/responses/callback_refund_paypal.txt +1 -0
- data/spec/fixtures/responses/callback_reversal_paypal.txt +1 -0
- data/spec/fixtures/responses/callback_reversal_sepa.txt +1 -0
- data/spec/fixtures/responses/callback_valid_signature.txt +1 -0
- data/spec/fixtures/responses/cancel_success.txt +1 -0
- data/spec/fixtures/responses/recurrent_transaction_success.txt +1 -0
- data/spec/fixtures/responses/refund_info_error.txt +1 -0
- data/spec/fixtures/responses/refund_info_success.txt +1 -0
- data/spec/fixtures/responses/refund_transaction_success.txt +1 -0
- data/spec/fixtures/responses/setup_transaction_success.txt +1 -0
- data/spec/fixtures/responses/status_cancellable.txt +1 -0
- data/spec/fixtures/responses/status_noncancellable.txt +1 -0
- data/spec/fixtures/responses/status_success.txt +1 -0
- data/spec/spec_helper.rb +2 -0
- metadata +54 -4
- data/lib/buckaruby/urls.rb +0 -6
data/lib/buckaruby/iban.rb
CHANGED
data/lib/buckaruby/ideal.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Buckaruby
|
2
4
|
module Ideal
|
3
5
|
ISSUERS = {
|
4
6
|
"ABNANL2A" => "ABN AMRO",
|
5
7
|
"ASNBNL21" => "ASN Bank",
|
6
|
-
"BUNQNL2A" => "
|
8
|
+
"BUNQNL2A" => "bunq",
|
7
9
|
"INGBNL2A" => "ING",
|
8
10
|
"KNABNL2H" => "Knab bank",
|
11
|
+
"MOYONL21" => "Moneyou",
|
9
12
|
"RABONL2U" => "Rabobank",
|
10
13
|
"RBRBNL21" => "RegioBank",
|
11
14
|
"SNSBNL2A" => "SNS Bank",
|
12
15
|
"TRIONL2U" => "Triodos Bank",
|
13
16
|
"FVLBNL22" => "Van Lanschot"
|
14
|
-
}
|
17
|
+
}.freeze
|
15
18
|
end
|
16
19
|
end
|
data/lib/buckaruby/language.rb
CHANGED
data/lib/buckaruby/operation.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Buckaruby
|
2
4
|
module PaymentMethod
|
3
|
-
IDEAL = "ideal"
|
5
|
+
IDEAL = "ideal" # iDEAL collecting
|
6
|
+
IDEAL_PROCESSING = "idealprocessing" # iDEAL processing
|
7
|
+
|
4
8
|
SEPA_DIRECT_DEBIT = "sepadirectdebit"
|
5
9
|
PAYPAL = "paypal"
|
6
10
|
BANCONTACT_MISTER_CASH = "bancontactmrcash"
|
data/lib/buckaruby/request.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bigdecimal'
|
2
4
|
require 'cgi'
|
3
5
|
require 'date'
|
4
|
-
require 'logger'
|
5
6
|
require 'net/http'
|
6
7
|
require 'openssl'
|
7
8
|
require 'uri'
|
@@ -9,20 +10,18 @@ require 'uri'
|
|
9
10
|
module Buckaruby
|
10
11
|
# Base class for any request.
|
11
12
|
class Request
|
12
|
-
def initialize(
|
13
|
-
@
|
14
|
-
|
15
|
-
@logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
|
13
|
+
def initialize(config)
|
14
|
+
@config = config
|
15
|
+
@logger = config.logger
|
16
16
|
end
|
17
17
|
|
18
18
|
def execute(options)
|
19
|
-
uri = URI.parse(api_url)
|
19
|
+
uri = URI.parse(@config.api_url)
|
20
20
|
uri.query = "op=#{options[:operation]}" if options[:operation]
|
21
21
|
|
22
|
-
|
23
|
-
response = parse_response(raw_response)
|
22
|
+
response = post_buckaroo(uri, build_request_data(options))
|
24
23
|
|
25
|
-
@logger.debug("[execute] response: #{response.inspect}")
|
24
|
+
# @logger.debug("[execute] response: #{response.inspect}")
|
26
25
|
|
27
26
|
response
|
28
27
|
end
|
@@ -46,7 +45,8 @@ module Buckaruby
|
|
46
45
|
raise InvalidResponseException, raw_response
|
47
46
|
end
|
48
47
|
|
49
|
-
|
48
|
+
raw_response.body
|
49
|
+
|
50
50
|
# Try to catch some common exceptions Net::HTTP might raise
|
51
51
|
rescue Errno::ETIMEDOUT, Errno::EINVAL, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH,
|
52
52
|
IOError, SocketError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::OpenTimeout,
|
@@ -55,14 +55,14 @@ module Buckaruby
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def build_request_data(options)
|
58
|
-
params = { brq_websitekey: @
|
58
|
+
params = { brq_websitekey: @config.website }
|
59
59
|
|
60
60
|
params.merge!(build_request_params(options))
|
61
61
|
|
62
62
|
params[:add_buckaruby] = "Buckaruby #{Buckaruby::VERSION}"
|
63
63
|
|
64
64
|
# Sign the data with our secret key.
|
65
|
-
params[:brq_signature] = Signature.generate_signature(params, @
|
65
|
+
params[:brq_signature] = Signature.generate_signature(params, @config)
|
66
66
|
|
67
67
|
params
|
68
68
|
end
|
@@ -70,20 +70,6 @@ module Buckaruby
|
|
70
70
|
def post_data(params)
|
71
71
|
params.map { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
72
72
|
end
|
73
|
-
|
74
|
-
def parse_response(body)
|
75
|
-
query = CGI.parse(body)
|
76
|
-
query.each { |key, value| query[key] = value.first }
|
77
|
-
query
|
78
|
-
end
|
79
|
-
|
80
|
-
def test?
|
81
|
-
@options[:mode] == :test
|
82
|
-
end
|
83
|
-
|
84
|
-
def api_url
|
85
|
-
test? ? Urls::TEST_URL : Urls::PRODUCTION_URL
|
86
|
-
end
|
87
73
|
end
|
88
74
|
|
89
75
|
# Base class for a transaction request.
|
@@ -97,7 +83,7 @@ module Buckaruby
|
|
97
83
|
brq_payment_method: options[:payment_method],
|
98
84
|
brq_culture: options[:culture] || Language::DUTCH,
|
99
85
|
brq_currency: options[:currency] || Currency::EURO,
|
100
|
-
brq_amount: BigDecimal
|
86
|
+
brq_amount: BigDecimal(options[:amount].to_s).to_s("F"),
|
101
87
|
brq_invoicenumber: options[:invoicenumber]
|
102
88
|
}
|
103
89
|
|
@@ -127,6 +113,12 @@ module Buckaruby
|
|
127
113
|
brq_service_ideal_issuer: options[:payment_issuer],
|
128
114
|
brq_service_ideal_version: "2"
|
129
115
|
)
|
116
|
+
when PaymentMethod::IDEAL_PROCESSING
|
117
|
+
params.merge!(
|
118
|
+
brq_service_idealprocessing_action: Action::PAY,
|
119
|
+
brq_service_idealprocessing_issuer: options[:payment_issuer],
|
120
|
+
brq_service_idealprocessing_version: "2"
|
121
|
+
)
|
130
122
|
when PaymentMethod::SEPA_DIRECT_DEBIT
|
131
123
|
params.merge!(
|
132
124
|
brq_service_sepadirectdebit_action: Action::PAY,
|
@@ -175,6 +167,44 @@ module Buckaruby
|
|
175
167
|
end
|
176
168
|
end
|
177
169
|
|
170
|
+
# Request for a creating a refund.
|
171
|
+
class RefundTransactionRequest < Request
|
172
|
+
def execute(options)
|
173
|
+
super(options.merge(operation: Operation::TRANSACTION_REQUEST))
|
174
|
+
end
|
175
|
+
|
176
|
+
def build_request_params(options)
|
177
|
+
params = {
|
178
|
+
brq_payment_method: options[:payment_method],
|
179
|
+
brq_amount_credit: BigDecimal(options[:amount].to_s).to_s("F"),
|
180
|
+
brq_currency: options[:currency] || Currency::EURO,
|
181
|
+
brq_invoicenumber: options[:invoicenumber]
|
182
|
+
}
|
183
|
+
|
184
|
+
key = :"brq_service_#{options[:payment_method]}_action"
|
185
|
+
params[key] = Action::REFUND
|
186
|
+
|
187
|
+
params[:brq_originaltransaction] = options[:transaction_id]
|
188
|
+
|
189
|
+
params
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Request for retrieving refund information.
|
194
|
+
class RefundInfoRequest < Request
|
195
|
+
def execute(options)
|
196
|
+
super(options.merge(operation: Operation::REFUND_INFO))
|
197
|
+
end
|
198
|
+
|
199
|
+
def build_request_params(options)
|
200
|
+
params = {}
|
201
|
+
|
202
|
+
params[:brq_transaction] = options[:transaction_id]
|
203
|
+
|
204
|
+
params
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
178
208
|
# Request for getting the status of a transaction.
|
179
209
|
class StatusRequest < Request
|
180
210
|
def execute(options)
|
@@ -190,4 +220,17 @@ module Buckaruby
|
|
190
220
|
params
|
191
221
|
end
|
192
222
|
end
|
223
|
+
|
224
|
+
# Request for cancelling a transaction.
|
225
|
+
class CancelRequest < Request
|
226
|
+
def execute(options)
|
227
|
+
super(options.merge(operation: Operation::CANCEL_TRANSACTION))
|
228
|
+
end
|
229
|
+
|
230
|
+
def build_request_params(options)
|
231
|
+
params = { brq_transaction: options[:transaction_id] }
|
232
|
+
|
233
|
+
params
|
234
|
+
end
|
235
|
+
end
|
193
236
|
end
|
data/lib/buckaruby/response.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cgi'
|
1
4
|
require 'date'
|
2
5
|
|
3
6
|
module Buckaruby
|
@@ -5,32 +8,74 @@ module Buckaruby
|
|
5
8
|
class Response
|
6
9
|
attr_reader :params
|
7
10
|
|
8
|
-
def initialize(
|
9
|
-
@
|
11
|
+
def initialize(body, config)
|
12
|
+
@logger = config.logger
|
13
|
+
|
14
|
+
@response = parse_response(body)
|
15
|
+
@params = Support::CaseInsensitiveHash.new(@response)
|
16
|
+
|
17
|
+
@logger.debug("[response] params: #{params.inspect}")
|
18
|
+
|
19
|
+
verify_signature!(@response, config)
|
20
|
+
end
|
21
|
+
|
22
|
+
def status
|
23
|
+
# See http://support.buckaroo.nl/index.php/Statuscodes
|
24
|
+
case params[:brq_statuscode]
|
25
|
+
when '190'
|
26
|
+
TransactionStatus::SUCCESS
|
27
|
+
when '490', '491', '492'
|
28
|
+
TransactionStatus::FAILED
|
29
|
+
when '690'
|
30
|
+
TransactionStatus::REJECTED
|
31
|
+
when '790', '791', '792', '793'
|
32
|
+
TransactionStatus::PENDING
|
33
|
+
when '890', '891'
|
34
|
+
TransactionStatus::CANCELLED
|
35
|
+
end
|
36
|
+
end
|
10
37
|
|
11
|
-
|
38
|
+
def timestamp
|
39
|
+
parse_time(params[:brq_timestamp])
|
12
40
|
end
|
13
41
|
|
14
42
|
private
|
15
43
|
|
16
|
-
def
|
44
|
+
def parse_response(body)
|
45
|
+
if body.is_a?(Hash)
|
46
|
+
response = body
|
47
|
+
else
|
48
|
+
response = CGI.parse(body)
|
49
|
+
response.each { |key, value| response[key] = value.first }
|
50
|
+
end
|
51
|
+
|
52
|
+
response
|
53
|
+
end
|
54
|
+
|
55
|
+
def verify_signature!(response, config)
|
17
56
|
if params[:brq_apiresult] != "Fail"
|
18
57
|
sent_signature = params[:brq_signature]
|
19
|
-
generated_signature = Signature.generate_signature(response,
|
58
|
+
generated_signature = Signature.generate_signature(response, config)
|
20
59
|
|
21
60
|
if sent_signature != generated_signature
|
22
61
|
raise SignatureException.new(sent_signature, generated_signature)
|
23
62
|
end
|
24
63
|
end
|
25
64
|
end
|
65
|
+
|
66
|
+
def parse_time(time)
|
67
|
+
time ? Time.strptime(time, '%Y-%m-%d %H:%M:%S') : nil
|
68
|
+
end
|
26
69
|
end
|
27
70
|
|
28
|
-
# Base
|
29
|
-
|
71
|
+
# Base for a transaction response.
|
72
|
+
module TransactionResponse
|
30
73
|
def account_bic
|
31
74
|
case payment_method
|
32
75
|
when PaymentMethod::IDEAL
|
33
76
|
params[:brq_service_ideal_consumerbic]
|
77
|
+
when PaymentMethod::IDEAL_PROCESSING
|
78
|
+
params[:brq_service_idealprocessing_consumerbic]
|
34
79
|
when PaymentMethod::SEPA_DIRECT_DEBIT
|
35
80
|
params[:brq_service_sepadirectdebit_customerbic]
|
36
81
|
end
|
@@ -40,6 +85,8 @@ module Buckaruby
|
|
40
85
|
case payment_method
|
41
86
|
when PaymentMethod::IDEAL
|
42
87
|
params[:brq_service_ideal_consumeriban]
|
88
|
+
when PaymentMethod::IDEAL_PROCESSING
|
89
|
+
params[:brq_service_idealprocessing_consumeriban]
|
43
90
|
when PaymentMethod::SEPA_DIRECT_DEBIT
|
44
91
|
params[:brq_service_sepadirectdebit_customeriban]
|
45
92
|
end
|
@@ -49,6 +96,8 @@ module Buckaruby
|
|
49
96
|
case payment_method
|
50
97
|
when PaymentMethod::IDEAL
|
51
98
|
params[:brq_service_ideal_consumername] || params[:brq_customer_name]
|
99
|
+
when PaymentMethod::IDEAL_PROCESSING
|
100
|
+
params[:brq_service_idealprocessing_consumername] || params[:brq_customer_name]
|
52
101
|
when PaymentMethod::SEPA_DIRECT_DEBIT
|
53
102
|
params[:brq_service_sepadirectdebit_customername] || params[:brq_customer_name]
|
54
103
|
end
|
@@ -90,10 +139,6 @@ module Buckaruby
|
|
90
139
|
params[:brq_relatedtransaction_reversal]
|
91
140
|
end
|
92
141
|
|
93
|
-
def timestamp
|
94
|
-
parse_time(params[:brq_timestamp])
|
95
|
-
end
|
96
|
-
|
97
142
|
def transaction_id
|
98
143
|
params[:brq_transactions]
|
99
144
|
end
|
@@ -123,19 +168,7 @@ module Buckaruby
|
|
123
168
|
end
|
124
169
|
|
125
170
|
def transaction_status
|
126
|
-
|
127
|
-
case params[:brq_statuscode]
|
128
|
-
when '190'
|
129
|
-
TransactionStatus::SUCCESS
|
130
|
-
when '490', '491', '492'
|
131
|
-
TransactionStatus::FAILED
|
132
|
-
when '690'
|
133
|
-
TransactionStatus::REJECTED
|
134
|
-
when '790', '791', '792', '793'
|
135
|
-
TransactionStatus::PENDING
|
136
|
-
when '890', '891'
|
137
|
-
TransactionStatus::CANCELLED
|
138
|
-
end
|
171
|
+
status
|
139
172
|
end
|
140
173
|
|
141
174
|
def to_h
|
@@ -165,39 +198,75 @@ module Buckaruby
|
|
165
198
|
date ? Date.strptime(date, '%Y-%m-%d') : nil
|
166
199
|
end
|
167
200
|
|
168
|
-
def parse_time(time)
|
169
|
-
time ? Time.strptime(time, '%Y-%m-%d %H:%M:%S') : nil
|
170
|
-
end
|
171
|
-
|
172
201
|
def parse_payment_method(method)
|
173
202
|
method ? method.downcase : nil
|
174
203
|
end
|
175
204
|
end
|
176
205
|
|
177
|
-
# Base class for a
|
178
|
-
class
|
179
|
-
def initialize(response,
|
180
|
-
super(response,
|
206
|
+
# Base class for a response via the API.
|
207
|
+
class ApiResponse < Response
|
208
|
+
def initialize(response, config)
|
209
|
+
super(response, config)
|
181
210
|
|
182
|
-
if params[:brq_apiresult].nil? || params[:brq_apiresult]
|
211
|
+
if params[:brq_apiresult].nil? || params[:brq_apiresult].casecmp("fail").zero?
|
183
212
|
raise ApiException, params
|
184
213
|
end
|
185
214
|
end
|
186
215
|
end
|
187
216
|
|
188
217
|
# Response when creating a new transaction.
|
189
|
-
class SetupTransactionResponse <
|
218
|
+
class SetupTransactionResponse < ApiResponse
|
219
|
+
include TransactionResponse
|
190
220
|
end
|
191
221
|
|
192
222
|
# Response when creating a recurrent transaction.
|
193
|
-
class RecurrentTransactionResponse <
|
223
|
+
class RecurrentTransactionResponse < ApiResponse
|
224
|
+
include TransactionResponse
|
225
|
+
end
|
226
|
+
|
227
|
+
# Response when creating a refund transaction.
|
228
|
+
class RefundTransactionResponse < ApiResponse
|
229
|
+
include TransactionResponse
|
230
|
+
end
|
231
|
+
|
232
|
+
# Response when retrieving the refund information.
|
233
|
+
class RefundInfoResponse < ApiResponse
|
234
|
+
def payment_method
|
235
|
+
params[:brq_refundinfo_1_servicecode]
|
236
|
+
end
|
237
|
+
|
238
|
+
def refundable?
|
239
|
+
!params[:brq_refundinfo_1_isrefundable].nil? && params[:brq_refundinfo_1_isrefundable].casecmp("true").zero?
|
240
|
+
end
|
241
|
+
|
242
|
+
def maximum_amount
|
243
|
+
params[:brq_refundinfo_1_maximumrefundamount]
|
244
|
+
end
|
245
|
+
|
246
|
+
def invoicenumber
|
247
|
+
params[:brq_refundinfo_1_invoice]
|
248
|
+
end
|
249
|
+
|
250
|
+
def currency
|
251
|
+
params[:brq_refundinfo_1_refundcurrency]
|
252
|
+
end
|
194
253
|
end
|
195
254
|
|
196
255
|
# Response when getting the status of a transaction.
|
197
|
-
class StatusResponse <
|
256
|
+
class StatusResponse < ApiResponse
|
257
|
+
include TransactionResponse
|
258
|
+
|
259
|
+
def cancellable?
|
260
|
+
!params[:brq_transaction_cancelable].nil? && params[:brq_transaction_cancelable].casecmp("true").zero?
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Response when cancelling a transaction.
|
265
|
+
class CancelResponse < ApiResponse
|
198
266
|
end
|
199
267
|
|
200
268
|
# Response when verifying the Buckaroo callback.
|
201
|
-
class CallbackResponse <
|
269
|
+
class CallbackResponse < Response
|
270
|
+
include TransactionResponse
|
202
271
|
end
|
203
272
|
end
|