nma-webtopay 1.2.1
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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README +71 -0
- data/Rakefile +2 -0
- data/init.rb +2 -0
- data/lib/webtopay.rb +20 -0
- data/lib/webtopay/api.rb +407 -0
- data/lib/webtopay/configuration.rb +6 -0
- data/lib/webtopay/exception.rb +26 -0
- data/lib/webtopay/version.rb +4 -0
- data/lib/webtopay_controller.rb +35 -0
- data/lib/webtopay_helper.rb +19 -0
- data/webtopay.gemspec +22 -0
- metadata +60 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Kristijonas Urbaitis
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
WebToPay
|
2
|
+
===========
|
3
|
+
|
4
|
+
It is a plugin which could be very useful on working with https://www.webtopay.com/ (https://www.mokejimai.lt/) billing system.
|
5
|
+
The main function of this plugin is protection against forgeries that could be done by sending required parameters to the application and getting services without paying for free.
|
6
|
+
This plugin could be integrated with both billing types - MACRO (VISA, MasterCard, banks etc.) and MICRO (SMS, phone calls etc.).
|
7
|
+
|
8
|
+
*It works with OpenSSL so be sure that you have installed all necessary libs or modules on your system.
|
9
|
+
|
10
|
+
Installation
|
11
|
+
===========
|
12
|
+
|
13
|
+
cd your_application
|
14
|
+
./script/plugin install git://github.com/kristis/webtopay.git
|
15
|
+
|
16
|
+
Configuration
|
17
|
+
===========
|
18
|
+
Create initializer
|
19
|
+
config/initializers/webtopay.rb
|
20
|
+
|
21
|
+
WebToPay.configure do |config|
|
22
|
+
config.project_id = 00000
|
23
|
+
config.sign_password = 'your sign password'
|
24
|
+
end
|
25
|
+
|
26
|
+
Examples
|
27
|
+
===========
|
28
|
+
|
29
|
+
These code slices will protect your controller actions, which work with webtopay.com billing, against forgeries.
|
30
|
+
|
31
|
+
****** Usage for MICRO and MACRO billing on controller:
|
32
|
+
|
33
|
+
[........]
|
34
|
+
|
35
|
+
webtopay :activate_user, :confirm_cart # You can add here as many actions as you want
|
36
|
+
|
37
|
+
def activate_user
|
38
|
+
# write here code which do some stuff
|
39
|
+
render :text => "Your user has been successfully activated. Thank you!" # it sends SMS answer
|
40
|
+
end
|
41
|
+
|
42
|
+
def confirm_cart
|
43
|
+
# write here code which do some stuff
|
44
|
+
render :text => "ok" # it sends successful answer to webtopay.com crawler
|
45
|
+
end
|
46
|
+
|
47
|
+
[........]
|
48
|
+
|
49
|
+
****** You can also use helper method to generate required form for MACRO billing query:
|
50
|
+
|
51
|
+
[........]
|
52
|
+
|
53
|
+
<% macro_form :test => 1, :orderid => 123, :amount => 2000, :payment => 'vb', :country => 'lt', :paytext => "Billing for XX at the website XXX" do %>
|
54
|
+
Select paying method: <%= select_tag(:payment, options_for_select(['', 'vb', 'hanza', 'nord', 'snoras'])) %>
|
55
|
+
<%= submit_tag "test paying" %>
|
56
|
+
<% end %>
|
57
|
+
|
58
|
+
[........]
|
59
|
+
|
60
|
+
* Attention!!! Be sure that you have set required option, which let sending test requests, at your webtopay.com account settings at first if you want to use test requests.
|
61
|
+
* You can add into the helper options additional parameters or remove them according to technical specifications at https://www.webtopay.com/ .
|
62
|
+
|
63
|
+
TODO
|
64
|
+
===========
|
65
|
+
|
66
|
+
1. Write more clear documentation with real examples
|
67
|
+
2. Write unit tests for each billing method (requires some testing data from https://www.webtopay.com/)
|
68
|
+
3. Add more settings for controller filters
|
69
|
+
|
70
|
+
===========
|
71
|
+
Copyright (c) 2009 Kristijonas Urbaitis, released under the MIT license
|
data/Rakefile
ADDED
data/init.rb
ADDED
data/lib/webtopay.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'webtopay/exception'
|
2
|
+
require 'webtopay/configuration'
|
3
|
+
require 'webtopay/api'
|
4
|
+
require 'webtopay_controller'
|
5
|
+
require 'webtopay_helper'
|
6
|
+
|
7
|
+
module WebToPay
|
8
|
+
class << self
|
9
|
+
attr_accessor :config
|
10
|
+
|
11
|
+
def configure
|
12
|
+
self.config ||= Configuration.new
|
13
|
+
yield(config)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
ActionController::Base.send(:include, WebToPayController)
|
19
|
+
ActionView::Base.send(:include, WebToPayHelper)
|
20
|
+
|
data/lib/webtopay/api.rb
ADDED
@@ -0,0 +1,407 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'openssl'
|
3
|
+
require 'open-uri'
|
4
|
+
|
5
|
+
module WebToPay
|
6
|
+
class Api
|
7
|
+
VERSION = "1.4"
|
8
|
+
PREFIX = "wp_"
|
9
|
+
CERT_PATH = "http://downloads.webtopay.com/download/public.key"
|
10
|
+
|
11
|
+
# Array structure:
|
12
|
+
# * name – request item name.
|
13
|
+
# * maxlen – max allowed value for item.
|
14
|
+
# * required – is this item is required.
|
15
|
+
# * user – if true, user can set value of this item, if false
|
16
|
+
# item value is generated.
|
17
|
+
# * isrequest – if true, item will be included in request array, if
|
18
|
+
# false, item only be used internaly and will not be
|
19
|
+
# included in outgoing request array.
|
20
|
+
# * regexp – regexp to test item value.
|
21
|
+
REQUEST_SPECS = [ [ :projectid, 11, true, true, true, /^\d+$/ ],
|
22
|
+
[ :orderid, 40, true, true, true, '' ],
|
23
|
+
[ :lang, 3, false, true, true, /^[a-z]{3}$/i ],
|
24
|
+
[ :amount, 11, false, true, true, /^\d+$/ ],
|
25
|
+
[ :currency, 3, false, true, true, /^[a-z]{3}$/i ],
|
26
|
+
[ :accepturl, 255, true, true, true, '' ],
|
27
|
+
[ :cancelurl, 255, true, true, true, '' ],
|
28
|
+
[ :callbackurl, 255, true, true, true, '' ],
|
29
|
+
[ :payment, 20, false, true, true, '' ],
|
30
|
+
[ :country, 2, false, true, true, /^[a-z]{2}$/i ],
|
31
|
+
[ :paytext, 255, false, true, true, '' ],
|
32
|
+
[ :p_firstname, 255, false, true, true, '' ],
|
33
|
+
[ :p_lastname, 255, false, true, true, '' ],
|
34
|
+
[ :p_email, 255, false, true, true, '' ],
|
35
|
+
[ :p_street, 255, false, true, true, '' ],
|
36
|
+
[ :p_city, 255, false, true, true, '' ],
|
37
|
+
[ :p_state, 20, false, true, true, '' ],
|
38
|
+
[ :p_zip, 20, false, true, true, '' ],
|
39
|
+
[ :p_countrycode, 2, false, true, true, /^[a-z]{2}$/i ],
|
40
|
+
[ :sign, 255, true, false, true, '' ],
|
41
|
+
[ :sign_password, 255, true, true, false, '' ],
|
42
|
+
[ :test, 1, false, true, true, /^[01]$/ ],
|
43
|
+
[ :version, 9, true, false, true, /^\d+\.\d+$/ ] ]
|
44
|
+
|
45
|
+
# Array structure:
|
46
|
+
# * name – request item name.
|
47
|
+
# * maxlen – max allowed value for item.
|
48
|
+
# * required – is this item is required in response.
|
49
|
+
# * mustcheck – this item must be checked by user.
|
50
|
+
# * isresponse – if false, item must not be included in response array.
|
51
|
+
# * regexp – regexp to test item value.
|
52
|
+
MAKRO_RESPONSE_SPECS = [
|
53
|
+
[ :projectid, 11, true, true, true, /^\d+$/ ],
|
54
|
+
[ :orderid, 40, false, false, true, '' ],
|
55
|
+
[ :lang, 3, false, false, true, /^[a-z]{3}$/i ],
|
56
|
+
[ :amount, 11, false, false, true, /^\d+$/ ],
|
57
|
+
[ :currency, 3, false, false, true, /^[a-z]{3}$/i ],
|
58
|
+
[ :payment, 20, false, false, true, '' ],
|
59
|
+
[ :country, 2, false, false, true, /^[a-z]{2}$/i ],
|
60
|
+
[ :paytext, 0, false, false, true, '' ],
|
61
|
+
[ :_ss2, 0, true, false, true, '' ],
|
62
|
+
[ :_ss1, 0, false, false, true, '' ],
|
63
|
+
[ :name, 255, false, false, true, '' ],
|
64
|
+
[ :surename, 255, false, false, true, '' ],
|
65
|
+
[ :status, 255, false, false, true, '' ],
|
66
|
+
[ :error, 20, false, false, true, '' ],
|
67
|
+
[ :test, 1, false, false, true, /^[01]$/ ],
|
68
|
+
[ :p_email, 0, false, false, true, '' ],
|
69
|
+
[ :payamount, 0, false, false, true, '' ],
|
70
|
+
[ :paycurrency, 0, false, false, true, '' ],
|
71
|
+
[ :version, 9, true, false, true, /^\d+\.\d+$/ ],
|
72
|
+
[ :sign_password, 255, false, true, false, '' ] ]
|
73
|
+
|
74
|
+
# Specification array for mikro response.
|
75
|
+
#
|
76
|
+
# Array structure:
|
77
|
+
# * name – request item name.
|
78
|
+
# * maxlen – max allowed value for item.
|
79
|
+
# * required – is this item is required in response.
|
80
|
+
# * mustcheck – this item must be checked by user.
|
81
|
+
# * isresponse – if false, item must not be included in response array.
|
82
|
+
# * regexp – regexp to test item value.
|
83
|
+
MIKRO_RESPONSE_SPECS = [
|
84
|
+
[ :to, 0, true, false, true, '' ],
|
85
|
+
[ :sms, 0, true, false, true, '' ],
|
86
|
+
[ :from, 0, true, false, true, '' ],
|
87
|
+
[ :operator, 0, true, false, true, '' ],
|
88
|
+
[ :amount, 0, true, false, true, '' ],
|
89
|
+
[ :currency, 0, true, false, true, '' ],
|
90
|
+
[ :country, 0, true, false, true, '' ],
|
91
|
+
[ :id, 0, true, false, true, '' ],
|
92
|
+
[ :_ss2, 0, true, false, true, '' ],
|
93
|
+
[ :_ss1, 0, true, false, true, '' ],
|
94
|
+
[ :test, 0, true, false, true, '' ],
|
95
|
+
[ :key, 0, true, false, true, '' ],
|
96
|
+
#[ :version, 9, true, false, true, /^\d+\.\d+$/ ]
|
97
|
+
]
|
98
|
+
|
99
|
+
# Checks user given request data array.
|
100
|
+
#
|
101
|
+
# If any errors occurs, WebToPay::Exception will be raised.
|
102
|
+
#
|
103
|
+
# This method returns validated request array. Returned array contains
|
104
|
+
# only those items from data, that are needed.
|
105
|
+
#
|
106
|
+
def self.check_request_data(data)
|
107
|
+
request = {}
|
108
|
+
data.symbolize_keys!
|
109
|
+
|
110
|
+
REQUEST_SPECS.each do |spec|
|
111
|
+
name, maxlen, required, user, isrequest, regexp = spec
|
112
|
+
|
113
|
+
next unless user
|
114
|
+
|
115
|
+
name = name.to_sym
|
116
|
+
|
117
|
+
if required && data[name].nil?
|
118
|
+
e = Exception.new self._("'%s' is required but missing.", name)
|
119
|
+
e.code = Exception::E_MISSING
|
120
|
+
e.field_name = name
|
121
|
+
raise e
|
122
|
+
end
|
123
|
+
|
124
|
+
unless data[name].to_s.empty?
|
125
|
+
if (maxlen && data[name].to_s.length > maxlen)
|
126
|
+
e = Exception.new self._("'%s' value '%s' is too long, %d characters allowed.",
|
127
|
+
name, data[name], maxlen)
|
128
|
+
e.code = Exception::E_MAXLEN
|
129
|
+
e.field_name = name
|
130
|
+
raise e
|
131
|
+
end
|
132
|
+
|
133
|
+
if ('' != regexp && !data[name].to_s.match(regexp))
|
134
|
+
e = Exception.new self._("'%s' value '%s' is invalid.", name, data[name])
|
135
|
+
e.code = Exception::E_REGEXP
|
136
|
+
e.field_name = name
|
137
|
+
raise e
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
if isrequest && !data[name].nil?
|
142
|
+
request[name] = data[name]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
return request
|
147
|
+
end
|
148
|
+
|
149
|
+
# Puts signature on request data hash
|
150
|
+
def self.sign_request(request, password)
|
151
|
+
fields = [ :projectid, :orderid, :lang, :amount, :currency,
|
152
|
+
:accepturl, :cancelurl, :callbackurl, :payment, :country,
|
153
|
+
:p_firstname, :p_lastname, :p_email, :p_street,
|
154
|
+
:p_city, :p_state, :p_zip, :p_countrycode, :test,
|
155
|
+
:version ]
|
156
|
+
|
157
|
+
request.symbolize_keys!
|
158
|
+
|
159
|
+
data = ''
|
160
|
+
|
161
|
+
fields.each do |key|
|
162
|
+
val = request[key].to_s
|
163
|
+
|
164
|
+
unless val.strip.blank?
|
165
|
+
data+= val
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
request[:sign] = Digest::MD5.hexdigest(data + password)
|
170
|
+
|
171
|
+
return request
|
172
|
+
end
|
173
|
+
|
174
|
+
# Builds request data array.
|
175
|
+
#
|
176
|
+
# This method checks all given data and generates correct request data
|
177
|
+
# array or raises WebToPayException on failure.
|
178
|
+
#
|
179
|
+
# Method accepts single parameter $data of array type. All possible array
|
180
|
+
# keys are described here:
|
181
|
+
# https://www.mokejimai.lt/makro_specifikacija.html
|
182
|
+
def self.build_request(data)
|
183
|
+
data.symbolize_keys!
|
184
|
+
|
185
|
+
request = self.check_request_data(data)
|
186
|
+
request[:version] = self::VERSION
|
187
|
+
request = self.sign_request(request, data[:sign_password])
|
188
|
+
|
189
|
+
return request
|
190
|
+
end
|
191
|
+
|
192
|
+
# Checks and validates response from WebToPay server.
|
193
|
+
#
|
194
|
+
# This function accepts both mikro and makro responses.
|
195
|
+
#
|
196
|
+
# First parameter usualy should by params hash
|
197
|
+
#
|
198
|
+
# Description about response can be found here:
|
199
|
+
# makro: https://www.mokejimai.lt/makro_specifikacija.html
|
200
|
+
# mikro: https://www.mokejimai.lt/mikro_mokejimu_specifikacija_SMS.html
|
201
|
+
#
|
202
|
+
# If response is not correct, WebToPay::Exception will be raised.
|
203
|
+
def self.check_response(query, user_data = {})
|
204
|
+
@@verified = false;
|
205
|
+
|
206
|
+
response = self.query_to_response(query)
|
207
|
+
response = self.get_prefixed(response, self::PREFIX)
|
208
|
+
response.symbolize_keys!
|
209
|
+
|
210
|
+
# *get* response type (makro|mikro)
|
211
|
+
type, specs = self.get_specs_for_response(response)
|
212
|
+
|
213
|
+
self.check_response_data(response, user_data, specs)
|
214
|
+
@@verified = 'RESPONSE';
|
215
|
+
|
216
|
+
# *check* response
|
217
|
+
if :makro == type && response[:version] != self::VERSION
|
218
|
+
e = Exception.new(self._('Incompatible library and response versions: ' +
|
219
|
+
'libwebtopay %s, response %s', self::VERSION, response[:version]))
|
220
|
+
e.code = Exception::E_INVALID
|
221
|
+
raise e
|
222
|
+
end
|
223
|
+
|
224
|
+
if :makro == type
|
225
|
+
@@verified = 'RESPONSE VERSION ' + response[:version] + ' OK'
|
226
|
+
end
|
227
|
+
|
228
|
+
orderid = :makro == type ? response[:orderid] : response[:id]
|
229
|
+
password = user_data[:sign_password]
|
230
|
+
|
231
|
+
if self.check_response_cert(query)
|
232
|
+
@@verified = 'SS2 public.key'
|
233
|
+
end
|
234
|
+
|
235
|
+
# *check* status
|
236
|
+
if :makro == type && 1 != response[:status].to_i
|
237
|
+
e = Exception.new(self._('Returned transaction status is %d, successful status ' +
|
238
|
+
'should be 1.', response[:status]))
|
239
|
+
e.code = Exception::E_INVALID
|
240
|
+
raise e
|
241
|
+
end
|
242
|
+
|
243
|
+
return response
|
244
|
+
end
|
245
|
+
|
246
|
+
def self.check_response_data(response, mustcheck_data, specs)
|
247
|
+
resp_keys = []
|
248
|
+
|
249
|
+
response.symbolize_keys!
|
250
|
+
mustcheck_data.symbolize_keys!
|
251
|
+
|
252
|
+
specs.each do |spec|
|
253
|
+
name, maxlen, required, mustcheck, is_response, regexp = spec
|
254
|
+
|
255
|
+
if required && response[name].nil?
|
256
|
+
e = Exception.new(self._("'%s' is required but missing.", name))
|
257
|
+
e.code = Exception::E_MISSING
|
258
|
+
e.field_name = name
|
259
|
+
raise e
|
260
|
+
end
|
261
|
+
|
262
|
+
if mustcheck
|
263
|
+
if mustcheck_data[name].nil?
|
264
|
+
e = Exception.new(self._("'%s' must exists in array of second " +
|
265
|
+
"parameter of checkResponse() method.", name))
|
266
|
+
e.code = Exception::E_USER_PARAMS
|
267
|
+
e.field_name = name
|
268
|
+
raise e
|
269
|
+
end
|
270
|
+
|
271
|
+
if is_response
|
272
|
+
if response[name].to_s != mustcheck_data[name].to_s
|
273
|
+
e = Exception.new(self._("'%s' yours and requested value is not " +
|
274
|
+
"equal ('%s' != '%s') ",
|
275
|
+
name, mustcheck_data[name], response[name]))
|
276
|
+
e.code = Exception::E_INVALID
|
277
|
+
e.field_name = name
|
278
|
+
raise e
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
if !response[name].to_s.empty?
|
284
|
+
if maxlen > 0 && response[name].to_s.length > maxlen
|
285
|
+
e = Exception.new(self._("'%s' value '%s' is too long, %d characters allowed.",
|
286
|
+
name, response[name], maxlen))
|
287
|
+
e.code = Exception::E_MAXLEN
|
288
|
+
e.field_name = name
|
289
|
+
raise e
|
290
|
+
end
|
291
|
+
|
292
|
+
if '' != regexp && !response[name].to_s.match(regexp)
|
293
|
+
e = new WebToPayException(self._("'%s' value '%s' is invalid.",
|
294
|
+
name, response[name]))
|
295
|
+
e.code = Exception::E_REGEXP
|
296
|
+
e.field_name = name
|
297
|
+
raise e
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
resp_keys << name unless response[name].nil?
|
302
|
+
end
|
303
|
+
|
304
|
+
# Filter only parameters passed from webtopay
|
305
|
+
_response = {}
|
306
|
+
|
307
|
+
response.keys.each do |key|
|
308
|
+
_response[key] = response[key] if resp_keys.include?(key)
|
309
|
+
end
|
310
|
+
|
311
|
+
return _response
|
312
|
+
end
|
313
|
+
|
314
|
+
# Return type and specification of given response array.
|
315
|
+
def self.get_specs_for_response(response)
|
316
|
+
response.symbolize_keys!
|
317
|
+
|
318
|
+
if ( !response[:to].nil? && !response[:from].nil? &&
|
319
|
+
!response[:sms].nil? && response[:projectid].nil? )
|
320
|
+
|
321
|
+
type = :mikro
|
322
|
+
specs = self::MIKRO_RESPONSE_SPECS
|
323
|
+
else
|
324
|
+
type = :makro
|
325
|
+
specs = self::MAKRO_RESPONSE_SPECS
|
326
|
+
end
|
327
|
+
|
328
|
+
return [ type, specs ]
|
329
|
+
end
|
330
|
+
|
331
|
+
# Check if response certificate is valid
|
332
|
+
def self.check_response_cert(query)
|
333
|
+
public_key = self.get_public_key
|
334
|
+
|
335
|
+
if (!public_key)
|
336
|
+
e = Exception.new(self._('Can\'t get openssl public key for %s', cert))
|
337
|
+
e.code = Exception::E_INVALID
|
338
|
+
raise e
|
339
|
+
end
|
340
|
+
|
341
|
+
res = self.query_to_response(query)
|
342
|
+
res = self.get_prefixed(res, PREFIX).symbolize_keys
|
343
|
+
keys = self.get_query_keys(query)
|
344
|
+
skip = [ :_ss2, :controller, :action ]
|
345
|
+
_SS2 = ''
|
346
|
+
|
347
|
+
keys.each do |key|
|
348
|
+
if !skip.include?(key)
|
349
|
+
_SS2 << res[key].to_s + '|'
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
if !public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(res[:_ss2]), _SS2)
|
354
|
+
e = Exception.new(self._('Can\'t verify SS2'))
|
355
|
+
e.code = Exception::E_INVALID
|
356
|
+
raise e
|
357
|
+
end
|
358
|
+
|
359
|
+
return true
|
360
|
+
end
|
361
|
+
|
362
|
+
def self.get_public_key
|
363
|
+
OpenSSL::X509::Certificate.new(open(CERT_PATH).read).public_key
|
364
|
+
end
|
365
|
+
|
366
|
+
def self.get_prefixed(data, prefix)
|
367
|
+
return data if prefix.to_s.blank?
|
368
|
+
|
369
|
+
ret = {}
|
370
|
+
reg = /^#{prefix}/
|
371
|
+
|
372
|
+
data.stringify_keys!
|
373
|
+
|
374
|
+
data.each_pair do |key, val|
|
375
|
+
if key.length > prefix.length && key.match(reg)
|
376
|
+
ret[key.gsub(reg, '')] = val
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
return ret
|
381
|
+
end
|
382
|
+
|
383
|
+
def self.query_to_response(query)
|
384
|
+
response = {}
|
385
|
+
|
386
|
+
query.split(/&/).each do |item|
|
387
|
+
key, val = item.split(/\=/)
|
388
|
+
response[key] = CGI.unescape(val.to_s)
|
389
|
+
end
|
390
|
+
|
391
|
+
return response
|
392
|
+
end
|
393
|
+
|
394
|
+
def self.get_query_keys(query)
|
395
|
+
query.split(/&/).collect { |i| i.split(/\=/).first.gsub(/^#{PREFIX}/, '').to_sym }
|
396
|
+
end
|
397
|
+
|
398
|
+
# I18n support.
|
399
|
+
def self._(*args)
|
400
|
+
if args.length > 1
|
401
|
+
return send(:sprintf, *args)
|
402
|
+
else
|
403
|
+
return args[0]
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module WebToPay
|
2
|
+
class Exception < ::Exception
|
3
|
+
# Missing field.
|
4
|
+
E_MISSING = 1
|
5
|
+
|
6
|
+
# Invalid field value.
|
7
|
+
E_INVALID = 2
|
8
|
+
|
9
|
+
# Max length exceeded.
|
10
|
+
E_MAXLEN = 3
|
11
|
+
|
12
|
+
# Regexp for field value doesn't match.
|
13
|
+
E_REGEXP = 4
|
14
|
+
|
15
|
+
# Missing or invalid user given parameters.
|
16
|
+
E_USER_PARAMS = 5
|
17
|
+
|
18
|
+
# Logging errors
|
19
|
+
E_LOG = 6
|
20
|
+
|
21
|
+
# SMS answer errors
|
22
|
+
E_SMS_ANSWER = 7
|
23
|
+
|
24
|
+
attr_accessor :code, :field_name
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module WebToPayController
|
2
|
+
module ClassMethods
|
3
|
+
def webtopay(*actions)
|
4
|
+
before_filter :webtopay_check
|
5
|
+
write_inheritable_array(:actions, actions)
|
6
|
+
|
7
|
+
attr_reader :webtopay_response
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.included(controller)
|
12
|
+
controller.extend(ClassMethods)
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def webtopay_required?
|
18
|
+
(self.class.read_inheritable_attribute(:actions) || []).include?(action_name.to_sym)
|
19
|
+
end
|
20
|
+
|
21
|
+
def webtopay_check
|
22
|
+
if webtopay_required?
|
23
|
+
begin
|
24
|
+
|
25
|
+
@webtopay_response = WebToPay::Api.check_response(request.query_string, {
|
26
|
+
:projectid => WebToPay.config.project_id,
|
27
|
+
:sign_password => WebToPay.config.sign_password
|
28
|
+
})
|
29
|
+
|
30
|
+
rescue WebToPay::Exception => e
|
31
|
+
render :text => e.message, :status => 500
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module WebToPayHelper
|
2
|
+
def macro_form(params, &block)
|
3
|
+
fields = {:orderid => "1", :lang => 'LIT', :amount => 0, :currency => 'LTL',
|
4
|
+
:accepturl => 'http://google.com', :cancelurl => 'http://yahoo.com', :callbackurl => 'http://yourdomain.com',
|
5
|
+
:projectid => WebToPay.config.project_id,
|
6
|
+
:sign_password => WebToPay.config.sign_password,
|
7
|
+
:test => 0}
|
8
|
+
|
9
|
+
fields.merge!(params)
|
10
|
+
|
11
|
+
request = WebToPay::Api.build_request(fields)
|
12
|
+
|
13
|
+
concat "<form action=\"https://www.mokejimai.lt/pay/\" method=\"post\" style=\"padding:0px;margin:0px\">".html_safe
|
14
|
+
request.each_pair {|k,v| concat hidden_field_tag(k, v) if !v.nil? }
|
15
|
+
yield if block_given?
|
16
|
+
concat "</form>".html_safe
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
data/webtopay.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "webtopay/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "nma-webtopay"
|
7
|
+
s.version = Webtopay::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Nacionaline Moksleiviu Akademija"]
|
10
|
+
s.email = ["dev@nmakademija.lt"]
|
11
|
+
s.homepage = "https://github.com/nmakademija/webtopay"
|
12
|
+
s.summary = %q{Provides integration with http://www.webtopay.com (mokejimai.lt) payment system}
|
13
|
+
s.description = %q{Verifies webtopay.com (mokejimai.lt) payment data transfer}
|
14
|
+
|
15
|
+
s.rubyforge_project = "nma-webtopay"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
22
|
+
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nma-webtopay
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nacionaline Moksleiviu Akademija
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-09-05 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: Verifies webtopay.com (mokejimai.lt) payment data transfer
|
15
|
+
email:
|
16
|
+
- dev@nmakademija.lt
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- Gemfile
|
23
|
+
- MIT-LICENSE
|
24
|
+
- README
|
25
|
+
- Rakefile
|
26
|
+
- init.rb
|
27
|
+
- lib/webtopay.rb
|
28
|
+
- lib/webtopay/api.rb
|
29
|
+
- lib/webtopay/configuration.rb
|
30
|
+
- lib/webtopay/exception.rb
|
31
|
+
- lib/webtopay/version.rb
|
32
|
+
- lib/webtopay_controller.rb
|
33
|
+
- lib/webtopay_helper.rb
|
34
|
+
- webtopay.gemspec
|
35
|
+
homepage: https://github.com/nmakademija/webtopay
|
36
|
+
licenses: []
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project: nma-webtopay
|
55
|
+
rubygems_version: 1.8.10
|
56
|
+
signing_key:
|
57
|
+
specification_version: 3
|
58
|
+
summary: Provides integration with http://www.webtopay.com (mokejimai.lt) payment
|
59
|
+
system
|
60
|
+
test_files: []
|