buckaroo-ideal 0.0.1

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.
@@ -0,0 +1,26 @@
1
+ $LOAD_PATH << File.expand_path('..', __FILE__)
2
+
3
+ module Buckaroo
4
+ module Ideal
5
+ # The banks that are supported by Buckaroo's iDEAL platform
6
+ BANKS = %w[ ABNAMRO ASNBANK FRIESLAND
7
+ INGBANK RABOBANK SNSBANK
8
+ SNSREGIO TRIODOS LANSCHOT ]
9
+
10
+ # The currencies that are supported by Buckaroo's iDEAL platform
11
+ CURRENCIES = %w[ EUR ]
12
+
13
+ # The languages supported by Buckaroo's user interface:
14
+ LANGUAGES = %w[ NL EN DE FR ]
15
+
16
+ autoload :VERSION, 'buckaroo-ideal/version'
17
+ autoload :Config, 'buckaroo-ideal/config'
18
+ autoload :Order, 'buckaroo-ideal/order'
19
+ autoload :Response, 'buckaroo-ideal/response'
20
+ autoload :ResponseSignature, 'buckaroo-ideal/response_signature'
21
+ autoload :RequestSignature, 'buckaroo-ideal/request_signature'
22
+ autoload :Request, 'buckaroo-ideal/request'
23
+ autoload :Status, 'buckaroo-ideal/status'
24
+ autoload :Util, 'buckaroo-ideal/util'
25
+ end
26
+ end
@@ -0,0 +1,101 @@
1
+ module Buckaroo
2
+ module Ideal
3
+ #
4
+ # Configuration singleton for storing settings required for making
5
+ # transactions.
6
+ #
7
+ class Config
8
+ class << self
9
+ # The gateway URL that is used to post form data to.
10
+ #
11
+ # @return [String] The gateway URL
12
+ attr_accessor :gateway_url
13
+
14
+ # The merchant-key is supllied by Buckaroo. Every application MUST have
15
+ # it's own merchant key.
16
+ #
17
+ # @return [String] The merchant-key for the application
18
+ attr_accessor :merchant_key
19
+
20
+ # The secret_key should only be known by your application and Buckaroo.
21
+ # It is used to sign orders and validate transactions.
22
+ #
23
+ # @return [String] The shared secret key that is used to sign
24
+ # transaction requests
25
+ attr_accessor :secret_key
26
+
27
+ # If test_mode is enabled, transactions will be registered by Buckaroo,
28
+ # but clients will not be forwared to the iDEAL page of their bank.
29
+ #
30
+ # Clients will be redirected back to the success_url of your application
31
+ #
32
+ # @return [Boolean] Test mode on/off
33
+ attr_accessor :test_mode
34
+
35
+ # @return [String] The URL the user will be redirected to after a
36
+ # successful transaction
37
+ attr_accessor :success_url
38
+
39
+ # @return [String] The URL the user will be redirected to after a failed
40
+ # transaction
41
+ attr_accessor :reject_url
42
+
43
+ # @return [String] The URL the user will be redirected to after an error
44
+ # occured during the transaction
45
+ attr_accessor :error_url
46
+
47
+ # @return [String] The HTTP method that will be used to return the user
48
+ # back to the application after a transaction
49
+ attr_accessor :return_method
50
+
51
+ # There are 2 styles that you can use to integrate Buckaroo iDEAL:
52
+ # * POPUP - The transaction is performed in a popup
53
+ # * PAGE - The transaction is performed in the original window
54
+ #
55
+ # @return [String] The style that is being used
56
+ attr_accessor :style
57
+
58
+ # If the POPUP style is being used, you can autoclose the popup after
59
+ # a transaction. You will have to provide information about the
60
+ # transaction to the user on the page he will arrive on.
61
+ #
62
+ # @return [Boolean] Autoclose the popup after a transaction
63
+ attr_accessor :autoclose_popup
64
+
65
+ # Default settings
66
+ def defaults
67
+ {
68
+ gateway_url: 'https://payment.buckaroo.nl/gateway/payment.asp',
69
+ merchant_key: nil,
70
+ secret_key: nil,
71
+ test_mode: false,
72
+ success_url: nil,
73
+ reject_url: nil,
74
+ error_url: nil,
75
+ return_method: 'POST',
76
+ style: 'PAGE',
77
+ autoclose_popup: false
78
+ }
79
+ end
80
+
81
+ # Configure the integration with Buckaroo
82
+ def configure(settings = {})
83
+ defaults.merge(settings).each do |key, value|
84
+ set key, value
85
+ end
86
+ end
87
+
88
+ # Reset the configuration to the default values
89
+ def reset
90
+ configure({})
91
+ end
92
+
93
+ private
94
+
95
+ def set(key, value)
96
+ instance_variable_set(:"@#{key}", value)
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,46 @@
1
+ require 'active_support/core_ext/module/delegation'
2
+
3
+ module Buckaroo
4
+ module Ideal
5
+ class Order
6
+ def self.defaults
7
+ { currency: 'EUR' }
8
+ end
9
+
10
+ # @return [Float] The total amount that this order is for
11
+ attr_accessor :amount
12
+
13
+ # @return [String] The currency that is being used for the transaction
14
+ attr_accessor :currency
15
+
16
+ # @return [String] The bank that will be used for the order's transaction.
17
+ attr_accessor :bank
18
+
19
+ # @return [String] The description for the transaction
20
+ attr_accessor :description
21
+
22
+ # @return [String] The reference that will be passed to the response URLs
23
+ attr_accessor :reference
24
+
25
+ # @return [String] The invoice number that is associated with the order
26
+ attr_accessor :invoice_number
27
+
28
+ # Initialize a new +Order+ with the given settings. Uses the defaults from
29
+ # +Buckaroo::Ideal::Order.defaults+ for settings that are not specified.
30
+ #
31
+ # @return [Buckaroo::Ideal::Order] The +Order+ instance
32
+ def initialize(settings = {})
33
+ settings = self.class.defaults.merge(settings)
34
+ settings.each do |key, value|
35
+ set key, value
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def set(key, value)
42
+ instance_variable_set(:"@#{key}", value)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,164 @@
1
+ require 'active_support/core_ext/module/delegation'
2
+
3
+ module Buckaroo
4
+ module Ideal
5
+ #
6
+ # A class to help with the generation of payment forms for the Buckaroo
7
+ # Payment Gateway.
8
+ #
9
+ # A form has a number of required parameters that are retreived from the
10
+ # +Buckaroo::Idea::Order+:
11
+ # * +currency+ -- required; but set by default to 'EUR'
12
+ # * +invoice_number+ -- required; not set by default
13
+ # * +amount+ -- required; this is the whole amount, it is automatically
14
+ # converted to cents
15
+ # * +bank+ -- optional
16
+ # * +description+ -- optional
17
+ #
18
+ # It is possible to set the following options for this form:
19
+ # * +language+ -- required, defaults to 'NL'
20
+ # * +return_method+ -- required, defaults to +Buckaroo::Ideal::Config.return_method+
21
+ # * +style+ -- required, defaults to +Buckaroo::Ideal::Config.style+
22
+ # * +autoclose_popup+ -- required, defaults to +Buckaroo::Ideal::Config.autoclose_popup+
23
+ # * +reference+ -- optional
24
+ # * +success_url+ -- optional according to documentation
25
+ # * +reject_url+ -- optional
26
+ # * +error_url+ -- optional
27
+ #
28
+ # The +test_mode+, +gateway_url+ and +merchant_key+ are read from
29
+ # +Buckaroo::Ideal::Config+.
30
+ #
31
+ # To access the information required to create a form, instantiate a new
32
+ # +Buckaroo::Ideal::Request+ with an +Buckaroo::Ideal::Order+ instance:
33
+ #
34
+ # order = Buckaroo::Ideal::Order.new(amount: 100, invoice_number: 'EETNU-123')
35
+ # request = Buckaroo::Ideal::Request.new(order)
36
+ #
37
+ # You can then use the information to create a form. An example in Rails:
38
+ #
39
+ # <%= form_tag request.gateway_url do %>
40
+ # <% request.parameters.each do |name, value| %>
41
+ # <%= hidden_field_tag name, value %>
42
+ # <% end %>
43
+ # <%= submit_tag 'Proceed to payment' %>
44
+ # <% end %>
45
+ class Request
46
+ def self.defaults
47
+ {
48
+ language: 'NL',
49
+ success_url: Config.success_url,
50
+ reject_url: Config.reject_url,
51
+ error_url: Config.error_url,
52
+ return_method: Config.return_method,
53
+ style: Config.style,
54
+ autoclose_popup: Config.autoclose_popup
55
+ }
56
+ end
57
+
58
+ # @return [String] The configured gateway_url in +Buckaroo::Ideal::Config+
59
+ delegate :gateway_url, to: Config
60
+
61
+ # @return [Boolean] The configured test_mode in +Buckaroo::Ideal::Config+
62
+ delegate :test_mode, to: Config
63
+
64
+ # @return [String] The configured merchant_key in +Buckaroo::Ideal::Config+
65
+ delegate :merchant_key, to: Config
66
+
67
+ # @return [Buckaroo::Ideal::Order] The order for which the payment request
68
+ # is being made
69
+ attr_reader :order
70
+
71
+ # @return [String] The language in wich Buckaroo's user interface is
72
+ # presented.
73
+ attr_accessor :language
74
+
75
+ # Defaults to the configured +Buckaroo::Ideal::Config.success_url+, but
76
+ # can be overwritten in the +Order+ instance.
77
+ #
78
+ # @return [String] The URL the user will be redirected to after a
79
+ # successful transaction
80
+ attr_accessor :success_url
81
+
82
+ # Defaults to the configured +Buckaroo::Ideal::Config.reject_url+, but can
83
+ # be overwritten in the +Order+ instance.
84
+ #
85
+ # @return [String] The URL the user will be redirected to after a failed
86
+ # transaction
87
+ attr_accessor :reject_url
88
+
89
+ # Defaults to the configured +Buckaroo::Ideal::Config.error_url+, but can
90
+ # be overwritten in the +Order+ instance.
91
+ #
92
+ # @return [String] The URL the user will be redirected to after an error
93
+ # occured during the transaction
94
+ attr_accessor :error_url
95
+
96
+ # Defaults to the configured +Buckaroo::Ideal::Config.return_method+, but
97
+ # can be overwritten in the +Order+ instance.
98
+ #
99
+ # @return [String] The HTTP method that will be used to return the user
100
+ # back to the application after a transaction
101
+ attr_accessor :return_method
102
+
103
+ # Defaults to the configured +Buckaroo::Ideal::Config.style+, but can be
104
+ # overwritten in the +Order+ instance.
105
+ #
106
+ # @return [String] The style that is being used
107
+ attr_accessor :style
108
+
109
+ # Defaults to the configured +Buckaroo::Ideal::Config.autoclose_popup+,
110
+ # but can be overwritten in the +Order+ instance.
111
+ #
112
+ # @return [Boolean] Autoclose the popup after a transaction
113
+ attr_accessor :autoclose_popup
114
+
115
+ # Initialize a new +Buckaroo::Ideal::Request+ instance for the given
116
+ # order.
117
+ #
118
+ # @param [Buckaroo::Ideal::Order] The order that needs to be signed.
119
+ # @param [Hash] The settings for this form.
120
+ # @return [Buckaroo::Ideal::Request] The form for the order instance.
121
+ def initialize(order, settings = {})
122
+ @order = order
123
+ settings = self.class.defaults.merge(settings)
124
+ settings.each do |key, value|
125
+ set key, value
126
+ end
127
+ end
128
+
129
+ def parameters
130
+ {
131
+ 'BPE_Currency' => order.currency,
132
+ 'BPE_Invoice' => order.invoice_number,
133
+ 'BPE_Amount' => to_cents(order.amount),
134
+ 'BPE_Merchant' => merchant_key,
135
+ 'BPE_Language' => language,
136
+ 'BPE_Mode' => to_numeric_boolean(test_mode),
137
+ 'BPE_Return_Method' => return_method,
138
+ 'BPE_Style' => style,
139
+ 'BPE_Autoclose_Popup' => to_numeric_boolean(autoclose_popup),
140
+ 'BPE_Signature2' => signature
141
+ }.merge compact({
142
+ 'BPE_Issuer' => order.bank,
143
+ 'BPE_Description' => order.description,
144
+ 'BPE_Reference' => order.reference,
145
+ 'BPE_Return_Success' => success_url,
146
+ 'BPE_Return_Reject' => reject_url,
147
+ 'BPE_Return_Error' => error_url
148
+ })
149
+ end
150
+
151
+ private
152
+
153
+ def signature
154
+ RequestSignature.new(order).signature
155
+ end
156
+
157
+ def set(key, value)
158
+ instance_variable_set(:"@#{key}", value)
159
+ end
160
+
161
+ include Util
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,74 @@
1
+ require 'digest/md5'
2
+ require 'active_support/core_ext/module/delegation'
3
+
4
+ module Buckaroo
5
+ module Ideal
6
+ #
7
+ # Digital signature generator for +Buckaroo::Ideal::Order+ instances.
8
+ #
9
+ # A digital signature is used to sign your request so the Buckaroo Payment
10
+ # Service can validate that the request was made by your application.
11
+ #
12
+ # A digital signature is composed by generating a MD5 hash of the following
13
+ # values:
14
+ # * Merchant Key: The +merchant_key+ that is provided by Buckaroo and set
15
+ # in +Buckaroo::Ideal::Config+.
16
+ # * Invoice Number: The +invoice_number+ that is set in your
17
+ # +Buckaroo::Ideal::Order+ instance.
18
+ # * Amount: The +amount+ that is set in your +Buckaroo::Ideal::Order+
19
+ # instance in cents.
20
+ # * Currency: The +currency+ that is set in your +Buckaroo::Ideal::Order+
21
+ # instance.
22
+ # * Mode: The +test_mode+ that is set in +Buckaroo::Ideal::Config+.
23
+ #
24
+ # To create a signature for an +Buckaroo::Ideal::Order+, instantiate a new
25
+ # +Buckaroo::Ideal::RequestSignature+ and provide the order:
26
+ #
27
+ # order = Buckaroo::Ideal::Order.new(amount: 100, invoice_number: 'EETNU-123')
28
+ # signature = Buckaroo::Ideal::Signature.new(order)
29
+ class RequestSignature
30
+
31
+ # @return [Buckaroo::Ideal::Order] The order that is being signed.
32
+ attr_reader :order
33
+
34
+ # @return [Boolean] The configured test_mode in +Buckaroo::Ideal::Config+
35
+ delegate :test_mode, to: Config
36
+
37
+ # @return [String] The configured merchant_key in +Buckaroo::Ideal::Config+
38
+ delegate :merchant_key, to: Config
39
+
40
+ # @return [String] The configured secret_key in +Buckaroo::Ideal::Config+
41
+ delegate :secret_key, to: Config
42
+
43
+ # Initialize a new +Buckaroo::Ideal::Signature+ instance for the given
44
+ # order.
45
+ #
46
+ # @param [Buckaroo::Ideal::Order] The order that needs to be signed.
47
+ # @param [String] The secret key that is used to sign the order.
48
+ # Defaults to the configured +Buckaroo::Ideal::Config.secret_key+.
49
+ # @return [Buckaroo::Ideal::Signature] The signature for the order
50
+ # instance.
51
+ def initialize(order)
52
+ @order = order
53
+ end
54
+
55
+ def signature
56
+ salt = [
57
+ merchant_key,
58
+ to_normalized_string(order.invoice_number),
59
+ to_cents(order.amount),
60
+ order.currency,
61
+ to_numeric_boolean(test_mode),
62
+ secret_key
63
+ ].join
64
+
65
+ Digest::MD5.hexdigest(salt)
66
+ end
67
+ alias_method :to_s, :signature
68
+
69
+ private
70
+
71
+ include Util
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,68 @@
1
+ require 'active_support/core_ext/module/delegation'
2
+ require 'time'
3
+
4
+ module Buckaroo
5
+ module Ideal
6
+ class Response
7
+ # @return [Hash] The raw parameters that form the heart of the response
8
+ attr_reader :parameters
9
+
10
+ # @return [String] The unique code that is given to the transaction by
11
+ # Buckaroo's Payment Gateway
12
+ attr_reader :transaction_id
13
+
14
+ # @return [Buckaroo::Ideal::Status] The status of the transaction
15
+ attr_reader :status
16
+
17
+ # @return [String] The reference that was given to the
18
+ # +Buckaroo::Ideal::Order+
19
+ attr_reader :reference
20
+
21
+ # @return [String] The invoice_number that was given to the
22
+ # +Buckaroo::Ideal::Order+
23
+ attr_reader :invoice_number
24
+
25
+ # @return [Buckaroo::Ideal::ResponseSignature] The signature of the
26
+ # transaction, which can be used to validate it's authenticity.
27
+ attr_reader :signature
28
+
29
+ # @return [String] The currency that was used during the transaction
30
+ attr_reader :currency
31
+
32
+ # @return [Time] The date and time of the transaction
33
+ attr_reader :time
34
+
35
+ # @return [String] The timestamp of the transaction
36
+ attr_reader :timestamp
37
+
38
+ # @return [Float] The amount that was transferred during the transaction
39
+ attr_reader :amount
40
+
41
+ # @return [Boolean] Returns +true+ if the transaction was a test, +false+
42
+ # if it was real
43
+ attr_reader :test_mode
44
+
45
+ def initialize(params = {})
46
+ @parameters = params
47
+ @transaction_id = parameters['bpe_trx']
48
+ @reference = parameters['bpe_reference']
49
+ @invoice_number = parameters['bpe_invoice']
50
+ @currency = parameters['bpe_currency']
51
+ @timestamp = parameters['bpe_timestamp']
52
+ @time = Time.parse(timestamp)
53
+ @amount = from_cents(parameters['bpe_amount'])
54
+ @test_mode = from_numeric_boolean(parameters['bpe_mode'])
55
+ @status = Status.new(parameters['bpe_result'])
56
+ @signature = ResponseSignature.new(self, parameters['bpe_signature2'])
57
+ end
58
+
59
+ def valid?
60
+ signature.valid?
61
+ end
62
+
63
+ private
64
+
65
+ include Util
66
+ end
67
+ end
68
+ end