offsite_payments 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +70 -0
- data/lib/offsite_payments.rb +46 -0
- data/lib/offsite_payments/action_view_helper.rb +72 -0
- data/lib/offsite_payments/helper.rb +119 -0
- data/lib/offsite_payments/integrations.rb +14 -0
- data/lib/offsite_payments/integrations/a1agregator.rb +245 -0
- data/lib/offsite_payments/integrations/authorize_net_sim.rb +580 -0
- data/lib/offsite_payments/integrations/bit_pay.rb +150 -0
- data/lib/offsite_payments/integrations/bogus.rb +32 -0
- data/lib/offsite_payments/integrations/chronopay.rb +283 -0
- data/lib/offsite_payments/integrations/citrus.rb +227 -0
- data/lib/offsite_payments/integrations/direc_pay.rb +339 -0
- data/lib/offsite_payments/integrations/directebanking.rb +237 -0
- data/lib/offsite_payments/integrations/doku.rb +171 -0
- data/lib/offsite_payments/integrations/dotpay.rb +166 -0
- data/lib/offsite_payments/integrations/dwolla.rb +160 -0
- data/lib/offsite_payments/integrations/e_payment_plans.rb +146 -0
- data/lib/offsite_payments/integrations/easy_pay.rb +137 -0
- data/lib/offsite_payments/integrations/epay.rb +161 -0
- data/lib/offsite_payments/integrations/first_data.rb +133 -0
- data/lib/offsite_payments/integrations/gestpay.rb +201 -0
- data/lib/offsite_payments/integrations/hi_trust.rb +179 -0
- data/lib/offsite_payments/integrations/ipay88.rb +240 -0
- data/lib/offsite_payments/integrations/klarna.rb +291 -0
- data/lib/offsite_payments/integrations/liqpay.rb +216 -0
- data/lib/offsite_payments/integrations/maksuturva.rb +231 -0
- data/lib/offsite_payments/integrations/mollie_ideal.rb +213 -0
- data/lib/offsite_payments/integrations/moneybookers.rb +199 -0
- data/lib/offsite_payments/integrations/nochex.rb +228 -0
- data/lib/offsite_payments/integrations/pag_seguro.rb +255 -0
- data/lib/offsite_payments/integrations/paxum.rb +114 -0
- data/lib/offsite_payments/integrations/pay_fast.rb +269 -0
- data/lib/offsite_payments/integrations/paydollar.rb +142 -0
- data/lib/offsite_payments/integrations/payflow_link.rb +194 -0
- data/lib/offsite_payments/integrations/paypal.rb +362 -0
- data/lib/offsite_payments/integrations/paypal_payments_advanced.rb +23 -0
- data/lib/offsite_payments/integrations/paysbuy.rb +71 -0
- data/lib/offsite_payments/integrations/payu_in.rb +266 -0
- data/lib/offsite_payments/integrations/payu_in_paisa.rb +46 -0
- data/lib/offsite_payments/integrations/platron.rb +153 -0
- data/lib/offsite_payments/integrations/pxpay.rb +271 -0
- data/lib/offsite_payments/integrations/quickpay.rb +232 -0
- data/lib/offsite_payments/integrations/rbkmoney.rb +110 -0
- data/lib/offsite_payments/integrations/robokassa.rb +154 -0
- data/lib/offsite_payments/integrations/sage_pay_form.rb +425 -0
- data/lib/offsite_payments/integrations/two_checkout.rb +332 -0
- data/lib/offsite_payments/integrations/universal.rb +180 -0
- data/lib/offsite_payments/integrations/valitor.rb +200 -0
- data/lib/offsite_payments/integrations/verkkomaksut.rb +143 -0
- data/lib/offsite_payments/integrations/web_pay.rb +186 -0
- data/lib/offsite_payments/integrations/webmoney.rb +119 -0
- data/lib/offsite_payments/integrations/wirecard_checkout_page.rb +359 -0
- data/lib/offsite_payments/integrations/world_pay.rb +273 -0
- data/lib/offsite_payments/notification.rb +71 -0
- data/lib/offsite_payments/return.rb +37 -0
- data/lib/offsite_payments/version.rb +3 -0
- 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
|