offsite_payments 2.0.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.
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,200 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ module Valitor
4
+ mattr_accessor :test_url
5
+ self.test_url = 'https://testvefverslun.valitor.is/1_1/'
6
+
7
+ mattr_accessor :production_url
8
+ self.production_url = 'https://vefverslun.valitor.is/1_1/'
9
+
10
+ def self.test?
11
+ (OffsitePayments.mode == :test)
12
+ end
13
+
14
+ def self.service_url
15
+ (test? ? test_url : production_url)
16
+ end
17
+
18
+ def self.notification(params, options={})
19
+ Notification.new(params, options.merge(:test => test?))
20
+ end
21
+
22
+ def self.return(query_string, options={})
23
+ Return.new(query_string, options.merge(:test => test?))
24
+ end
25
+
26
+ class Helper < OffsitePayments::Helper
27
+ include ActiveMerchant::RequiresParameters
28
+
29
+ DEFAULT_SUCCESS_TEXT = "The transaction has been completed."
30
+
31
+ def initialize(order, account, options={})
32
+ options[:currency] ||= 'ISK'
33
+ super
34
+ add_field 'Adeinsheimild', '0'
35
+ add_field 'KaupandaUpplysingar', '0'
36
+ add_field 'SlokkvaHaus', '0'
37
+ @security_number = options[:credential2]
38
+ @amount = options[:amount]
39
+ @order = order
40
+ end
41
+
42
+ mapping :account, 'VefverslunID'
43
+ mapping :currency, 'Gjaldmidill'
44
+
45
+ mapping :order, 'Tilvisunarnumer'
46
+
47
+ mapping :notify_url, 'SlodTokstAdGjaldfaeraServerSide'
48
+ mapping :return_url, 'SlodTokstAdGjaldfaera'
49
+ mapping :cancel_return_url, 'SlodNotandiHaettirVid'
50
+
51
+ mapping :success_text, 'SlodTokstAdGjaldfaeraTexti'
52
+
53
+ mapping :language, 'Lang'
54
+
55
+ def authorize_only
56
+ add_field 'Adeinsheimild', '1'
57
+ end
58
+
59
+ def collect_customer_info
60
+ add_field 'KaupandaUpplysingar', '1'
61
+ end
62
+
63
+ def hide_header
64
+ add_field 'SlokkvaHaus', '1'
65
+ end
66
+
67
+ def product(id, options={})
68
+ raise ArgumentError, "Product id #{id} is not an integer between 1 and 500" unless id.to_i > 0 && id.to_i <= 500
69
+ requires!(options, :amount, :description)
70
+ options.assert_valid_keys([:description, :quantity, :amount, :discount])
71
+
72
+ add_field("Vara_#{id}_Verd", format_amount(options[:amount], @fields[mappings[:currency]]))
73
+ add_field("Vara_#{id}_Fjoldi", options[:quantity] || "1")
74
+
75
+ add_field("Vara_#{id}_Lysing", options[:description]) if options[:description]
76
+ add_field("Vara_#{id}_Afslattur", options[:discount] || '0')
77
+
78
+ @products ||= []
79
+ @products << id.to_i
80
+ end
81
+
82
+ def signature
83
+ raise ArgumentError, "Security number not set" unless @security_number
84
+ parts = [@security_number, @fields['Adeinsheimild']]
85
+ @products.sort.uniq.each do |id|
86
+ parts.concat(["Vara_#{id}_Fjoldi", "Vara_#{id}_Verd", "Vara_#{id}_Afslattur"].collect{|e| @fields[e]})
87
+ end if @products
88
+ parts.concat(%w(VefverslunID Tilvisunarnumer SlodTokstAdGjaldfaera SlodTokstAdGjaldfaeraServerSide Gjaldmidill).collect{|e| @fields[e]})
89
+ Digest::MD5.hexdigest(parts.compact.join(''))
90
+ end
91
+
92
+ def form_fields
93
+ product(1, :amount => @amount, :description => @order) if Array(@products).empty?
94
+ @fields[mappings[:success_text]] ||= DEFAULT_SUCCESS_TEXT
95
+ @fields.merge('RafraenUndirskrift' => signature)
96
+ end
97
+
98
+ def format_amount(amount, currency)
99
+ OffsitePayments::CURRENCIES_WITHOUT_FRACTIONS.include?(currency) ? amount.to_f.round : sprintf("%.2f", amount)
100
+ end
101
+ end
102
+
103
+ module ResponseFields
104
+ def success?
105
+ status == 'Completed'
106
+ end
107
+ alias :complete? :success?
108
+
109
+ def test?
110
+ @options[:test]
111
+ end
112
+
113
+ def item_id
114
+ params['Tilvisunarnumer']
115
+ end
116
+ alias :order :item_id
117
+
118
+ def transaction_id
119
+ params['VefverslunSalaID']
120
+ end
121
+
122
+ def currency
123
+ nil
124
+ end
125
+
126
+ def status
127
+ "Completed" if acknowledge
128
+ end
129
+
130
+ def received_at
131
+ Time.parse(params['Dagsetning'].to_s)
132
+ end
133
+
134
+ def gross
135
+ "%0.2f" % params['Upphaed'].to_s.sub(',', '.')
136
+ end
137
+
138
+ def card_type
139
+ params['Kortategund']
140
+ end
141
+
142
+ def card_last_four
143
+ params['KortnumerSidustu']
144
+ end
145
+
146
+ def authorization_number
147
+ params['Heimildarnumer']
148
+ end
149
+
150
+ def transaction_number
151
+ params['Faerslunumer']
152
+ end
153
+
154
+ def customer_name
155
+ params['Nafn']
156
+ end
157
+
158
+ def customer_address
159
+ params['Heimilisfang']
160
+ end
161
+
162
+ def customer_zip
163
+ params['Postnumer']
164
+ end
165
+
166
+ def customer_city
167
+ params['Stadur']
168
+ end
169
+
170
+ def customer_country
171
+ params['Land']
172
+ end
173
+
174
+ def customer_email
175
+ params['Tolvupostfang']
176
+ end
177
+
178
+ def customer_comment
179
+ params['Athugasemdir']
180
+ end
181
+
182
+ def password
183
+ @options[:credential2]
184
+ end
185
+
186
+ def acknowledge(authcode = nil)
187
+ password ? Digest::MD5.hexdigest("#{password}#{order}") == params['RafraenUndirskriftSvar'] : true
188
+ end
189
+ end
190
+
191
+ class Notification < OffsitePayments::Notification
192
+ include ResponseFields
193
+ end
194
+
195
+ class Return < OffsitePayments::Return
196
+ include ResponseFields
197
+ end
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,143 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ # Usage, see the blog post here: http://blog.kiskolabs.com/post/22374612968/understanding-active-merchant-integrations and E1 API documentation here: http://docs.verkkomaksut.fi/
4
+ module Verkkomaksut
5
+ mattr_accessor :service_url
6
+ self.service_url = 'https://payment.verkkomaksut.fi/'
7
+
8
+ def self.notification(post)
9
+ Notification.new(post)
10
+ end
11
+
12
+ class Helper < OffsitePayments::Helper
13
+ # Fetches the md5secret and adds MERCHANT_ID and API TYPE to the form
14
+ def initialize(order, account, options = {})
15
+ md5secret options.delete(:credential2)
16
+ super
17
+ add_field("MERCHANT_ID", account)
18
+ add_field("TYPE", "E1")
19
+ end
20
+
21
+ def md5secret(value)
22
+ @md5secret = value
23
+ end
24
+
25
+ # Adds the AUTHCODE to the form
26
+ def form_fields
27
+ @fields.merge("AUTHCODE" => generate_md5string)
28
+ end
29
+
30
+ # Calculates the AUTHCODE
31
+ def generate_md5string
32
+ fields = [@md5secret, @fields["MERCHANT_ID"], @fields["ORDER_NUMBER"], @fields["REFERENCE_NUMBER"], @fields["ORDER_DESCRIPTION"], @fields["CURRENCY"], @fields["RETURN_ADDRESS"], @fields["CANCEL_ADDRESS"], @fields["PENDING_ADDRESS"],
33
+ @fields["NOTIFY_ADDRESS"], @fields["TYPE"], @fields["CULTURE"], @fields["PRESELECTED_METHOD"], @fields["MODE"], @fields["VISIBLE_METHODS"], @fields["GROUP"], @fields["CONTACT_TELNO"], @fields["CONTACT_CELLNO"],
34
+ @fields["CONTACT_EMAIL"], @fields["CONTACT_FIRSTNAME"], @fields["CONTACT_LASTNAME"], @fields["CONTACT_COMPANY"], @fields["CONTACT_ADDR_STREET"], @fields["CONTACT_ADDR_ZIP"], @fields["CONTACT_ADDR_CITY"], @fields["CONTACT_ADDR_COUNTRY"], @fields["INCLUDE_VAT"],
35
+ @fields["ITEMS"]]
36
+
37
+ (0..@fields["ITEMS"].to_i-1).each do |i|
38
+ fields += [@fields["ITEM_TITLE[#{i}]"], @fields["ITEM_NO[#{i}]"], @fields["ITEM_AMOUNT[#{i}]"], @fields["ITEM_PRICE[#{i}]"], @fields["ITEM_TAX[#{i}]"], @fields["ITEM_DISCOUNT[#{i}]"], @fields["ITEM_TYPE[#{i}]"]]
39
+ end
40
+
41
+ fields = fields.join("|")
42
+
43
+ return Digest::MD5.hexdigest(fields).upcase
44
+ end
45
+
46
+ # Mappings
47
+ mapping :merchant_id, "MERCHANT_ID"
48
+ mapping :order, "ORDER_NUMBER"
49
+ mapping :reference_number, "REFERENCE_NUMBER"
50
+ mapping :customer, :first_name => "CONTACT_FIRSTNAME",
51
+ :last_name => "CONTACT_LASTNAME",
52
+ :email => "CONTACT_EMAIL",
53
+ :phone => "CONTACT_CELLNO",
54
+ :tellno => "CONTACT_TELLNO",
55
+ :company => "CONTACT_COMPANY"
56
+
57
+
58
+ mapping :billing_address, :city => "CONTACT_ADDR_CITY",
59
+ :address1 => "CONTACT_ADDR_STREET",
60
+ :address2 => "",
61
+ :state => "",
62
+ :zip => "CONTACT_ADDR_ZIP",
63
+ :country => "CONTACT_ADDR_COUNTRY"
64
+
65
+ mapping :notify_url, "NOTIFY_ADDRESS"
66
+ mapping :currency, "CURRENCY"
67
+ mapping :return_url, "RETURN_ADDRESS"
68
+ mapping :cancel_return_url, "CANCEL_ADDRESS"
69
+ mapping :description, "ORDER_DESCRIPTION"
70
+ mapping :tax, ""
71
+ mapping :shipping, ""
72
+ mapping :include_vat, "INCLUDE_VAT"
73
+ mapping :pending_address, "PENDING_ADDRESS"
74
+ mapping :culture, "CULTURE"
75
+ mapping :items, "ITEMS"
76
+ mapping :preselected_method, "PRESELECTED_METHOD"
77
+ mapping :mode, "MODE"
78
+ mapping :visible_methods, "VISIBLE_METHODS"
79
+ mapping :group, "GROUP"
80
+
81
+ (0..499.to_i).each do |i|
82
+ mapping "item_title_#{i}".to_sym, "ITEM_TITLE[#{i}]"
83
+ mapping "item_no_#{i}".to_sym, "ITEM_NO[#{i}]"
84
+ mapping "item_amount_#{i}".to_sym, "ITEM_AMOUNT[#{i}]"
85
+ mapping "item_price_#{i}".to_sym, "ITEM_PRICE[#{i}]"
86
+ mapping "item_tax_#{i}".to_sym, "ITEM_TAX[#{i}]"
87
+ mapping "item_discount_#{i}".to_sym, "ITEM_DISCOUNT[#{i}]"
88
+ mapping "item_type_#{i}".to_sym, "ITEM_TYPE[#{i}]"
89
+ end
90
+ end
91
+
92
+ class Notification < OffsitePayments::Notification
93
+ # Is the payment complete or not. Verkkomaksut only has two statuses: random string or 0000000000 which means pending
94
+ def complete?
95
+ params['PAID'] != "0000000000"
96
+ end
97
+
98
+ # Order id
99
+ def order_id
100
+ params['ORDER_NUMBER']
101
+ end
102
+
103
+ # Payment method used
104
+ def method
105
+ params['METHOD']
106
+ end
107
+
108
+ # When was this payment received by the client.
109
+ def received_at
110
+ params['TIMESTAMP']
111
+ end
112
+
113
+ # Security key got from Verkkomaksut
114
+ def security_key
115
+ params['RETURN_AUTHCODE']
116
+ end
117
+
118
+ # Another way of asking the payment status
119
+ def status
120
+ if complete?
121
+ "PAID"
122
+ else
123
+ "PENDING"
124
+ end
125
+ end
126
+
127
+ # Acknowledges the payment. If the authcodes match, returns true.
128
+ def acknowledge(authcode = nil)
129
+ return_authcode = [params["ORDER_NUMBER"], params["TIMESTAMP"], params["PAID"], params["METHOD"], authcode].join("|")
130
+ Digest::MD5.hexdigest(return_authcode).upcase == params["RETURN_AUTHCODE"]
131
+ end
132
+
133
+ private
134
+
135
+ def parse(post)
136
+ post.each do |key, value|
137
+ params[key] = value
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,186 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ # Documentation: You will get it after registration steps here:
4
+ # http://reg.webpay.by/registration-form.php
5
+ module WebPay
6
+ # Overwrite this if you want to change the WebPay sandbox url
7
+ mattr_accessor :test_url
8
+ self.test_url = 'https://secure.sandbox.webpay.by:8843'
9
+
10
+ # Overwrite this if you want to change the WebPay production url
11
+ mattr_accessor :production_url
12
+ self.production_url = 'https://secure.webpay.by'
13
+
14
+ mattr_accessor :signature_parameter_name
15
+ self.signature_parameter_name = 'wsb_signature'
16
+
17
+ def self.service_url
18
+ mode = OffsitePayments.mode
19
+ case mode
20
+ when :production
21
+ self.production_url
22
+ when :test
23
+ self.test_url
24
+ else
25
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
26
+ end
27
+ end
28
+
29
+ def self.helper(order, account, options = {})
30
+ Helper.new(order, account, options)
31
+ end
32
+
33
+ def self.notification(query_string, options = {})
34
+ Notification.new(query_string, options)
35
+ end
36
+
37
+ module Common
38
+ def generate_signature(type)
39
+ string = case type
40
+ when :request
41
+ request_signature_string
42
+ when :notify
43
+ notify_signature_string
44
+ end
45
+ if type != :notify && @fields[mappings[:version]] == '2'
46
+ Digest::SHA1.hexdigest(string)
47
+ else
48
+ Digest::MD5.hexdigest(string)
49
+ end
50
+ end
51
+
52
+ def request_signature_string
53
+ [
54
+ @fields[mappings[:seed]],
55
+ @fields[mappings[:account]],
56
+ @fields[mappings[:order]],
57
+ @fields[mappings[:test]],
58
+ @fields[mappings[:currency]],
59
+ @fields[mappings[:amount]],
60
+ secret
61
+ ].join
62
+ end
63
+
64
+ def notify_signature_string
65
+ [
66
+ params['batch_timestamp'],
67
+ params['currency_id'],
68
+ params['amount'],
69
+ params['payment_method'],
70
+ params['order_id'],
71
+ params['site_order_id'],
72
+ params['transaction_id'],
73
+ params['payment_type'],
74
+ params['rrn'],
75
+ secret
76
+ ].join
77
+ end
78
+ end
79
+
80
+ class Helper < OffsitePayments::Helper
81
+ include Common
82
+
83
+ def initialize(order, account, options = {})
84
+ @md5secret = options.delete(:secret)
85
+ @line_item_count = 0
86
+ super
87
+ end
88
+
89
+ def form_fields
90
+ @fields.merge(OffsitePayments::Integrations::WebPay.signature_parameter_name => generate_signature(:request))
91
+ end
92
+
93
+ def params
94
+ @fields
95
+ end
96
+
97
+ def secret
98
+ @md5secret
99
+ end
100
+
101
+ def add_line_item(options)
102
+ options.each do |key, value|
103
+ add_field("wsb_invoice_item_#{key}[#{@line_item_count}]", value)
104
+ end
105
+
106
+ @line_item_count += 1
107
+ end
108
+
109
+ def calculate_total
110
+ sum = 0
111
+
112
+ @line_item_count.times do |i|
113
+ sum += @fields["wsb_invoice_item_quantity[#{i}]"].to_i * @fields["wsb_invoice_item_price[#{i}]"].to_i
114
+ end
115
+
116
+ sum + @fields[mappings[:tax]].to_i + @fields[mappings[:shipping_price]].to_i - @fields[mappings[:discount_price]].to_i
117
+ end
118
+
119
+ mapping :scart, '*scart'
120
+ mapping :account, 'wsb_storeid'
121
+ mapping :store, 'wsb_store'
122
+ mapping :order, 'wsb_order_num'
123
+ mapping :currency, 'wsb_currency_id'
124
+ mapping :version, 'wsb_version'
125
+ mapping :language, 'wsb_language_id'
126
+ mapping :seed, 'wsb_seed'
127
+ mapping :success_url, 'wsb_return_url'
128
+ mapping :cancel_url, 'wsb_cancel_return_url'
129
+ mapping :notify_url, 'wsb_notify_url'
130
+ mapping :test, 'wsb_test'
131
+ mapping :tax, 'wsb_tax'
132
+ mapping :shipping_name, 'wsb_shipping_name'
133
+ mapping :shipping_price, 'wsb_shipping_price'
134
+ mapping :discount_name, 'wsb_discount_name'
135
+ mapping :discount_price, 'wsb_discount_price'
136
+ mapping :amount, 'wsb_total'
137
+ mapping :email, 'wsb_email'
138
+ mapping :phone, 'wsb_phone'
139
+ end
140
+
141
+ class Notification < OffsitePayments::Notification
142
+ include Common
143
+
144
+ def self.recognizes?(params)
145
+ params.has_key?('site_order_id') && params.has_key?('amount')
146
+ end
147
+
148
+ def complete?
149
+ true
150
+ end
151
+
152
+ def amount
153
+ BigDecimal.new(gross)
154
+ end
155
+
156
+ def item_id
157
+ params['site_order_id']
158
+ end
159
+
160
+ def security_key
161
+ params[OffsitePayments::Integrations::WebPay.signature_parameter_name]
162
+ end
163
+
164
+ def gross
165
+ params['amount']
166
+ end
167
+
168
+ def status
169
+ 'success'
170
+ end
171
+
172
+ def secret
173
+ @options[:secret]
174
+ end
175
+
176
+ def acknowledge(authcode = nil)
177
+ (security_key == generate_signature(:notify))
178
+ end
179
+
180
+ def success_response(*args)
181
+ {:nothing => true}
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end