offsite_payments 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +70 -0
  4. data/lib/offsite_payments.rb +46 -0
  5. data/lib/offsite_payments/action_view_helper.rb +72 -0
  6. data/lib/offsite_payments/helper.rb +119 -0
  7. data/lib/offsite_payments/integrations.rb +14 -0
  8. data/lib/offsite_payments/integrations/a1agregator.rb +245 -0
  9. data/lib/offsite_payments/integrations/authorize_net_sim.rb +580 -0
  10. data/lib/offsite_payments/integrations/bit_pay.rb +150 -0
  11. data/lib/offsite_payments/integrations/bogus.rb +32 -0
  12. data/lib/offsite_payments/integrations/chronopay.rb +283 -0
  13. data/lib/offsite_payments/integrations/citrus.rb +227 -0
  14. data/lib/offsite_payments/integrations/direc_pay.rb +339 -0
  15. data/lib/offsite_payments/integrations/directebanking.rb +237 -0
  16. data/lib/offsite_payments/integrations/doku.rb +171 -0
  17. data/lib/offsite_payments/integrations/dotpay.rb +166 -0
  18. data/lib/offsite_payments/integrations/dwolla.rb +160 -0
  19. data/lib/offsite_payments/integrations/e_payment_plans.rb +146 -0
  20. data/lib/offsite_payments/integrations/easy_pay.rb +137 -0
  21. data/lib/offsite_payments/integrations/epay.rb +161 -0
  22. data/lib/offsite_payments/integrations/first_data.rb +133 -0
  23. data/lib/offsite_payments/integrations/gestpay.rb +201 -0
  24. data/lib/offsite_payments/integrations/hi_trust.rb +179 -0
  25. data/lib/offsite_payments/integrations/ipay88.rb +240 -0
  26. data/lib/offsite_payments/integrations/klarna.rb +291 -0
  27. data/lib/offsite_payments/integrations/liqpay.rb +216 -0
  28. data/lib/offsite_payments/integrations/maksuturva.rb +231 -0
  29. data/lib/offsite_payments/integrations/mollie_ideal.rb +213 -0
  30. data/lib/offsite_payments/integrations/moneybookers.rb +199 -0
  31. data/lib/offsite_payments/integrations/nochex.rb +228 -0
  32. data/lib/offsite_payments/integrations/pag_seguro.rb +255 -0
  33. data/lib/offsite_payments/integrations/paxum.rb +114 -0
  34. data/lib/offsite_payments/integrations/pay_fast.rb +269 -0
  35. data/lib/offsite_payments/integrations/paydollar.rb +142 -0
  36. data/lib/offsite_payments/integrations/payflow_link.rb +194 -0
  37. data/lib/offsite_payments/integrations/paypal.rb +362 -0
  38. data/lib/offsite_payments/integrations/paypal_payments_advanced.rb +23 -0
  39. data/lib/offsite_payments/integrations/paysbuy.rb +71 -0
  40. data/lib/offsite_payments/integrations/payu_in.rb +266 -0
  41. data/lib/offsite_payments/integrations/payu_in_paisa.rb +46 -0
  42. data/lib/offsite_payments/integrations/platron.rb +153 -0
  43. data/lib/offsite_payments/integrations/pxpay.rb +271 -0
  44. data/lib/offsite_payments/integrations/quickpay.rb +232 -0
  45. data/lib/offsite_payments/integrations/rbkmoney.rb +110 -0
  46. data/lib/offsite_payments/integrations/robokassa.rb +154 -0
  47. data/lib/offsite_payments/integrations/sage_pay_form.rb +425 -0
  48. data/lib/offsite_payments/integrations/two_checkout.rb +332 -0
  49. data/lib/offsite_payments/integrations/universal.rb +180 -0
  50. data/lib/offsite_payments/integrations/valitor.rb +200 -0
  51. data/lib/offsite_payments/integrations/verkkomaksut.rb +143 -0
  52. data/lib/offsite_payments/integrations/web_pay.rb +186 -0
  53. data/lib/offsite_payments/integrations/webmoney.rb +119 -0
  54. data/lib/offsite_payments/integrations/wirecard_checkout_page.rb +359 -0
  55. data/lib/offsite_payments/integrations/world_pay.rb +273 -0
  56. data/lib/offsite_payments/notification.rb +71 -0
  57. data/lib/offsite_payments/return.rb +37 -0
  58. data/lib/offsite_payments/version.rb +3 -0
  59. metadata +270 -0
