better_offsite_payments 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +76 -0
  4. data/lib/offsite_payments.rb +39 -0
  5. data/lib/offsite_payments/action_view_helper.rb +72 -0
  6. data/lib/offsite_payments/helper.rb +120 -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/coinbase.rb +172 -0
  15. data/lib/offsite_payments/integrations/direc_pay.rb +332 -0
  16. data/lib/offsite_payments/integrations/directebanking.rb +237 -0
  17. data/lib/offsite_payments/integrations/doku.rb +171 -0
  18. data/lib/offsite_payments/integrations/dotpay.rb +166 -0
  19. data/lib/offsite_payments/integrations/dwolla.rb +160 -0
  20. data/lib/offsite_payments/integrations/e_payment_plans.rb +146 -0
  21. data/lib/offsite_payments/integrations/easy_pay.rb +137 -0
  22. data/lib/offsite_payments/integrations/epay.rb +161 -0
  23. data/lib/offsite_payments/integrations/first_data.rb +133 -0
  24. data/lib/offsite_payments/integrations/gestpay.rb +205 -0
  25. data/lib/offsite_payments/integrations/hi_trust.rb +179 -0
  26. data/lib/offsite_payments/integrations/ipay88.rb +251 -0
  27. data/lib/offsite_payments/integrations/klarna.rb +275 -0
  28. data/lib/offsite_payments/integrations/liqpay.rb +216 -0
  29. data/lib/offsite_payments/integrations/maksuturva.rb +231 -0
  30. data/lib/offsite_payments/integrations/megakassa.rb +184 -0
  31. data/lib/offsite_payments/integrations/mollie.rb +32 -0
  32. data/lib/offsite_payments/integrations/mollie_ideal.rb +194 -0
  33. data/lib/offsite_payments/integrations/mollie_mistercash.rb +143 -0
  34. data/lib/offsite_payments/integrations/molpay.rb +193 -0
  35. data/lib/offsite_payments/integrations/moneybookers.rb +199 -0
  36. data/lib/offsite_payments/integrations/nochex.rb +228 -0
  37. data/lib/offsite_payments/integrations/pag_seguro.rb +268 -0
  38. data/lib/offsite_payments/integrations/paxum.rb +114 -0
  39. data/lib/offsite_payments/integrations/pay_fast.rb +269 -0
  40. data/lib/offsite_payments/integrations/paydollar.rb +142 -0
  41. data/lib/offsite_payments/integrations/payflow_link.rb +194 -0
  42. data/lib/offsite_payments/integrations/paypal.rb +362 -0
  43. data/lib/offsite_payments/integrations/paypal_payments_advanced.rb +23 -0
  44. data/lib/offsite_payments/integrations/paysbuy.rb +71 -0
  45. data/lib/offsite_payments/integrations/payu_in.rb +276 -0
  46. data/lib/offsite_payments/integrations/payu_in_paisa.rb +46 -0
  47. data/lib/offsite_payments/integrations/platron.rb +153 -0
  48. data/lib/offsite_payments/integrations/pxpay.rb +273 -0
  49. data/lib/offsite_payments/integrations/quickpay.rb +232 -0
  50. data/lib/offsite_payments/integrations/rbkmoney.rb +110 -0
  51. data/lib/offsite_payments/integrations/realex_offsite.rb +317 -0
  52. data/lib/offsite_payments/integrations/robokassa.rb +154 -0
  53. data/lib/offsite_payments/integrations/sage_pay_form.rb +431 -0
  54. data/lib/offsite_payments/integrations/two_checkout.rb +329 -0
  55. data/lib/offsite_payments/integrations/universal.rb +190 -0
  56. data/lib/offsite_payments/integrations/valitor.rb +200 -0
  57. data/lib/offsite_payments/integrations/verkkomaksut.rb +143 -0
  58. data/lib/offsite_payments/integrations/web_pay.rb +186 -0
  59. data/lib/offsite_payments/integrations/webmoney.rb +119 -0
  60. data/lib/offsite_payments/integrations/wirecard_checkout_page.rb +359 -0
  61. data/lib/offsite_payments/integrations/world_pay.rb +280 -0
  62. data/lib/offsite_payments/integrations/yandex_money.rb +175 -0
  63. data/lib/offsite_payments/notification.rb +71 -0
  64. data/lib/offsite_payments/return.rb +37 -0
  65. data/lib/offsite_payments/version.rb +3 -0
  66. metadata +297 -0
