buckaroo-ideal 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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