@@ -0,0 +1,216 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ # Documentation: https://www.liqpay.com/?do=pages&p=cnb10
4
+ module Liqpay
5
+ mattr_accessor :service_url
6
+ self.service_url = 'https://liqpay.com/?do=clickNbuy'
7
+
8
+ mattr_accessor :signature_parameter_name
9
+ self.signature_parameter_name = 'signature'
10
+
11
+ def self.helper(order, account, options = {})
12
+ Helper.new(order, account, options)
13
+ end
14
+
15
+ def self.notification(query_string, options = {})
16
+ Notification.new(query_string, options)
17
+ end
18
+
19
+ def self.return(query_string)
20
+ Return.new(query_string)
21
+ end
22
+
23
+ class Helper < OffsitePayments::Helper
24
+ def initialize(order, account, options = {})
25
+ @secret = options.delete(:secret)
26
+ super
27
+
28
+ add_field 'version', '1.2'
29
+ end
30
+
31
+ def form_fields
32
+ xml = "<request>
33
+ <version>1.2</version>
34
+ <result_url>#{@fields["result_url"]}</result_url>
35
+ <server_url>#{@fields["server_url"]}</server_url>
36
+ <merchant_id>#{@fields["merchant_id"]}</merchant_id>
37
+ <order_id>#{@fields["order_id"]}</order_id>
38
+ <amount>#{@fields["amount"]}</amount>
39
+ <currency>#{@fields["currency"]}</currency>
40
+ <description>#{@fields["description"]}</description>
41
+ <default_phone>#{@fields["default_phone"]}</default_phone>
42
+ <pay_way>card</pay_way>
43
+ </request>".strip
44
+ sign = Base64.encode64(Digest::SHA1.digest("#{@secret}#{xml}#{@secret}")).strip
45
+ {"operation_xml" => Base64.encode64(xml), "signature" => sign}
46
+ end
47
+
48
+ mapping :account, 'merchant_id'
49
+ mapping :amount, 'amount'
50
+ mapping :currency, 'currency'
51
+ mapping :order, 'order_id'
52
+ mapping :description, 'description'
53
+ mapping :phone, 'default_phone'
54
+
55
+ mapping :notify_url, 'server_url'
56
+ mapping :return_url, 'result_url'
57
+ end
58
+
59
+ class Notification < OffsitePayments::Notification
60
+ def self.recognizes?(params)
61
+ params.has_key?('amount') && params.has_key?('order_id')
62
+ end
63
+
64
+ def initialize(post, options = {})
65
+ raise ArgumentError if post.blank?
66
+ super
67
+ @params.merge!(Hash.from_xml(Base64.decode64(xml))["response"])
68
+ end
69
+
70
+ def xml
71
+ @params["operation_xml"]
72
+ end
73
+
74
+ def complete?
75
+ status == 'success'
76
+ end
77
+
78
+ def account
79
+ params['merchant_id']
80
+ end
81
+
82
+ def amount
83
+ BigDecimal.new(gross)
84
+ end
85
+
86
+ def item_id
87
+ params['order_id']
88
+ end
89
+
90
+ def transaction_id
91
+ params['transaction_id']
92
+ end
93
+
94
+ def action_name
95
+ params['action_name'] # either 'result_url' or 'server_url'
96
+ end
97
+
98
+ def version
99
+ params['version']
100
+ end
101
+
102
+ def sender_phone
103
+ params['sender_phone']
104
+ end
105
+
106
+ def security_key
107
+ params[OffsitePayments::Integrations::Liqpay.signature_parameter_name]
108
+ end
109
+
110
+ def gross
111
+ params['amount']
112
+ end
113
+
114
+ def currency
115
+ params['currency']
116
+ end
117
+
118
+ def status
119
+ params['status'] # 'success', 'failure' or 'wait_secure'
120
+ end
121
+
122
+ def code
123
+ params['code']
124
+ end
125
+
126
+ def generate_signature_string
127
+ "#{@options[:secret]}#{Base64.decode64(xml)}#{@options[:secret]}"
128
+ end
129
+
130
+ def generate_signature
131
+ Base64.encode64(Digest::SHA1.digest(generate_signature_string)).strip
132
+ end
133
+
134
+ def acknowledge(authcode = nil)
135
+ security_key == generate_signature
136
+ end
137
+ end
138
+
139
+ class Return < OffsitePayments::Return
140
+ def self.recognizes?(params)
141
+ params.has_key?('amount') && params.has_key?('order_id')
142
+ end
143
+
144
+ def initialize(post)
145
+ super
146
+ xml = Base64.decode64(@params["operation_xml"])
147
+ @params.merge!(Hash.from_xml(xml)["response"])
148
+ end
149
+
150
+ def complete?
151
+ status == 'success'
152
+ end
153
+
154
+ def account
155
+ params['merchant_id']
156
+ end
157
+
158
+ def amount
159
+ BigDecimal.new(gross)
160
+ end
161
+
162
+ def item_id
163
+ params['order_id']
164
+ end
165
+
166
+ def transaction_id
167
+ params['transaction_id']
168
+ end
169
+
170
+ def action_name
171
+ params['action_name'] # either 'result_url' or 'server_url'
172
+ end
173
+
174
+ def version
175
+ params['version']
176
+ end
177
+
178
+ def sender_phone
179
+ params['sender_phone']
180
+ end
181
+
182
+ def security_key
183
+ params[OffsitePayments::Integrations::Liqpay.signature_parameter_name]
184
+ end
185
+
186
+ def gross
187
+ params['amount']
188
+ end
189
+
190
+ def currency
191
+ params['currency']
192
+ end
193
+
194
+ def status
195
+ params['status'] # 'success', 'failure' or 'wait_secure'
196
+ end
197
+
198
+ def code
199
+ params['code']
200
+ end
201
+
202
+ def generate_signature_string
203
+ ['', version, @options[:secret], action_name, sender_phone, account, gross, currency, item_id, transaction_id, status, code, ''].flatten.compact.join('|')
204
+ end
205
+
206
+ def generate_signature
207
+ Base64.encode64(Digest::SHA1.digest(generate_signature_string)).gsub(/\n/, '')
208
+ end
209
+
210
+ def acknowledge(authcode = nil)
211
+ security_key == generate_signature
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,231 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ # USAGE:
4
+ #
5
+ # First define Maksuturva seller id and authcode in an initializer:
6
+ #
7
+ # MAKSUTURVA_SELLERID = "testikauppias"
8
+ # MAKSUTURVA_AUTHCODE = "11223344556677889900"
9
+ #
10
+ # Then in view do something like this (use dynamic values for your app)
11
+ #
12
+ # <% payment_service_for 2, MAKSUTURVA_SELLERID,
13
+ # :amount => "200,00", :currency => 'EUR', :credential2 => MAKSUTURVA_AUTHCODE,
14
+ # :service => :maksuturva do |service|
15
+ # service.pmt_reference = "134662"
16
+ # service.pmt_duedate = "24.06.2012"
17
+ # service.customer :phone => "0405051909",
18
+ # :email => "antti@example.com"
19
+ # service.billing_address :city => "Helsinki",
20
+ # :address1 => "Lorem street",
21
+ # :state => "-",
22
+ # :country => 'Finland',
23
+ # :zip => "00530"
24
+ # service.pmt_orderid = "2"
25
+ # service.pmt_buyername = "Antti Akonniemi"
26
+ # service.pmt_deliveryname = "Antti Akonniemi"
27
+ # service.pmt_deliveryaddress = "Köydenpunojankatu 13"
28
+ # service.pmt_deliverypostalcode = "00180"
29
+ # service.pmt_deliverycity = "Helsinki"
30
+ # service.pmt_deliverycountry = "FI"
31
+ # service.pmt_rows = 1
32
+ # service.pmt_row_name1 = "testi"
33
+ # service.pmt_row_desc1 = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
34
+ # service.pmt_row_articlenr1 = "1"
35
+ # service.pmt_row_quantity1 = "1"
36
+ # service.pmt_row_deliverydate1 = "26.6.2012"
37
+ # service.pmt_row_price_gross1 = "200,00"
38
+ # service.pmt_row_vat1= "23,00"
39
+ # service.pmt_row_discountpercentage1 = "0,00"
40
+ # service.pmt_row_type1 = "1"
41
+ # service.pmt_charset = "UTF-8"
42
+ # service.pmt_charsethttp = "UTF-8"
43
+ #
44
+ # service.return_url "http://localhost:3000/process"
45
+ # service.cancel_return_url "http://example.com"
46
+ # service.pmt_errorreturn "http://example.com"
47
+ #
48
+ # service.pmt_delayedpayreturn "http://example.com"
49
+ # service.pmt_escrow "N"
50
+ # service.pmt_escrowchangeallowed "N"
51
+ # service.pmt_sellercosts "0,00"
52
+ # service.pmt_keygeneration "001"
53
+ # %>
54
+ #
55
+ # Then in the controller handle the return with something like this
56
+ #
57
+ # def ipn
58
+ # notify = OffsitePayments::Integrations::Maksuturva::Notification.new(params)
59
+ #
60
+ # if notify.acknowledge(MAKSUTURVA_AUTHCODE)
61
+ # # Process order
62
+ # else
63
+ # # Show error
64
+ # end
65
+ # end
66
+ #
67
+ # For full list of available parameters etc check the integration documents
68
+ # here:
69
+ #
70
+ # https://www.maksuturva.fi/services/vendor_services/integration_guidelines.html
71
+ module Maksuturva
72
+ mattr_accessor :service_url
73
+ self.service_url = 'https://www.maksuturva.fi/NewPaymentExtended.pmt'
74
+
75
+ def self.notification(post)
76
+ Notification.new(post)
77
+ end
78
+
79
+ class Helper < OffsitePayments::Helper
80
+ def initialize(order, account, options = {})
81
+ md5secret options.delete(:credential2)
82
+ super
83
+ add_field("pmt_action", "NEW_PAYMENT_EXTENDED")
84
+ add_field("pmt_version", "0004")
85
+ add_field("pmt_sellerid", account)
86
+ add_field("pmt_hashversion", "MD5")
87
+ end
88
+
89
+ def md5secret(value)
90
+ @md5secret = value
91
+ end
92
+
93
+ def form_fields
94
+ @fields.merge("pmt_hash" => generate_md5string)
95
+ end
96
+
97
+ def generate_md5string
98
+ fields = [@fields["pmt_action"], @fields["pmt_version"]]
99
+ fields += [@fields["pmt_selleriban"]] unless @fields["pmt_selleriban"].nil?
100
+ fields += [@fields["pmt_id"], @fields["pmt_orderid"], @fields["pmt_reference"], @fields["pmt_duedate"],
101
+ @fields["pmt_amount"], @fields["pmt_currency"], @fields["pmt_okreturn"], @fields["pmt_errorreturn"], @fields["pmt_cancelreturn"],
102
+ @fields["pmt_delayedpayreturn"], @fields["pmt_escrow"], @fields["pmt_escrowchangeallowed"]]
103
+
104
+ fields += [@fields["pmt_invoicefromseller"]] unless @fields["pmt_invoicefromseller"].nil?
105
+ fields += [@fields["pmt_paymentmethod"]] unless @fields["pmt_paymentmethod"].nil?
106
+ fields += [@fields["pmt_buyeridentificationcode"]] unless @fields["pmt_buyeridentificationcode"].nil?
107
+
108
+
109
+ fields += [@fields["pmt_buyername"], @fields["pmt_buyeraddress"], @fields["pmt_buyerpostalcode"], @fields["pmt_buyercity"],
110
+ @fields["pmt_buyercountry"], @fields["pmt_deliveryname"], @fields["pmt_deliveryaddress"], @fields["pmt_deliverypostalcode"], @fields["pmt_deliverycity"],
111
+ @fields["pmt_deliverycountry"], @fields["pmt_sellercosts"]]
112
+
113
+ (1..@fields["pmt_rows"].to_i).each do |i|
114
+ fields += [@fields["pmt_row_name#{i}"], @fields["pmt_row_desc#{i}"], @fields["pmt_row_quantity#{i}"]]
115
+ fields += [@fields["pmt_row_articlenr#{i}"]] unless @fields["pmt_row_articlenr#{i}"].nil?
116
+ fields += [@fields["pmt_row_unit#{i}"]] unless @fields["pmt_row_unit#{i}"].nil?
117
+ fields += [@fields["pmt_row_deliverydate#{i}"]]
118
+ fields += [@fields["pmt_row_price_gross#{i}"]] unless @fields["pmt_row_price_gross#{i}"].nil?
119
+ fields += [@fields["pmt_row_price_net#{i}"]] unless @fields["pmt_row_price_net#{i}"].nil?
120
+ fields += [@fields["pmt_row_vat#{i}"], @fields["pmt_row_discountpercentage#{i}"], @fields["pmt_row_type#{i}"]]
121
+ end
122
+ fields += [@md5secret]
123
+ fields = fields.join("&") + "&"
124
+ Digest::MD5.hexdigest(fields).upcase
125
+ end
126
+
127
+ mapping :pmt_selleriban, "pmt_selleriban"
128
+ mapping :pmt_reference, "pmt_reference"
129
+ mapping :pmt_duedate, "pmt_duedate"
130
+ mapping :pmt_userlocale, "pmt_userlocale"
131
+ mapping :pmt_escrow, "pmt_escrow"
132
+ mapping :pmt_escrowchangeallowed, "pmt_escrowchangeallowed"
133
+ mapping :pmt_invoicefromseller, "pmt_invoicefromseller"
134
+ mapping :pmt_paymentmethod, "pmt_paymentmethod"
135
+ mapping :pmt_buyeridentificationcode, "pmt_buyeridentificationcode"
136
+ mapping :pmt_buyername, "pmt_buyername"
137
+
138
+ mapping :account, ''
139
+ mapping :currency, 'pmt_currency'
140
+ mapping :amount, 'pmt_amount'
141
+
142
+ mapping :order, 'pmt_id'
143
+ mapping :pmt_orderid, 'pmt_orderid'
144
+ mapping :pmt_deliveryname, "pmt_deliveryname"
145
+ mapping :pmt_deliveryaddress, "pmt_deliveryaddress"
146
+ mapping :pmt_deliverypostalcode, "pmt_deliverypostalcode"
147
+ mapping :pmt_deliverycity, "pmt_deliverycity"
148
+ mapping :pmt_deliverycountry, "pmt_deliverycountry"
149
+ mapping :pmt_sellercosts, "pmt_sellercosts"
150
+ mapping :pmt_rows, "pmt_rows"
151
+
152
+ (1..499.to_i).each do |i|
153
+ mapping "pmt_row_name#{i}".to_sym, "pmt_row_name#{i}"
154
+ mapping "pmt_row_desc#{i}".to_sym, "pmt_row_desc#{i}"
155
+ mapping "pmt_row_quantity#{i}".to_sym, "pmt_row_quantity#{i}"
156
+ mapping "pmt_row_articlenr#{i}".to_sym, "pmt_row_articlenr#{i}"
157
+ mapping "pmt_row_unit#{i}".to_sym, "pmt_row_unit#{i}"
158
+ mapping "pmt_row_deliverydate#{i}".to_sym, "pmt_row_deliverydate#{i}"
159
+ mapping "pmt_row_price_gross#{i}".to_sym, "pmt_row_price_gross#{i}"
160
+ mapping "pmt_row_price_net#{i}".to_sym, "pmt_row_price_net#{i}"
161
+ mapping "pmt_row_vat#{i}".to_sym, "pmt_row_vat#{i}"
162
+ mapping "pmt_row_discountpercentage#{i}".to_sym, "pmt_row_discountpercentage#{i}"
163
+ mapping "pmt_row_type#{i}".to_sym, "pmt_row_type#{i}"
164
+ end
165
+
166
+ mapping :pmt_charset, "pmt_charset"
167
+ mapping :pmt_charsethttp, "pmt_charsethttp"
168
+ mapping :pmt_hashversion, "pmt_hashversion"
169
+ mapping :pmt_keygeneration, "pmt_keygeneration"
170
+ mapping :customer, :email => 'pmt_buyeremail',
171
+ :phone => 'pmt_buyerphone'
172
+
173
+ mapping :billing_address, :city => 'pmt_buyercity',
174
+ :address1 => "pmt_buyeraddress",
175
+ :address2 => '',
176
+ :state => '',
177
+ :zip => "pmt_buyerpostalcode",
178
+ :country => 'pmt_buyercountry'
179
+
180
+ mapping :notify_url, ''
181
+ mapping :return_url, 'pmt_okreturn'
182
+ mapping :pmt_errorreturn, 'pmt_errorreturn'
183
+ mapping :pmt_delayedpayreturn, 'pmt_delayedpayreturn'
184
+ mapping :cancel_return_url, 'pmt_cancelreturn'
185
+
186
+ mapping :description, ''
187
+ mapping :tax, ''
188
+ mapping :shipping, ''
189
+ end
190
+
191
+ class Notification < OffsitePayments::Notification
192
+ def complete?
193
+ true
194
+ end
195
+
196
+ def transaction_id
197
+ params["pmt_id"]
198
+ end
199
+
200
+ def security_key
201
+ params["pmt_hash"]
202
+ end
203
+
204
+ def gross
205
+ params["pmt_amount"]
206
+ end
207
+
208
+ def currency
209
+ params["pmt_currency"]
210
+ end
211
+
212
+ def status
213
+ "PAID"
214
+ end
215
+
216
+ def acknowledge(authcode = nil)
217
+ return_authcode = [params["pmt_action"], params["pmt_version"], params["pmt_id"], params["pmt_reference"], params["pmt_amount"], params["pmt_currency"], params["pmt_sellercosts"], params["pmt_paymentmethod"], params["pmt_escrow"], authcode].join("&")
218
+ (Digest::MD5.hexdigest(return_authcode + "&").upcase == params["pmt_hash"])
219
+ end
220
+
221
+ private
222
+
223
+ def parse(post)
224
+ post.each do |key, value|
225
+ params[key] = value
226
+ end
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,213 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ module MollieIdeal
4
+ class API
5
+ include ActiveMerchant::PostsData
6
+
7
+ attr_reader :token
8
+
9
+ def initialize(token)
10
+ @token = token
11
+ end
12
+
13
+ def get_request(resource, params = nil)
14
+ uri = URI.parse(MOLLIE_API_V1_URI + resource)
15
+ uri.query = params.map { |k,v| "#{CGI.escape(k)}=#{CGI.escape(v)}}"}.join('&') if params
16
+ headers = { "Authorization" => "Bearer #{token}", "Content-Type" => "application/json" }
17
+ JSON.parse(ssl_get(uri.to_s, headers))
18
+ end
19
+
20
+ def post_request(resource, params = nil)
21
+ uri = URI.parse(MOLLIE_API_V1_URI + resource)
22
+ headers = { "Authorization" => "Bearer #{token}", "Content-Type" => "application/json" }
23
+ data = params.nil? ? nil : JSON.dump(params)
24
+ JSON.parse(ssl_post(uri.to_s, data, headers))
25
+ end
26
+ end
27
+
28
+ RedirectError = Class.new(ActiveMerchant::ActiveMerchantError)
29
+
30
+ MOLLIE_API_V1_URI = 'https://api.mollie.nl/v1/'.freeze
31
+
32
+ mattr_accessor :live_issuers
33
+ self.live_issuers = [
34
+ ["ABN AMRO", "ideal_ABNANL2A"],
35
+ ["ASN Bank", "ideal_ASNBNL21"],
36
+ ["Friesland Bank", "ideal_FRBKNL2L"],
37
+ ["ING", "ideal_INGBNL2A"],
38
+ ["Knab", "ideal_KNABNL2H"],
39
+ ["Rabobank", "ideal_RABONL2U"],
40
+ ["RegioBank", "ideal_RBRBNL21"],
41
+ ["SNS Bank", "ideal_SNSBNL2A"],
42
+ ["Triodos Bank", "ideal_TRIONL2U"],
43
+ ["van Lanschot", "ideal_FVLBNL22"]
44
+ ]
45
+
46
+ mattr_accessor :test_issuers
47
+ self.test_issuers = [
48
+ ["TBM Bank", "ideal_TESTNL99"]
49
+ ]
50
+
51
+ def self.notification(post, options = {})
52
+ Notification.new(post, options)
53
+ end
54
+
55
+ def self.return(post, options = {})
56
+ Return.new(post, options)
57
+ end
58
+
59
+ def self.live?
60
+ OffsitePayments.mode == :production
61
+ end
62
+
63
+ def self.requires_redirect_param?
64
+ true
65
+ end
66
+
67
+ def self.redirect_param_label
68
+ "Select your bank"
69
+ end
70
+
71
+ def self.redirect_param_options(options = {})
72
+ return test_issuers if options[:credential1].blank?
73
+ options[:credential1].start_with?('live_') ? live_issuers : test_issuers
74
+ end
75
+
76
+ def self.retrieve_issuers(token)
77
+ response = API.new(token).get_request("issuers")
78
+ response['data']
79
+ .select { |issuer| issuer['method'] == 'ideal' }
80
+ .map { |issuer| [issuer['name'], issuer['id']] }
81
+ end
82
+
83
+ def self.create_payment(token, params)
84
+ API.new(token).post_request('payments', params)
85
+ end
86
+
87
+ def self.check_payment_status(token, payment_id)
88
+ API.new(token).get_request("payments/#{payment_id}")
89
+ end
90
+
91
+ class Helper < OffsitePayments::Helper
92
+ attr_reader :transaction_id, :redirect_paramaters, :token
93
+
94
+ def initialize(order, account, options = {})
95
+ @token = account
96
+ @redirect_paramaters = {
97
+ :amount => options[:amount],
98
+ :description => options[:description],
99
+ :issuer => options[:redirect_param],
100
+ :redirectUrl => options[:return_url],
101
+ :method => 'ideal',
102
+ :metadata => { :order => order }
103
+ }
104
+
105
+ @redirect_paramaters[:webhookUrl] = options[:notify_url] if options[:notify_url]
106
+
107
+ super
108
+
109
+ raise ArgumentError, "The redirect_param option needs to be set to the bank_id the customer selected." if options[:redirect_param].blank?
110
+ raise ArgumentError, "The return_url option needs to be set." if options[:return_url].blank?
111
+ raise ArgumentError, "The description option needs to be set." if options[:description].blank?
112
+ end
113
+
114
+ def credential_based_url
115
+ response = request_redirect
116
+ @transaction_id = response['id']
117
+
118
+ uri = URI.parse(response['links']['paymentUrl'])
119
+ set_form_fields_for_redirect(uri)
120
+ uri.query = ''
121
+ uri.to_s.sub(/\?\z/, '')
122
+ end
123
+
124
+ def form_method
125
+ "GET"
126
+ end
127
+
128
+ def set_form_fields_for_redirect(uri)
129
+ CGI.parse(uri.query).each do |key, value|
130
+ if value.is_a?(Array) && value.length == 1
131
+ add_field(key, value.first)
132
+ else
133
+ add_field(key, value)
134
+ end
135
+ end
136
+ end
137
+
138
+ def request_redirect
139
+ MollieIdeal.create_payment(token, redirect_paramaters)
140
+ rescue ActiveMerchant::ResponseError => e
141
+ if %w(401 403 422).include?(e.response.code)
142
+ error = JSON.parse(e.response.body)['error']['message']
143
+ raise ActionViewHelperError, error
144
+ else
145
+ raise
146
+ end
147
+ end
148
+ end
149
+
150
+ class Notification < OffsitePayments::Notification
151
+ def initialize(post_arguments, options = {})
152
+ super
153
+
154
+ raise ArgumentError, "The transaction_id needs to be included in the query string." if transaction_id.nil?
155
+ raise ArgumentError, "The credential1 option needs to be set to the Mollie API key." if api_key.blank?
156
+ end
157
+
158
+ def complete?
159
+ true
160
+ end
161
+
162
+ def item_id
163
+ params['metadata']['order']
164
+ end
165
+
166
+ def transaction_id
167
+ params['id']
168
+ end
169
+
170
+ def api_key
171
+ @options[:credential1]
172
+ end
173
+
174
+ def currency
175
+ "EUR"
176
+ end
177
+
178
+ # the money amount we received in X.2 decimal.
179
+ def gross
180
+ @params['amount']
181
+ end
182
+
183
+ def gross_cents
184
+ (BigDecimal.new(@params['amount'], 2) * 100).to_i
185
+ end
186
+
187
+ def status
188
+ case @params['status']
189
+ when 'open'; 'Pending'
190
+ when 'paidout', 'paid'; 'Completed'
191
+ else 'Failed'
192
+ end
193
+ end
194
+
195
+ def test?
196
+ @params['mode'] == 'test'
197
+ end
198
+
199
+ def acknowledge(authcode = nil)
200
+ @params = check_payment_status(transaction_id)
201
+ true
202
+ end
203
+
204
+ def check_payment_status(transaction_id)
205
+ MollieIdeal.check_payment_status(@options[:credential1], transaction_id)
206
+ end
207
+ end
208
+
209
+ class Return < OffsitePayments::Return
210
+ end
211
+ end
212
+ end
213
+ end