@@ -0,0 +1,280 @@
1
+ require 'ipaddr'
2
+ module OffsitePayments #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module WorldPay
5
+ mattr_accessor :production_url, :test_url
6
+ self.production_url = 'https://secure.worldpay.com/wcc/purchase'
7
+ self.test_url = 'https://secure-test.worldpay.com/wcc/purchase'
8
+
9
+ def self.service_url
10
+ case OffsitePayments.mode
11
+ when :production
12
+ self.production_url
13
+ when :test
14
+ self.test_url
15
+ else
16
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
17
+ end
18
+ end
19
+
20
+ def self.notification(post, options = {})
21
+ Notification.new(post, options)
22
+ end
23
+
24
+ def self.return(post, options = {})
25
+ Return.new(post, options)
26
+ end
27
+
28
+ class Helper < OffsitePayments::Helper
29
+ mapping :account, 'instId'
30
+ mapping :amount, 'amount'
31
+ mapping :order, 'cartId'
32
+ mapping :currency, 'currency'
33
+
34
+ mapping :customer, :email => 'email',
35
+ :phone => 'tel'
36
+
37
+ mapping :billing_address, :zip => 'postcode',
38
+ :country => 'country'
39
+
40
+ mapping :description, 'desc'
41
+ mapping :notify_url, 'MC_callback'
42
+ mapping :return_url, 'MC_return'
43
+
44
+ # WorldPay supports two different test modes - :always_succeed and :always_fail
45
+ def initialize(order, account, options = {})
46
+ super
47
+
48
+ if OffsitePayments.mode == :test || options[:test]
49
+ test_mode = case options[:test]
50
+ when :always_fail
51
+ 101
52
+ when false
53
+ 0
54
+ else
55
+ 100
56
+ end
57
+ add_field('testMode', test_mode.to_s)
58
+ elsif OffsitePayments.mode == :always_succeed
59
+ add_field('testMode', '100')
60
+ elsif OffsitePayments.mode == :always_fail
61
+ add_field('testMode', '101')
62
+ end
63
+ end
64
+
65
+ # WorldPay only supports a single address field so we
66
+ # have to concat together - lines are separated using &#10;
67
+ def billing_address(params={})
68
+ add_field(mappings[:billing_address][:zip], params[:zip])
69
+ add_field(mappings[:billing_address][:country], lookup_country_code(params[:country]))
70
+
71
+ address = [params[:address1], params[:address2], params[:city], params[:state]].compact
72
+ add_field('address', address.join('&#10;'))
73
+ end
74
+
75
+ # WorldPay only supports a single name field so we have to concat
76
+ def customer(params={})
77
+ add_field(mappings[:customer][:email], params[:email])
78
+ add_field(mappings[:customer][:phone], params[:phone])
79
+ add_field('name', "#{params[:first_name]} #{params[:last_name]}")
80
+ end
81
+
82
+ # Support for a MD5 hash of selected fields to prevent tampering
83
+ # For further information read the tech note at the address below:
84
+ # http://support.worldpay.com/kb/integration_guides/junior/integration/help/tech_notes/sjig_tn_009.html
85
+ def encrypt(secret, fields = [:amount, :currency, :account, :order])
86
+ signature_fields = fields.collect{ |field| mappings[field] }
87
+ add_field('signatureFields', signature_fields.join(':'))
88
+
89
+ field_values = fields.collect{ |field| form_fields[mappings[field]] }
90
+ signature = "#{secret}:#{field_values.join(':')}"
91
+ add_field('signature', Digest::MD5.hexdigest(signature))
92
+ end
93
+
94
+ # Add a time window for which the payment can be completed. Read the link below for how they work
95
+ # http://support.worldpay.com/kb/integration_guides/junior/integration/help/appendicies/sjig_10100.html
96
+ def valid_from(from_time)
97
+ add_field('authValidFrom', from_time.to_i.to_s + '000')
98
+ end
99
+
100
+ def valid_to(to_time)
101
+ add_field('authValidTo', to_time.to_i.to_s + '000')
102
+ end
103
+
104
+ # WorldPay supports the passing of custom parameters prefixed with the following:
105
+ # C_ : These parameters can be used in the response pages hosted on WorldPay's site
106
+ # M_ : These parameters are passed through to the callback script (if enabled)
107
+ # MC_ or CM_ : These parameters are availble both in the response and callback contexts
108
+ def response_params(params={})
109
+ params.each{|k,v| add_field("C_#{k}",v)}
110
+ end
111
+
112
+ def callback_params(params={})
113
+ params.each{|k,v| add_field("M_#{k}",v)}
114
+ end
115
+
116
+ def combined_params(params={})
117
+ params.each{|k,v| add_field("MC_#{k}",v)}
118
+ end
119
+ end
120
+
121
+ class Notification < OffsitePayments::Notification
122
+ def complete?
123
+ status == 'Completed'
124
+ end
125
+
126
+ def account
127
+ params['instId']
128
+ end
129
+
130
+ def item_id
131
+ params['cartId']
132
+ end
133
+
134
+ def transaction_id
135
+ params['transId']
136
+ end
137
+
138
+ # Time this payment was received by the client in UTC time.
139
+ def received_at
140
+ Time.at(params['transTime'].to_i / 1000).utc
141
+ end
142
+
143
+ # Callback password set in the WorldPay CMS
144
+ def security_key
145
+ params['callbackPW']
146
+ end
147
+
148
+ # the money amount we received in X.2 decimal.
149
+ def gross
150
+ params['authAmount']
151
+ end
152
+
153
+ def currency
154
+ params['authCurrency']
155
+ end
156
+
157
+ # Was this a test transaction?
158
+ def test?
159
+ params.key?('testMode') && params['testMode'] != '0'
160
+ end
161
+
162
+ def status
163
+ params['transStatus'] == 'Y' ? 'Completed' : 'Cancelled'
164
+ end
165
+
166
+ def name
167
+ params['name']
168
+ end
169
+
170
+ def address
171
+ params['address']
172
+ end
173
+
174
+ def postcode
175
+ params['postcode']
176
+ end
177
+
178
+ def country
179
+ params['country']
180
+ end
181
+
182
+ def phone_number
183
+ params['tel']
184
+ end
185
+
186
+ def fax_number
187
+ params['fax']
188
+ end
189
+
190
+ def email_address
191
+ params['email']
192
+ end
193
+
194
+ def card_type
195
+ params['cardType']
196
+ end
197
+
198
+ # WorldPay extended fraud checks returned as a 4 character string
199
+ # 1st char: Credit card CVV check
200
+ # 2nd char: Postcode AVS check
201
+ # 3rd char: Address AVS check
202
+ # 4th char: Country comparison check
203
+ # Possible values are:
204
+ # :not_supported - 0
205
+ # :not_checked - 1
206
+ # :matched - 2
207
+ # :not_matched - 4
208
+ # :partial_match - 8
209
+ def cvv_status
210
+ return avs_value_to_symbol(params['AVS'][0].chr)
211
+ end
212
+
213
+ def postcode_status
214
+ return avs_value_to_symbol(params['AVS'][1].chr)
215
+ end
216
+
217
+ def address_status
218
+ return avs_value_to_symbol(params['AVS'][2].chr)
219
+ end
220
+
221
+ def country_status
222
+ return avs_value_to_symbol(params['AVS'][3].chr)
223
+ end
224
+
225
+ def acknowledge(authcode = nil)
226
+ return true
227
+ end
228
+
229
+ # WorldPay supports the passing of custom parameters through to the callback script
230
+ def custom_params
231
+ return @custom_params ||= read_custom_params
232
+ end
233
+
234
+ # Check if the request comes from IP range 195.35.90.0 – 195.35.91.255
235
+ def valid_sender?(ip)
236
+ return true if OffsitePayments.mode == :test
237
+ IPAddr.new("195.35.90.0/23").include?(IPAddr.new(ip))
238
+ end
239
+
240
+ private
241
+
242
+ # Take the posted data and move the relevant data into a hash
243
+ def parse(post)
244
+ @raw = post
245
+ for line in post.split('&')
246
+ key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten
247
+ params[key] = value
248
+ end
249
+ end
250
+
251
+ # Read the custom params into a hash
252
+ def read_custom_params
253
+ custom = {}
254
+ params.each do |key, value|
255
+ if /\A(M_|MC_|CM_)/ === key
256
+ custom[key.gsub(/\A(M_|MC_|CM_)/, '').to_sym] = value
257
+ end
258
+ end
259
+ custom
260
+ end
261
+
262
+ # Convert a AVS value to a symbol - see above for more about AVS
263
+ def avs_value_to_symbol(value)
264
+ case value.to_s
265
+ when '8'
266
+ :partial_match
267
+ when '4'
268
+ :no_match
269
+ when '2'
270
+ :matched
271
+ when '1'
272
+ :not_checked
273
+ else
274
+ :not_supported
275
+ end
276
+ end
277
+ end
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,175 @@
1
+ require 'net/http'
2
+
3
+ module OffsitePayments #:nodoc:
4
+ module Integrations #:nodoc:
5
+ module YandexMoney
6
+
7
+ # Start integration with yandex.money here:
8
+ # https://money.yandex.ru/joinups
9
+
10
+ # Shop example:
11
+ # https://github.com/yurijmi/yandex_money_offsite_payments_demo
12
+
13
+ mattr_accessor :production_url, :test_url
14
+
15
+ self.production_url = 'https://money.yandex.ru/eshop.xml'
16
+ self.test_url = 'https://demomoney.yandex.ru/eshop.xml'
17
+
18
+ def self.service_url
19
+ case OffsitePayments.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.notification(post)
30
+ Notification.new(post)
31
+ end
32
+
33
+ class Helper < OffsitePayments::Helper
34
+ mapping :account, 'customerNumber'
35
+ mapping :amount, 'sum'
36
+ mapping :order, 'orderNumber'
37
+ mapping :error_url, 'shopFailURL'
38
+ mapping :return_url, 'shopSuccessURL'
39
+ mapping :description, 'orderDetails'
40
+
41
+ mapping :customer, :email => 'cps_email',
42
+ :phone => 'cps_phone'
43
+
44
+ # additional yandex.money parameters
45
+ mapping :scid, 'scid'
46
+ mapping :shopId, 'shopId'
47
+ mapping :shopArticleId, 'shopArticleId'
48
+ end
49
+
50
+ class Notification < OffsitePayments::Notification
51
+ def initialize(post, options = {})
52
+ super
53
+ @response_code = '200'
54
+ end
55
+
56
+ def complete?
57
+ params['_raw_action'] == 'paymentAviso'
58
+ end
59
+
60
+ def item_id
61
+ params['_raw_orderNumber']
62
+ end
63
+
64
+ def transaction_id
65
+ params['_raw_invoiceId']
66
+ end
67
+
68
+ # When was this payment received by the client.
69
+ def received_at
70
+ params['_raw_orderCreatedDatetime']
71
+ end
72
+
73
+ def currency
74
+ params['_raw_orderSumCurrencyPaycash']
75
+ end
76
+
77
+ def payer_email
78
+ params['_raw_cps_email']
79
+ end
80
+
81
+ # the money amount we received in X.2 decimal.
82
+ def gross
83
+ params['_raw_orderSumAmount'].to_f
84
+ end
85
+
86
+ def customer_id
87
+ params['_raw_customerNumber']
88
+ end
89
+
90
+ def set_response(code)
91
+ @response_code = code
92
+ end
93
+
94
+ def get_response()
95
+ @response_code
96
+ end
97
+
98
+ # Was this a test transaction?
99
+ def test?
100
+ false
101
+ end
102
+
103
+ def status
104
+ case params['_raw_action']
105
+ when 'checkOrder'
106
+ 'pending'
107
+ when 'paymentAviso'
108
+ 'completed'
109
+ else 'unknown'
110
+ end
111
+ end
112
+
113
+ def response
114
+ shop_id = params['_raw_shopId']
115
+ method = params['_raw_action']
116
+ dt = Time.now.iso8601
117
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
118
+ "<#{method}Response performedDatetime=\"#{dt}\" code=\"#{@response_code}\"" +
119
+ " invoiceId=\"#{transaction_id}\" shopId=\"#{shop_id}\"/>"
120
+ end
121
+
122
+ # Acknowledge the transaction to YandexMoney. This method has to be called after a new
123
+ # apc arrives. YandexMoney will verify that all the information we received are correct and will return a
124
+ # ok or a fail.
125
+ #
126
+ # Example:
127
+ #
128
+ # def ipn
129
+ # notify = YandexMoneyNotification.new(request.raw_post)
130
+ #
131
+ # if notify.acknowledge(authcode)
132
+ # if notify.complete?
133
+ # ... process order ...
134
+ # end
135
+ # else
136
+ # ... log possible hacking attempt ...
137
+ # end
138
+ # render text: notify.response
139
+ #
140
+
141
+ def acknowledge(authcode = nil)
142
+ string = [params['_raw_action'],
143
+ params['_raw_orderSumAmount'],
144
+ params['_raw_orderSumCurrencyPaycash'],
145
+ params['_raw_orderSumBankPaycash'],
146
+ params['_raw_shopId'],
147
+ params['_raw_invoiceId'],
148
+ params['_raw_customerNumber'],
149
+ authcode
150
+ ].join(';')
151
+
152
+ digest = Digest::MD5.hexdigest(string)
153
+ res = params['_raw_md5'] == digest.upcase
154
+ if res
155
+ @response_code = '0'
156
+ else
157
+ @response_code = '1'
158
+ end
159
+ end
160
+
161
+ private
162
+
163
+ # Take the posted data and move the relevant data into a hash
164
+ def parse(post)
165
+ @raw = post.to_s
166
+ for line in @raw.split('&')
167
+ key, value = *line.scan( %r{^([A-Za-z0-9_.-]+)\=(.*)$} ).flatten
168
+ # to divide raw values from other
169
+ params['_raw_' + key] = CGI.unescape(value.to_s) if key.present?
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end