webmoney 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +9 -0
- data/README +4 -3
- data/RUNNING_TESTS +21 -6
- data/VERSION +1 -1
- data/lib/interfaces.rb +28 -0
- data/lib/passport.rb +1 -1
- data/lib/request_result.rb +16 -6
- data/lib/request_retval.rb +12 -0
- data/lib/request_xml.rb +14 -0
- data/lib/webmoney.rb +7 -33
- data/spec/spec_helper.rb +17 -23
- data/spec/unit/webmoney_spec.rb +29 -13
- data/webmoney.gemspec +3 -2
- metadata +4 -7
data/ChangeLog
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
ChangeLog
|
2
2
|
|
3
|
+
Wed Oct 06 2010 11:14:00 +0300
|
4
|
+
----------------------------
|
5
|
+
V 0.0.10
|
6
|
+
* Add login interface
|
7
|
+
* Fix bug in Passport, when datereg == 0
|
8
|
+
* Earlier added:
|
9
|
+
- create_invoice - x1
|
10
|
+
- outgoing_invoices - x4
|
11
|
+
|
3
12
|
Mon Sep 20 2010 14:31:00 +0300
|
4
13
|
----------------------------
|
5
14
|
V 0.0.9
|
data/README
CHANGED
@@ -14,16 +14,17 @@ License:: MIT License
|
|
14
14
|
== Request types
|
15
15
|
|
16
16
|
Completed:
|
17
|
+
- create_invoice - x1
|
18
|
+
- create_transaction - x2
|
19
|
+
- outgoing_invoices - x4
|
17
20
|
- send_message - x6
|
18
21
|
- get_passport - x11
|
19
22
|
- find_wm - x8
|
20
23
|
- bussines_level
|
24
|
+
- login
|
21
25
|
|
22
26
|
Incompleted (help need!):
|
23
|
-
- create_invoice - x1
|
24
|
-
- create_transaction - x2
|
25
27
|
- operation_history - x3
|
26
|
-
- outgoing_invoices - x4
|
27
28
|
- finish_protect - x5
|
28
29
|
- check_sign - x7
|
29
30
|
- balance - x9
|
data/RUNNING_TESTS
CHANGED
@@ -1,12 +1,27 @@
|
|
1
1
|
== Running tests
|
2
2
|
|
3
|
-
|
3
|
+
First, you should have two WMIDs associated with Personal attestate (WMT require!).
|
4
|
+
Then, create ~/.wm/config.yml file:
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
ca_cert: file_or_path_to_directory # optional, all needed certs in lib
|
7
|
+
first:
|
8
|
+
wmtype: classic
|
9
|
+
wmid: '123456789012' # quotes for interpretate as string
|
8
10
|
key: 'gQABAIR6... YOUR BASE64-KEY (see wmsigner readme) ...2cC8FZTyKyjBM='
|
9
11
|
password: _your_password_
|
10
|
-
|
12
|
+
wmz: Z123456789012
|
13
|
+
second:
|
14
|
+
wmtype: light
|
15
|
+
wmid: '012345678901'
|
16
|
+
password: _your_another_password_
|
17
|
+
cert: webmoney.pem
|
18
|
+
key: webmoney.key
|
19
|
+
wmz: Z012345678901
|
20
|
+
rid: 57f9ff86-1afb-431f-aff4-9dfb00b70773 # site RID from login.wmtransfer.com
|
11
21
|
|
12
|
-
|
22
|
+
|
23
|
+
|
24
|
+
HOWTO convert Light-keys:
|
25
|
+
Russian: https://wiki.webmoney.ru/wiki/show/Konvertatsiya_klyuchey_WM_Keeper_Light_v_PEM_format
|
26
|
+
|
27
|
+
Then type (RSpec required): rake spec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.10
|
data/lib/interfaces.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Webmoney
|
2
|
+
# Presets for interfaces
|
3
|
+
def interface_urls
|
4
|
+
{
|
5
|
+
:create_invoice => w3s_url + 'XMLInvoice.asp', # x1
|
6
|
+
:create_transaction => w3s_url + 'XMLTrans.asp', # x2
|
7
|
+
:operation_history => w3s_url + 'XMLOperations.asp', # x3
|
8
|
+
:outgoing_invoices => w3s_url + 'XMLOutInvoices.asp', # x4
|
9
|
+
:finish_protect => w3s_url + 'XMLFinishProtect.asp', # x5
|
10
|
+
:send_message => w3s_url + 'XMLSendMsg.asp', # x6
|
11
|
+
:check_sign => w3s_url + 'XMLClassicAuth.asp', # x7
|
12
|
+
:find_wm => w3s_url + 'XMLFindWMPurse.asp', # x8
|
13
|
+
:balance => w3s_url + 'XMLPurses.asp', # x9
|
14
|
+
:incoming_invoices => w3s_url + 'XMLInInvoices.asp', # x10
|
15
|
+
:get_passport => 'https://passport.webmoney.ru/asp/XMLGetWMPassport.asp', # x11
|
16
|
+
:reject_protection => w3s_url + 'XMLRejectProtect.asp', # x13
|
17
|
+
:transaction_moneyback => w3s_url + 'XMLTransMoneyback.asp', # x14
|
18
|
+
:i_trust => w3s_url + 'XMLTrustList.asp', # x15
|
19
|
+
:trust_me => w3s_url + 'XMLTrustList2.asp', # x15
|
20
|
+
:trust_save => w3s_url + 'XMLTrustSave2.asp', # x15
|
21
|
+
:create_purse => w3s_url + 'XMLCreatePurse.asp', # x16
|
22
|
+
:create_contract => 'https://arbitrage.webmoney.ru/xml/X17_CreateContract.aspx', # x17
|
23
|
+
:transaction_get => 'https://merchant.webmoney.ru/conf/xml/XMLTransGet.asp', # x18
|
24
|
+
:bussines_level => 'https://stats.wmtransfer.com/levels/XMLWMIDLevel.aspx',
|
25
|
+
:login => 'https://login.wmtransfer.com/ws/authorize.xiface' # login
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
data/lib/passport.rb
CHANGED
@@ -76,7 +76,7 @@ module Webmoney
|
|
76
76
|
end
|
77
77
|
|
78
78
|
wmids = root.xpath('certinfo/wmids/row').inject({}) do |memo, elm|
|
79
|
-
attrs = {:created_at => Time.xmlschema(elm['datereg'])}
|
79
|
+
attrs = {:created_at => (Time.xmlschema(elm['datereg']) rescue nil)}
|
80
80
|
attrs.merge!(:nickname => elm['nickname']) unless elm['nickname'].empty?
|
81
81
|
attrs.merge!(:info => elm['info']) unless elm['info'].empty?
|
82
82
|
memo.merge!(elm['wmid'] => attrs)
|
data/lib/request_result.rb
CHANGED
@@ -14,10 +14,10 @@ module Webmoney::RequestResult # :nodoc:all
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def result_send_message(doc)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
{
|
18
|
+
:id => doc.at('//message')['id'],
|
19
|
+
:date => Time.parse(doc.at('//message/datecrt').inner_html)
|
20
|
+
}
|
21
21
|
end
|
22
22
|
|
23
23
|
def result_find_wm(doc)
|
@@ -38,7 +38,7 @@ module Webmoney::RequestResult # :nodoc:all
|
|
38
38
|
res[:id] = (doc.at('//invoice').attributes['id'].value.to_i)
|
39
39
|
res[:ts] = (doc.at('//invoice').attributes['ts'].value.to_i)
|
40
40
|
res[:state] = (doc.at('//invoice/state').inner_html.to_i)
|
41
|
-
res[:created_at] =
|
41
|
+
res[:created_at] = Time.parse(doc.at('//invoice/datecrt').inner_html)
|
42
42
|
end
|
43
43
|
res
|
44
44
|
end
|
@@ -69,7 +69,7 @@ module Webmoney::RequestResult # :nodoc:all
|
|
69
69
|
value = tag.inner_html
|
70
70
|
value = value.to_i if [:orderid, :tranid, :period, :expiration, :wmtranid, :state].include?(name)
|
71
71
|
value = value.to_f if [:rest, :amount, :comiss].include?(name)
|
72
|
-
value =
|
72
|
+
value = Time.parse(value) if [:datecrt, :dateupd].include?(name)
|
73
73
|
r[name] = value
|
74
74
|
end
|
75
75
|
r
|
@@ -77,4 +77,14 @@ module Webmoney::RequestResult # :nodoc:all
|
|
77
77
|
end
|
78
78
|
res
|
79
79
|
end
|
80
|
+
|
81
|
+
def result_login(doc)
|
82
|
+
{
|
83
|
+
:retval => doc.at('/response')['retval'].to_i,
|
84
|
+
:retdesc => doc.at('/response')['sval'],
|
85
|
+
:lastAccess => doc.at('/response')['lastAccess'],
|
86
|
+
:expires => doc.at('/response')['expires']
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
80
90
|
end
|
data/lib/request_retval.rb
CHANGED
@@ -32,4 +32,16 @@ module Webmoney::RequestRetval # :nodoc:all
|
|
32
32
|
@errormsg = doc.at('//retdesc').inner_html
|
33
33
|
raise Webmoney::ResultError, [@error, @errormsg].join(' ') unless @error == 0
|
34
34
|
end
|
35
|
+
|
36
|
+
def retval_login(doc)
|
37
|
+
if retval = doc.at('/response')['retval']
|
38
|
+
@error = retval.to_i
|
39
|
+
@errormsg = doc.at('/response')['sval']
|
40
|
+
else
|
41
|
+
@error = -3
|
42
|
+
@errormsg = 'Unknown response'
|
43
|
+
end
|
44
|
+
raise Webmoney::ResultError, [@error, @errormsg].join(' ') unless @error == 0
|
45
|
+
end
|
46
|
+
|
35
47
|
end
|
data/lib/request_xml.rb
CHANGED
@@ -154,4 +154,18 @@ module Webmoney::RequestXML # :nodoc:all
|
|
154
154
|
}
|
155
155
|
}
|
156
156
|
end
|
157
|
+
|
158
|
+
def xml_login(opt)
|
159
|
+
Nokogiri::XML::Builder.new { |x|
|
160
|
+
x.send('request') {
|
161
|
+
x.siteHolder opt[:siteHolder] || @wmid
|
162
|
+
x.user opt[:WmLogin_WMID]
|
163
|
+
x.ticket opt[:WmLogin_Ticket]
|
164
|
+
x.urlId opt[:WmLogin_UrlID]
|
165
|
+
x.authType opt[:WmLogin_AuthType]
|
166
|
+
x.userAddress opt[:remote_ip]
|
167
|
+
}
|
168
|
+
}
|
169
|
+
end
|
170
|
+
|
157
171
|
end
|
data/lib/webmoney.rb
CHANGED
@@ -11,7 +11,7 @@ require 'iconv'
|
|
11
11
|
require 'nokogiri'
|
12
12
|
|
13
13
|
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
|
14
|
-
%w(wmsigner wmid passport purse request_xml request_retval request_result messenger).each
|
14
|
+
%w(wmsigner interfaces wmid passport purse request_xml request_retval request_result messenger).each{|lib| require lib}
|
15
15
|
|
16
16
|
# Module for Webmoney lib. Instance contain info
|
17
17
|
# for WMT-interfaces requests (wmid, key, etc).
|
@@ -31,7 +31,7 @@ module Webmoney
|
|
31
31
|
class NonExistentWmidError < WebmoneyError; end
|
32
32
|
class CaCertificateError < WebmoneyError; end
|
33
33
|
|
34
|
-
attr_reader :wmid, :error, :errormsg, :last_request, :last_response, :interfaces
|
34
|
+
attr_reader :wmid, :error, :errormsg, :last_request, :last_response, :interfaces, :rid
|
35
35
|
attr_accessor :messenger
|
36
36
|
|
37
37
|
|
@@ -40,46 +40,18 @@ module Webmoney
|
|
40
40
|
'https://w3s.wmtransfer.com/asp/'
|
41
41
|
end
|
42
42
|
|
43
|
-
# Presets for interfaces
|
44
|
-
def interface_urls
|
45
|
-
{
|
46
|
-
:create_invoice => w3s_url + 'XMLInvoice.asp', # x1
|
47
|
-
:create_transaction => w3s_url + 'XMLTrans.asp', # x2
|
48
|
-
:operation_history => w3s_url + 'XMLOperations.asp', # x3
|
49
|
-
:outgoing_invoices => w3s_url + 'XMLOutInvoices.asp', # x4
|
50
|
-
:finish_protect => w3s_url + 'XMLFinishProtect.asp', # x5
|
51
|
-
:send_message => w3s_url + 'XMLSendMsg.asp', # x6
|
52
|
-
:check_sign => w3s_url + 'XMLClassicAuth.asp', # x7
|
53
|
-
:find_wm => w3s_url + 'XMLFindWMPurse.asp', # x8
|
54
|
-
:balance => w3s_url + 'XMLPurses.asp', # x9
|
55
|
-
:incoming_invoices => w3s_url + 'XMLInInvoices.asp', # x10
|
56
|
-
:get_passport => 'https://passport.webmoney.ru/asp/XMLGetWMPassport.asp', # x11
|
57
|
-
:reject_protection => w3s_url + 'XMLRejectProtect.asp', # x13
|
58
|
-
:transaction_moneyback => w3s_url + 'XMLTransMoneyback.asp', # x14
|
59
|
-
:i_trust => w3s_url + 'XMLTrustList.asp', # x15
|
60
|
-
:trust_me => w3s_url + 'XMLTrustList2.asp', # x15
|
61
|
-
:trust_save => w3s_url + 'XMLTrustSave2.asp', # x15
|
62
|
-
:create_purse => w3s_url + 'XMLCreatePurse.asp', # x16
|
63
|
-
:create_contract => 'https://arbitrage.webmoney.ru/xml/X17_CreateContract.aspx', # x17
|
64
|
-
:transaction_get => 'https://merchant.webmoney.ru/conf/xml/XMLTransGet.asp', # x18
|
65
|
-
:bussines_level => 'https://stats.wmtransfer.com/levels/XMLWMIDLevel.aspx'
|
66
|
-
}
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
43
|
# Required options:
|
71
44
|
#
|
72
45
|
# - :wmid - WMID
|
46
|
+
#
|
47
|
+
# Optional:
|
48
|
+
#
|
73
49
|
# - :password - on Classic key or Light X509 certificate & key
|
74
50
|
# - :key - Base64 string for Classic key
|
75
|
-
#
|
76
51
|
# OR
|
77
|
-
# #TODO
|
78
52
|
# - :key - OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object
|
79
53
|
# - :cert - OpenSSL::X509::Certificate object
|
80
54
|
#
|
81
|
-
# Optional:
|
82
|
-
#
|
83
55
|
# - :ca_cert - file CA certificate or path to directory with certs (in PEM format)
|
84
56
|
|
85
57
|
def initialize(opt = {})
|
@@ -108,6 +80,8 @@ module Webmoney
|
|
108
80
|
opt[:ca_cert]
|
109
81
|
end
|
110
82
|
|
83
|
+
@rid = opt[:rid]
|
84
|
+
|
111
85
|
# Iconv.new(to, from)
|
112
86
|
@ic_in = Iconv.new('UTF-8', 'CP1251')
|
113
87
|
@ic_out = Iconv.new('CP1251', 'UTF-8')
|
data/spec/spec_helper.rb
CHANGED
@@ -1,24 +1,6 @@
|
|
1
1
|
#encoding: utf-8
|
2
2
|
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# ca_cert:
|
6
|
-
#
|
7
|
-
# first:
|
8
|
-
# wmtype: classic
|
9
|
-
# wmid:
|
10
|
-
# password:
|
11
|
-
# key:
|
12
|
-
# wmz:
|
13
|
-
#
|
14
|
-
# second:
|
15
|
-
# wmtype: light
|
16
|
-
# wmid:
|
17
|
-
# password:
|
18
|
-
# cert: webmoney.cert
|
19
|
-
# key: webmoney.key
|
20
|
-
# wmz:
|
21
|
-
#
|
3
|
+
# Please, see RUNNING_TESTS
|
22
4
|
|
23
5
|
require 'rubygems'
|
24
6
|
require 'test/unit'
|
@@ -53,18 +35,30 @@ end
|
|
53
35
|
def getwm(config)
|
54
36
|
if config.wmtype == "light"
|
55
37
|
# light
|
56
|
-
cert = OpenSSL::X509::Certificate.new(
|
57
|
-
|
38
|
+
cert = OpenSSL::X509::Certificate.new(
|
39
|
+
begin
|
40
|
+
File.read(config.cert)
|
41
|
+
rescue
|
42
|
+
File.read("#{ENV['HOME']}/.wm/#{config.cert}")
|
43
|
+
end)
|
44
|
+
key = OpenSSL::PKey::RSA.new(
|
45
|
+
begin
|
46
|
+
File.read(config.key)
|
47
|
+
rescue
|
48
|
+
File.read("#{ENV['HOME']}/.wm/#{config.key}")
|
49
|
+
end, config.password)
|
58
50
|
TestWM.new :wmid => config.wmid,
|
59
51
|
:key => key,
|
60
52
|
:cert => cert,
|
61
|
-
:ca_cert => WmConfig.ca_cert
|
53
|
+
:ca_cert => WmConfig.ca_cert,
|
54
|
+
:rid => config.rid
|
62
55
|
else
|
63
56
|
# classic
|
64
57
|
TestWM.new :wmid => config.wmid,
|
65
58
|
:password => config.password,
|
66
59
|
:key => config.key,
|
67
|
-
:ca_cert => config.ca_cert
|
60
|
+
:ca_cert => config.ca_cert,
|
61
|
+
:rid => config.rid
|
68
62
|
end
|
69
63
|
end
|
70
64
|
|
data/spec/unit/webmoney_spec.rb
CHANGED
@@ -134,19 +134,6 @@ describe Webmoney, "class" do
|
|
134
134
|
((result[:date] + 60) > Time.now).should be_true
|
135
135
|
end
|
136
136
|
|
137
|
-
it "should create invoice" do
|
138
|
-
# TODO
|
139
|
-
#@wm.request(
|
140
|
-
# :create_invoice,
|
141
|
-
# :orderid => 3,
|
142
|
-
# :amount => 10.0,
|
143
|
-
# :customerwmid => "TEST_WMID",
|
144
|
-
# :storepurse => "Z161888783954",
|
145
|
-
# :desc => "Test invoice",
|
146
|
-
# :address => "Address"
|
147
|
-
#)
|
148
|
-
end
|
149
|
-
|
150
137
|
it "should return operation history" do
|
151
138
|
# TODO
|
152
139
|
#@mywm.request(:operation_history,
|
@@ -206,4 +193,33 @@ describe Webmoney, "class" do
|
|
206
193
|
end
|
207
194
|
end
|
208
195
|
|
196
|
+
describe "login interface" do
|
197
|
+
|
198
|
+
before(:each) do
|
199
|
+
@ca = contragent()
|
200
|
+
end
|
201
|
+
|
202
|
+
it "return InvalidArgument" do
|
203
|
+
lambda { @ca.request(:login,
|
204
|
+
:WmLogin_WMID => @ca.wmid,
|
205
|
+
:WmLogin_UrlID => 'invalid_rid')
|
206
|
+
}.should raise_error(Webmoney::ResultError, "1 InvalidArgument")
|
207
|
+
@ca.error.should == 1
|
208
|
+
@ca.errormsg.should == 'InvalidArgument'
|
209
|
+
end
|
210
|
+
|
211
|
+
it "return InvalidTicket" do
|
212
|
+
lambda { @ca.request(:login,
|
213
|
+
:WmLogin_WMID => @ca.wmid,
|
214
|
+
:WmLogin_UrlID => @ca.rid,
|
215
|
+
:WmLogin_Ticket => 'XVWuooAEOJ0gG5NyDXJ0Zu0GffroqkG7APNKFmCAzA7XNVSx',
|
216
|
+
:WmLogin_AuthType => 'KeeperLight',
|
217
|
+
:remote_ip => '127.0.0.1'
|
218
|
+
)
|
219
|
+
}.should raise_error(Webmoney::ResultError)
|
220
|
+
@ca.error.should == 2
|
221
|
+
@ca.errormsg.should == 'FalseTicket'
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
209
225
|
end
|
data/webmoney.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{webmoney}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.10"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Alexander Oryol"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-10-06}
|
13
13
|
s.email = %q{eagle.alex@gmail.com}
|
14
14
|
s.extensions = ["ext/wmsigner/extconf.rb"]
|
15
15
|
s.extra_rdoc_files = [
|
@@ -44,6 +44,7 @@ Gem::Specification.new do |s|
|
|
44
44
|
"lib/certs/3c58f906.0",
|
45
45
|
"lib/certs/AddTrust_External_Root.crt",
|
46
46
|
"lib/certs/WebMoneyCA.crt",
|
47
|
+
"lib/interfaces.rb",
|
47
48
|
"lib/messenger.rb",
|
48
49
|
"lib/passport.rb",
|
49
50
|
"lib/purse.rb",
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webmoney
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 13
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
8
|
+
- 10
|
9
|
+
version: 0.0.10
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Alexander Oryol
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2010-
|
17
|
+
date: 2010-10-06 00:00:00 +04:00
|
19
18
|
default_executable:
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
@@ -26,7 +25,6 @@ dependencies:
|
|
26
25
|
requirements:
|
27
26
|
- - ">="
|
28
27
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 3
|
30
28
|
segments:
|
31
29
|
- 0
|
32
30
|
version: "0"
|
@@ -69,6 +67,7 @@ files:
|
|
69
67
|
- lib/certs/3c58f906.0
|
70
68
|
- lib/certs/AddTrust_External_Root.crt
|
71
69
|
- lib/certs/WebMoneyCA.crt
|
70
|
+
- lib/interfaces.rb
|
72
71
|
- lib/messenger.rb
|
73
72
|
- lib/passport.rb
|
74
73
|
- lib/purse.rb
|
@@ -102,7 +101,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
102
101
|
requirements:
|
103
102
|
- - ">="
|
104
103
|
- !ruby/object:Gem::Version
|
105
|
-
hash: 3
|
106
104
|
segments:
|
107
105
|
- 0
|
108
106
|
version: "0"
|
@@ -111,7 +109,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
109
|
requirements:
|
112
110
|
- - ">="
|
113
111
|
- !ruby/object:Gem::Version
|
114
|
-
hash: 3
|
115
112
|
segments:
|
116
113
|
- 0
|
117
114
|
version: "0"
|