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,114 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ # Documentation:
4
+ # https://www.paxum.com/payment_docs/page.php?name=apiIntroduction
5
+ module Paxum
6
+ mattr_accessor :test_url
7
+ self.test_url = 'https://paxum.com/payment/phrame.php?action=displayProcessPaymentLogin'
8
+
9
+ mattr_accessor :production_url
10
+ self.production_url = 'https://paxum.com/payment/phrame.php?action=displayProcessPaymentLogin'
11
+
12
+ mattr_accessor :signature_parameter_name
13
+ self.signature_parameter_name = 'key'
14
+
15
+ def self.service_url
16
+ mode = OffsitePayments.mode
17
+ case mode
18
+ when :production
19
+ self.production_url
20
+ when :test
21
+ self.test_url
22
+ else
23
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
24
+ end
25
+ end
26
+
27
+ def self.helper(order, account, options = {})
28
+ Helper.new(order, account, options)
29
+ end
30
+
31
+ def self.notification(query_string, options = {})
32
+ Notification.new(query_string, options)
33
+ end
34
+
35
+ module Common
36
+ def generate_signature_string
37
+ @raw_post.slice!(0) if @raw_post.starts_with?("&")
38
+ @raw_post = CGI.unescape(@raw_post)
39
+ @raw_post = "&#{@raw_post}" unless @raw_post.starts_with?("&")
40
+ arr = @raw_post.split('&')
41
+ arr.delete(arr.last)
42
+ data = arr.join('&')
43
+
44
+ (data + secret)
45
+ end
46
+
47
+ def generate_signature
48
+ Digest::MD5.hexdigest(generate_signature_string)
49
+ end
50
+ end
51
+
52
+ class Helper < OffsitePayments::Helper
53
+ include Common
54
+
55
+ def initialize(order, account, options = {})
56
+ @paxum_options = options.dup
57
+ options.delete(:description)
58
+ options.delete(:fail_url)
59
+ options.delete(:success_url)
60
+ options.delete(:result_url)
61
+ super
62
+ add_field "button_type_id", "1"
63
+ add_field "variables", "notify_url=#{@paxum_options[:result_url]}"
64
+ @paxum_options.each do |key, value|
65
+ add_field mappings[key], value
66
+ end
67
+ end
68
+
69
+ def form_fields
70
+ @fields
71
+ end
72
+
73
+ def params
74
+ @fields
75
+ end
76
+
77
+ mapping :account, 'business_email'
78
+ mapping :amount, 'amount'
79
+ mapping :currency, 'currency'
80
+ mapping :order, 'item_id'
81
+ mapping :description, 'item_name'
82
+ mapping :fail_url, 'cancel_url'
83
+ mapping :success_url, 'finish_url'
84
+ mapping :result_url, 'notify_url'
85
+ end
86
+
87
+ class Notification < OffsitePayments::Notification
88
+ include Common
89
+
90
+ def initialize(post, options = {})
91
+ @raw_post = post.dup
92
+ post.slice!(0)
93
+ super
94
+ end
95
+
96
+ def self.recognizes?(params)
97
+ (params.has_key?('transaction_item_id') && params.has_key?('transaction_amount'))
98
+ end
99
+
100
+ def security_key
101
+ params["key"]
102
+ end
103
+
104
+ def secret
105
+ @options[:secret]
106
+ end
107
+
108
+ def acknowledge(authcode = nil)
109
+ (security_key == generate_signature)
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,269 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ # Documentation:
4
+ # https://www.payfast.co.za/s/std/integration-guide
5
+ module PayFast
6
+ # Overwrite this if you want to change the PayFast sandbox url
7
+ mattr_accessor :process_test_url
8
+ self.process_test_url = 'https://sandbox.payfast.co.za/eng/process'
9
+
10
+ # Overwrite this if you want to change the PayFast production url
11
+ mattr_accessor :process_production_url
12
+ self.process_production_url = 'https://www.payfast.co.za/eng/process'
13
+
14
+ # Overwrite this if you want to change the PayFast sandbox url
15
+ mattr_accessor :validate_test_url
16
+ self.validate_test_url = 'https://sandbox.payfast.co.za/eng/query/validate'
17
+
18
+ # Overwrite this if you want to change the PayFast production url
19
+ mattr_accessor :validate_production_url
20
+ self.validate_production_url = 'https://www.payfast.co.za/eng/query/validate'
21
+
22
+ mattr_accessor :signature_parameter_name
23
+ self.signature_parameter_name = 'signature'
24
+
25
+ def self.service_url
26
+ mode = OffsitePayments.mode
27
+ case mode
28
+ when :production
29
+ self.process_production_url
30
+ when :test
31
+ self.process_test_url
32
+ else
33
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
34
+ end
35
+ end
36
+
37
+ def self.validate_service_url
38
+ mode = OffsitePayments.mode
39
+ case mode
40
+ when :production
41
+ self.validate_production_url
42
+ when :test
43
+ self.validate_test_url
44
+ else
45
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
46
+ end
47
+ end
48
+
49
+ def self.helper(order, account, options = {})
50
+ Helper.new(order, account, options)
51
+ end
52
+
53
+ def self.notification(query_string, options = {})
54
+ Notification.new(query_string, options)
55
+ end
56
+
57
+ def self.return(post, options = {})
58
+ Return.new(post, options)
59
+ end
60
+
61
+ module Common
62
+ def generate_signature(type)
63
+ string = case type
64
+ when :request
65
+ request_signature_string
66
+ when :notify
67
+ notify_signature_string
68
+ end
69
+
70
+ Digest::MD5.hexdigest(string)
71
+ end
72
+
73
+ def request_attributes
74
+ [:merchant_id, :merchant_key, :return_url, :cancel_url,
75
+ :notify_url, :name_first, :name_last, :email_address,
76
+ :payment_id, :amount, :item_name, :item_description,
77
+ :custom_str1, :custom_str2, :custom_str3, :custom_str4,
78
+ :custom_str5, :custom_int1, :custom_int2, :custom_int3,
79
+ :custom_int4, :custom_int5, :email_confirmation,
80
+ :confirmation_address]
81
+ end
82
+
83
+ def request_signature_string
84
+ request_attributes.map do |attr|
85
+ "#{mappings[attr]}=#{CGI.escape(@fields[mappings[attr]])}" if @fields[mappings[attr]].present?
86
+ end.compact.join('&')
87
+ end
88
+
89
+ def notify_signature_string
90
+ params.map do |key, value|
91
+ "#{key}=#{CGI.escape(value)}" unless key == PayFast.signature_parameter_name
92
+ end.compact.join('&')
93
+ end
94
+ end
95
+
96
+ class Helper < OffsitePayments::Helper
97
+ include Common
98
+
99
+ def initialize(order, account, options = {})
100
+ super
101
+ add_field('merchant_id', account)
102
+ add_field('merchant_key', options.delete(:credential2))
103
+ add_field('m_payment_id', order)
104
+ end
105
+
106
+ def form_fields
107
+ @fields
108
+ end
109
+
110
+ def params
111
+ @fields
112
+ end
113
+
114
+ mapping :merchant_id, 'merchant_id'
115
+ mapping :merchant_key, 'merchant_key'
116
+ mapping :return_url, 'return_url'
117
+ mapping :cancel_return_url, 'cancel_url'
118
+ mapping :notify_url, 'notify_url'
119
+ mapping :name_first, 'name_first'
120
+ mapping :name_last, 'name_last'
121
+ mapping :email_address, 'email_address'
122
+ mapping :payment_id, 'm_payment_id'
123
+ mapping :amount, 'amount'
124
+ mapping :item_name, 'item_name'
125
+ mapping :description, 'item_name'
126
+
127
+ mapping :customer, :first_name => 'name_first',
128
+ :last_name => 'name_last',
129
+ :email => 'email_address',
130
+ :phone => 'phone'
131
+
132
+ 5.times { |i| mapping :"custom_str#{i}", "custom_str#{i}" }
133
+ 5.times { |i| mapping :"custom_int#{i}", "custom_int#{i}" }
134
+
135
+ mapping :email_confirmation, 'email_confirmation'
136
+ mapping :confirmation_address, 'confirmation_address'
137
+ end
138
+
139
+ # Parser and handler for incoming ITN from PayFast.
140
+ # The Example shows a typical handler in a rails application.
141
+ #
142
+ # Example
143
+ #
144
+ # class BackendController < ApplicationController
145
+ # include OffsitePayments::Integrations
146
+ #
147
+ # def pay_fast_itn
148
+ # notify = PayFast::Notification.new(request.raw_post)
149
+ #
150
+ # order = Order.find(notify.item_id)
151
+ #
152
+ # if notify.acknowledge
153
+ # begin
154
+ #
155
+ # if notify.complete? and order.total == notify.amount
156
+ # order.status = 'success'
157
+ #
158
+ # shop.ship(order)
159
+ # else
160
+ # logger.error("Failed to verify Paypal's notification, please investigate")
161
+ # end
162
+ #
163
+ # rescue => e
164
+ # order.status = 'failed'
165
+ # raise
166
+ # ensure
167
+ # order.save
168
+ # end
169
+ # end
170
+ #
171
+ # render :nothing
172
+ # end
173
+ # end
174
+ class Notification < OffsitePayments::Notification
175
+ include ActiveMerchant::PostsData
176
+ include Common
177
+
178
+ # Was the transaction complete?
179
+ def complete?
180
+ status == "Completed"
181
+ end
182
+
183
+ # Status of transaction. List of possible values:
184
+ # <tt>COMPLETE</tt>::
185
+ def status
186
+ if params['payment_status'] == "COMPLETE"
187
+ "Completed"
188
+ else
189
+ "Failed"
190
+ end
191
+ end
192
+
193
+ # Id of this transaction (uniq PayFast transaction id)
194
+ def transaction_id
195
+ params['pf_payment_id']
196
+ end
197
+
198
+ # Id of this transaction (uniq Shopify transaction id)
199
+ def item_id
200
+ params['m_payment_id']
201
+ end
202
+
203
+ # The total amount which the payer paid.
204
+ def gross
205
+ params['amount_gross']
206
+ end
207
+
208
+ # The total in fees which was deducted from the amount.
209
+ def fee
210
+ params['amount_fee']
211
+ end
212
+
213
+ # The net amount credited to the receiver's account.
214
+ def amount
215
+ params['amount_net']
216
+ end
217
+
218
+ # The name of the item being charged for.
219
+ def item_name
220
+ params['item_name']
221
+ end
222
+
223
+ # The Merchant ID as given by the PayFast system. Used to uniquely identify the receiver's account.
224
+ def merchant_id
225
+ params['merchant_id']
226
+ end
227
+
228
+ def currency
229
+ nil
230
+ end
231
+
232
+ # Generated hash depends on params order so use OrderedHash instead of Hash
233
+ def empty!
234
+ super
235
+ @params = ActiveSupport::OrderedHash.new
236
+ end
237
+
238
+ # Acknowledge the transaction to PayFast. This method has to be called after a new
239
+ # ITN arrives. PayFast will verify that all the information we received are correct and will return a
240
+ # VERIFIED or INVALID status.
241
+ #
242
+ # Example:
243
+ #
244
+ # def pay_fast_itn
245
+ # notify = PayFastNotification.new(request.raw_post)
246
+ #
247
+ # if notify.acknowledge
248
+ # ... process order ... if notify.complete?
249
+ # else
250
+ # ... log possible hacking attempt ...
251
+ # end
252
+ def acknowledge(authcode = nil)
253
+ if params[PayFast.signature_parameter_name] == generate_signature(:notify)
254
+ response = ssl_post(PayFast.validate_service_url, notify_signature_string,
255
+ 'Content-Type' => "application/x-www-form-urlencoded",
256
+ 'Content-Length' => "#{notify_signature_string.size}"
257
+ )
258
+ raise StandardError.new("Faulty PayFast result: #{response}") unless ['VALID', 'INVALID'].include?(response)
259
+
260
+ response == "VALID"
261
+ end
262
+ end
263
+ end
264
+
265
+ class Return < OffsitePayments::Return
266
+ end
267
+ end
268
+ end
269
+ end
@@ -0,0 +1,142 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ module Paydollar
4
+ CURRENCY_MAP = {
5
+ 'AED' => '784',
6
+ 'AUD' => '036',
7
+ 'BND' => '096',
8
+ 'CAD' => '124',
9
+ 'CNY' => '156',
10
+ 'EUR' => '978',
11
+ 'GBP' => '826',
12
+ 'HKD' => '344',
13
+ 'IDR' => '360',
14
+ 'JPY' => '392',
15
+ 'KRW' => '410',
16
+ 'MOP' => '446',
17
+ 'MYR' => '458',
18
+ 'NZD' => '554',
19
+ 'PHP' => '608',
20
+ 'SAR' => '682',
21
+ 'SGD' => '702',
22
+ 'THB' => '764',
23
+ 'TWD' => '901',
24
+ 'USD' => '840',
25
+ }
26
+
27
+ def self.service_url
28
+ case OffsitePayments.mode
29
+ when :production
30
+ 'https://www.paydollar.com/b2c2/eng/payment/payForm.jsp'
31
+ when :test
32
+ 'https://test.paydollar.com/b2cDemo/eng/payment/payForm.jsp'
33
+ else
34
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
35
+ end
36
+ end
37
+
38
+ def self.notification(post, options = {})
39
+ Notification.new(post, options)
40
+ end
41
+
42
+ def self.return(query_string, options = {})
43
+ Return.new(query_string, options)
44
+ end
45
+
46
+ def self.sign(fields, secret)
47
+ Digest::SHA1.hexdigest(fields.push(secret).join('|'))
48
+ end
49
+
50
+ class Helper < OffsitePayments::Helper
51
+ def initialize(order, account, options = {})
52
+ super
53
+ add_field('payType', 'N') # normal sale and not just auth
54
+ @secret = options[:credential2]
55
+ end
56
+
57
+ def form_fields
58
+ @fields.merge('secureHash' => generate_secure_hash)
59
+ end
60
+
61
+ def generate_secure_hash
62
+ fields = [@fields[mappings[:account]],
63
+ @fields[mappings[:order]],
64
+ @fields[mappings[:currency]],
65
+ @fields[mappings[:amount]],
66
+ @fields['payType']]
67
+ Paydollar.sign(fields, @secret)
68
+ end
69
+
70
+ def currency=(currency_code)
71
+ add_field(mappings[:currency], CURRENCY_MAP[currency_code])
72
+ end
73
+
74
+ mapping :account, 'merchantId'
75
+ mapping :amount, 'amount'
76
+ mapping :order, 'orderRef'
77
+ mapping :currency, 'currCode'
78
+ mapping :return_url, 'successUrl'
79
+ mapping :cancel_return_url, ['cancelUrl','failUrl']
80
+ end
81
+
82
+ class Notification < OffsitePayments::Notification
83
+ def complete?
84
+ status == 'Completed'
85
+ end
86
+
87
+ def item_id
88
+ @params['Ref']
89
+ end
90
+
91
+ def currency
92
+ CURRENCY_MAP.key(@params['Cur'])
93
+ end
94
+
95
+ def gross
96
+ @params['Amt']
97
+ end
98
+
99
+ def transaction_id
100
+ @params['PayRef']
101
+ end
102
+
103
+ def status
104
+ case @params['successcode']
105
+ when '0' then 'Completed'
106
+ else 'Failed'
107
+ end
108
+ end
109
+
110
+ def acknowledge(authcode = nil)
111
+ # paydollar supports multiple signature keys, therefore we need to check if any
112
+ # of their signatures match ours
113
+ hash = @params['secureHash']
114
+ if !hash
115
+ return false
116
+ end
117
+ hash.split(',').include? generate_secure_hash
118
+ end
119
+
120
+ private
121
+
122
+ def generate_secure_hash
123
+ fields = [@params['src'],
124
+ @params['prc'],
125
+ @params['successcode'],
126
+ @params['Ref'],
127
+ @params['PayRef'],
128
+ @params['Cur'],
129
+ @params['Amt'],
130
+ @params['payerAuth']]
131
+ Paydollar.sign(fields, @options[:credential2])
132
+ end
133
+ end
134
+
135
+ class Return < OffsitePayments::Return
136
+ def success?
137
+ @params.has_key?('Ref')
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end