life-api 0.1.5
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.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +207 -0
- data/Rakefile +1 -0
- data/examples/get_balance.rb +44 -0
- data/lib/life-api/methods.rb +114 -0
- data/lib/life-api/version.rb +5 -0
- data/lib/life-api.rb +171 -0
- data/life-api.gemspec +22 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: da009a2372ce299d656a0cdb99331a4c91c75e23
|
4
|
+
data.tar.gz: 4c956cdb158ab68669badb15bba6480ba9e8e824
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a4a8acdc289d333e7f19f2fb7300b7bbe570da378d132a70edc77b1c15d13aa6706b37f6634efbe26600544e903b4ef8d610a26bd87ad1a4447d244e84e39a78
|
7
|
+
data.tar.gz: 70c680fd0ba26ed01ec0cb403c75949dc9c161806d46046dce8dd8d994d25327a2c6c87d2461ec5054212cf1dfc4e50d027adad64263e1a530ea5de051424c7a
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Anton Maminov
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,207 @@
|
|
1
|
+
# Life::API
|
2
|
+
|
3
|
+
A Ruby library for interfacing with life:)'s undocumented/unannounced API.
|
4
|
+
|
5
|
+
[life:)](http://life.com.ua) — GSM operator in Ukraine.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```
|
12
|
+
gem 'life-api'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
```
|
18
|
+
$ bundle
|
19
|
+
```
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
```
|
24
|
+
$ gem install life-api
|
25
|
+
```
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
First of all require the `life-api` library.
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
require 'life-api'
|
33
|
+
```
|
34
|
+
|
35
|
+
### Authentication
|
36
|
+
|
37
|
+
You can authenticate with life:) in two ways: with password or with token.
|
38
|
+
|
39
|
+
Authentication with password to the life:) API is accomplished using a phone number(`msisdn`) starting with a plus sign ("+") and the country code("380"), and SuperPassword(`password`).
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
life = Life::API.new(msisdn: msisdn, password: password)
|
43
|
+
life.sign_in
|
44
|
+
token = life.token
|
45
|
+
sub_id = life.sub_id
|
46
|
+
```
|
47
|
+
|
48
|
+
> To obtain the SuperPassword send an SMS with key word PASSWORD to number 125, or enter life:) menu by dialing `*125#`, choose Manage account and then SuperPassword service or call `*125*779#`.
|
49
|
+
|
50
|
+
or
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
life = Life::API.new
|
54
|
+
life.token = token
|
55
|
+
life.sub_id = sub_id
|
56
|
+
```
|
57
|
+
|
58
|
+
Now you can make requests to the API.
|
59
|
+
|
60
|
+
### API Examples
|
61
|
+
|
62
|
+
Below you can see some the methods for working with life:) data.
|
63
|
+
|
64
|
+
#### Returns advanced information on the current subscriber
|
65
|
+
```
|
66
|
+
life.get_summary_data
|
67
|
+
```
|
68
|
+
|
69
|
+
Sample response
|
70
|
+
|
71
|
+
```
|
72
|
+
{"method"=>"getSummaryData",
|
73
|
+
"responseCode"=>"0",
|
74
|
+
"subscriber"=>
|
75
|
+
{"attribute"=>
|
76
|
+
[{"name"=>"ICCID", "content"=>"89380062300016907xxx"},
|
77
|
+
{"name"=>"PUK", "content"=>"25159xxx"},
|
78
|
+
{"name"=>"PUK2", "content"=>"00036xxx"},
|
79
|
+
{"name"=>"PIN2", "content"=>"55xx"},
|
80
|
+
{"name"=>"IMSI", "content"=>"25506109310xxxx"},
|
81
|
+
{"name"=>"PIN", "content"=>"70xx"},
|
82
|
+
{"name"=>"LINE_STATE", "content"=>"ACT/STD"},
|
83
|
+
{"name"=>"USE_COMMON_MAIN", "content"=>"false"},
|
84
|
+
{"name"=>"LINE_ACTIVATION_DATE",
|
85
|
+
"content"=>"2010-03-02T11:28:07.392+02:00"},
|
86
|
+
{"name"=>"LANGUAGE_ID", "content"=>"uk_tr"},
|
87
|
+
{"name"=>"DEVICE_NAME", "content"=>"HTC Sensation (PG58130)"},
|
88
|
+
{"name"=>"LINE_SUSPEND_DATE", "content"=>"2014-03-21T00:00:00+02:00"}],
|
89
|
+
"balance"=>
|
90
|
+
[{"code"=>"Line_Main", "amount"=>"12.83"},
|
91
|
+
{"code"=>"Line_Bonus", "amount"=>"0.00"},
|
92
|
+
{"code"=>"Line_Debt", "amount"=>"0.00"}],
|
93
|
+
"bundleFreeMigration"=>{"amount"=>"0"},
|
94
|
+
"tariff"=>{"code"=>"IND_PRE_YOUTH", "name"=>"Crazy day"}}}
|
95
|
+
```
|
96
|
+
|
97
|
+
#### Returns the balance of the current subscriber
|
98
|
+
|
99
|
+
```
|
100
|
+
life.get_balances
|
101
|
+
```
|
102
|
+
|
103
|
+
Sample response
|
104
|
+
|
105
|
+
```
|
106
|
+
{"method"=>"getBalances",
|
107
|
+
"responseCode"=>"0",
|
108
|
+
"balance"=>
|
109
|
+
[{"code"=>"Bundle_Gprs_Internet",
|
110
|
+
"amount"=>"0.00",
|
111
|
+
"measure"=>"Bytes",
|
112
|
+
"name"=>"Free Internet"},
|
113
|
+
{"code"=>"Bundle_Gprs_Wap",
|
114
|
+
"amount"=>"0.00",
|
115
|
+
"measure"=>"Bytes",
|
116
|
+
"name"=>"Free Internet [WAP]"},
|
117
|
+
{"code"=>"Bundle_Gprs_Internet_Youth",
|
118
|
+
"amount"=>"32624640.00",
|
119
|
+
"measure"=>"Bytes",
|
120
|
+
"name"=>"Internet [Crazy Day]"},
|
121
|
+
{"code"=>"Bundle_Usage_Internet_Weekly",
|
122
|
+
"amount"=>"0.00",
|
123
|
+
"measure"=>"Bytes",
|
124
|
+
"name"=>"Used Internet [Week]"},
|
125
|
+
{"code"=>"Bundle_Mms_Ukraine",
|
126
|
+
"amount"=>"0.00",
|
127
|
+
"measure"=>"MMS",
|
128
|
+
"name"=>"Free MMS [in Ukraine]"},
|
129
|
+
{"code"=>"Bundle_Sms_Ukraine",
|
130
|
+
"amount"=>"40.00",
|
131
|
+
"measure"=>"SMS",
|
132
|
+
"name"=>"Free SMS [in Ukraine]"},
|
133
|
+
{"code"=>"Bundle_Youth_Voice_Omo_Pstn",
|
134
|
+
"amount"=>"2160.00",
|
135
|
+
"measure"=>"Seconds",
|
136
|
+
"name"=>"100 min «life:) Сrazy day maximum» [other mob operators]"},
|
137
|
+
{"code"=>"Bundle_UsageN_FF_FREE",
|
138
|
+
"amount"=>"0.00",
|
139
|
+
"measure"=>"Seconds",
|
140
|
+
"name"=>"Free minutes [Family Numbers]"},
|
141
|
+
{"code"=>"Bundle_UsageN_Onnet_Region",
|
142
|
+
"amount"=>"0.00",
|
143
|
+
"measure"=>"Seconds",
|
144
|
+
"name"=>"Free minutes [Free life:) Donbas]"},
|
145
|
+
{"code"=>"Bundle_Voice_Onnet",
|
146
|
+
"amount"=>"24000.00",
|
147
|
+
"measure"=>"Seconds",
|
148
|
+
"name"=>"Free minutes [life:) network]"},
|
149
|
+
{"code"=>"Bundle_Voice_Offnet",
|
150
|
+
"amount"=>"0.00",
|
151
|
+
"measure"=>"Seconds",
|
152
|
+
"name"=>
|
153
|
+
"Free minutes [other mobile operators and fixed numbers of Ukraine]"},
|
154
|
+
{"code"=>"Line_Bonus",
|
155
|
+
"amount"=>"0.00",
|
156
|
+
"measure"=>"UAH",
|
157
|
+
"name"=>"Line Bonus"},
|
158
|
+
{"code"=>"Line_Main",
|
159
|
+
"amount"=>"12.83",
|
160
|
+
"measure"=>"UAH",
|
161
|
+
"name"=>"Line Main"}]}
|
162
|
+
```
|
163
|
+
|
164
|
+
#### Returns payments history for calendar month in format 'YYYY-mm'
|
165
|
+
|
166
|
+
```
|
167
|
+
life.get_payments_history('2013-03')
|
168
|
+
```
|
169
|
+
|
170
|
+
Sample response
|
171
|
+
|
172
|
+
```
|
173
|
+
{"method"=>"getPaymentsHistory",
|
174
|
+
"responseCode"=>"0",
|
175
|
+
"payments"=>
|
176
|
+
{"sum"=>"50.00",
|
177
|
+
"payment"=>
|
178
|
+
[{"date"=>"2013-03-21",
|
179
|
+
"time"=>"10:40:12",
|
180
|
+
"type"=>"Payment via WEB",
|
181
|
+
"sum"=>"10.00"},
|
182
|
+
{"date"=>"2013-03-21",
|
183
|
+
"time"=>"13:25:28",
|
184
|
+
"type"=>"Payment via WEB",
|
185
|
+
"sum"=>"40.00"}]}}
|
186
|
+
```
|
187
|
+
|
188
|
+
## Supported Rubies
|
189
|
+
|
190
|
+
Tested with the following Ruby versions:
|
191
|
+
|
192
|
+
* MRI 1.9.3
|
193
|
+
* MRI 2.0.0
|
194
|
+
|
195
|
+
## Contributing
|
196
|
+
|
197
|
+
1. Fork it
|
198
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
199
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
200
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
201
|
+
5. Create new Pull Request
|
202
|
+
|
203
|
+
## License and Author
|
204
|
+
|
205
|
+
Copyright (c) 2013-2015 by Anton Maminov
|
206
|
+
|
207
|
+
This library is distributed under the MIT license. Please see the LICENSE file.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup :default
|
5
|
+
|
6
|
+
require 'logger'
|
7
|
+
require 'life-api'
|
8
|
+
|
9
|
+
puts Life::API::VERSION
|
10
|
+
|
11
|
+
msisdn = '+38xxxxxxxxx'
|
12
|
+
password = ''
|
13
|
+
|
14
|
+
life = Life::API.new(msisdn: msisdn, password: password, lang: 'en')
|
15
|
+
life.log = Logger.new($stderr)
|
16
|
+
life.sign_in
|
17
|
+
|
18
|
+
summary_data = life.get_summary_data
|
19
|
+
|
20
|
+
tariff = summary_data['subscriber']['tariff']['name']
|
21
|
+
puts "Tariff: #{tariff}"
|
22
|
+
|
23
|
+
line_suspend_date = summary_data['subscriber']['attribute'].select{ |f| f['name'] == "LINE_SUSPEND_DATE" }.first['content']
|
24
|
+
line_suspend_date = Time.mktime(line_suspend_date).strftime("%d.%m.%Y")
|
25
|
+
puts "Suspend date: #{line_suspend_date}"
|
26
|
+
|
27
|
+
puts
|
28
|
+
|
29
|
+
balance = summary_data['subscriber']['balance']
|
30
|
+
main = balance.select{ |f| f['code'] == 'Line_Main' }.first['amount']
|
31
|
+
bonus = balance.select{ |f| f['code'] == 'Line_Bonus' }.first['amount']
|
32
|
+
debt = balance.select{ |f| f['code'] == 'Line_Debt' }.first['amount']
|
33
|
+
puts "Main: #{main} ₴"
|
34
|
+
puts "Bonus: #{bonus} ₴"
|
35
|
+
puts "Dept: #{debt} ₴"
|
36
|
+
|
37
|
+
|
38
|
+
puts "\nBalances:"
|
39
|
+
balances = life.get_balances
|
40
|
+
balances['balance'].keep_if{ |i| i['amount'].to_i != 0 }.each do |i|
|
41
|
+
puts " * #{i['name']}: #{i['amount']} #{i['measure']}"
|
42
|
+
end
|
43
|
+
|
44
|
+
life.sign_out
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# The list of available API method names:
|
4
|
+
# (16/22)
|
5
|
+
#
|
6
|
+
# [-] activateDeactivateService
|
7
|
+
# [+] callMeBack
|
8
|
+
# [+] changeLanguage
|
9
|
+
# [+] changeSuperPassword
|
10
|
+
# [-] changeTariff
|
11
|
+
# [+] getAvailableTariffs
|
12
|
+
# [+] getBalances
|
13
|
+
# [+] getExpensesSummary
|
14
|
+
# [+] getLanguages
|
15
|
+
# [+] getPaymentsHistory
|
16
|
+
# [-] getSeparateBalances
|
17
|
+
# [+] getServices
|
18
|
+
# [+] getSummaryData
|
19
|
+
# [+] getToken
|
20
|
+
# [+] getUIProperties
|
21
|
+
# [-] offerAction
|
22
|
+
# [+] refillBalanceByScratchCard
|
23
|
+
# [-] removeFromPreProcessing
|
24
|
+
# [+] requestBalanceTransfer
|
25
|
+
# [+] signIn
|
26
|
+
# [+] signOut
|
27
|
+
# [-] transferBalance
|
28
|
+
|
29
|
+
module Life
|
30
|
+
class API
|
31
|
+
def sign_in
|
32
|
+
xml = request('signIn', { msisdn: @msisdn, superPassword: @password })
|
33
|
+
@token = xml['token']
|
34
|
+
@sub_id = xml['subId']
|
35
|
+
return xml
|
36
|
+
end
|
37
|
+
|
38
|
+
def sign_out
|
39
|
+
request('signOut', { msisdn: @msisdn, subId: @sub_id })
|
40
|
+
end
|
41
|
+
|
42
|
+
def change_super_password(old_password, new_password)
|
43
|
+
request('changeSuperPassword', base_api_parameters.merge({ oldPassword: old_password, newPassword: new_password }))
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_token
|
47
|
+
request('getToken', { msisdn: @msisdn, subId: @sub_id })
|
48
|
+
end
|
49
|
+
|
50
|
+
# +last_date_update+ is DateTime object
|
51
|
+
#
|
52
|
+
def get_ui_properties(language_id, last_date_update)
|
53
|
+
request('getUIProperties', {
|
54
|
+
accessKeyCode: @access_key_code,
|
55
|
+
languageId: language_id,
|
56
|
+
osType: @os_type,
|
57
|
+
lastDateUpdate: last_date_update,
|
58
|
+
})
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_summary_data
|
62
|
+
request('getSummaryData', base_api_parameters)
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_services
|
66
|
+
request('getServices', base_api_parameters)
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_available_tariffs
|
70
|
+
request('getAvailableTariffs', base_api_parameters)
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_balances
|
74
|
+
request('getBalances', base_api_parameters)
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_languages
|
78
|
+
request('getLanguages', base_api_parameters)
|
79
|
+
end
|
80
|
+
|
81
|
+
def change_language(new_language_id)
|
82
|
+
request('changeLanguage', base_api_parameters.merge({ newLanguageId: new_language_id}))
|
83
|
+
end
|
84
|
+
|
85
|
+
def call_me_back(msisdn_b)
|
86
|
+
request('callMeBack', base_api_parameters.merge({ msisdnB: msisdn_b }))
|
87
|
+
end
|
88
|
+
|
89
|
+
def request_balance_transfer(msisdn_b)
|
90
|
+
request('requestBalanceTransfer', base_api_parameters.merge({ msisdnB: msisdn_b }))
|
91
|
+
end
|
92
|
+
|
93
|
+
# Payments history for calendar month +month_period+
|
94
|
+
#
|
95
|
+
# +month_period+ - A string like 'yyyy-MM' that represent month of year
|
96
|
+
#
|
97
|
+
def get_payments_history(month_period)
|
98
|
+
request('getPaymentsHistory', base_api_parameters.merge({ monthPeriod: month_period }))
|
99
|
+
end
|
100
|
+
|
101
|
+
# Summary expenses report for calendar month +month_period+
|
102
|
+
#
|
103
|
+
# +month_period+ - A string like 'yyyy-MM' that represent month of year
|
104
|
+
#
|
105
|
+
def get_expenses_summary(month_period)
|
106
|
+
request('getExpensesSummary', base_api_parameters.merge({ monthPeriod: month_period }))
|
107
|
+
end
|
108
|
+
|
109
|
+
def refill_balance_by_scratch_card(secret_code)
|
110
|
+
request('refillBalanceByScratchCard', base_api_parameters.merge({ secretCode: secret_code}))
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
data/lib/life-api.rb
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'cgi'
|
5
|
+
require 'net/https'
|
6
|
+
require 'openssl'
|
7
|
+
require 'base64'
|
8
|
+
|
9
|
+
require 'xmlsimple'
|
10
|
+
|
11
|
+
require "life-api/methods"
|
12
|
+
require "life-api/version"
|
13
|
+
|
14
|
+
# The Life::API library is used for interactions with a api.life.com.ua website.
|
15
|
+
# life:) — GSM operator in Ukraine
|
16
|
+
#
|
17
|
+
# == Example
|
18
|
+
#
|
19
|
+
# require 'life-api'
|
20
|
+
# require 'logger'
|
21
|
+
#
|
22
|
+
# life = Life::API.new(msisdn: msisdn, password: password, lang: 'uk')
|
23
|
+
# life.log = Logger.new($stderr)
|
24
|
+
# life.sign_in
|
25
|
+
# life.get_summary_data
|
26
|
+
# life.sign_out
|
27
|
+
#
|
28
|
+
module Life
|
29
|
+
|
30
|
+
class MethodError < ArgumentError; end
|
31
|
+
|
32
|
+
RESPONSE_CODES = {
|
33
|
+
'0' => 'SUCCESSFULY_PERFORMED',
|
34
|
+
'-1' => 'METHOD_INVOCATION_TIMEOUT',
|
35
|
+
'-2' => 'INTERNAL_ERROR',
|
36
|
+
'-3' => 'INVALID_PARAMETERS_LIST',
|
37
|
+
'-4' => 'VENDOR_AUTHORIZATION_FAILED',
|
38
|
+
'-5' => 'VENDOR_ACCESS_KEY_EXPIRED',
|
39
|
+
'-6' => 'VENDOR_AUTHENTICATION_FAILED',
|
40
|
+
'-7' => 'SUPERPASS_CHECKING_FAILED',
|
41
|
+
'-8' => 'INCORRECT_SUBSCRIBER_ID',
|
42
|
+
'-9' => 'INCORRECT_SUBSRIBER_STATE',
|
43
|
+
'-10' => 'SUPERPASS_BLOCKED',
|
44
|
+
'-11' => 'SUBSCRIBER_ID_NOT_FOUND',
|
45
|
+
'-12' => 'TOKEN_EXPIRED',
|
46
|
+
'-13' => 'CHANGE_TARIFF_FAILED',
|
47
|
+
'-14' => 'SERVICE_ACTIVATION_FAILED',
|
48
|
+
'-15' => 'OFFER_ACTIVATION_FAILED',
|
49
|
+
'-16' => 'GET_TARIFFS_FAILED',
|
50
|
+
'-17' => 'GET_SERVICES_FAILED',
|
51
|
+
'-18' => 'REMOVE_SERVICE_FROM_PREPROCESSING_FAILED',
|
52
|
+
'-19' => 'LOGIC_IS_BLOCKING',
|
53
|
+
'-20' => 'TOO_MANY_REQUESTS',
|
54
|
+
'-40' => 'PAYMENTS_OR_EXPENSES_MISSED',
|
55
|
+
'-21474833648' => 'INTERNAL_APPLICATION_ERROR',
|
56
|
+
}
|
57
|
+
|
58
|
+
class API
|
59
|
+
attr_accessor :token, :sub_id
|
60
|
+
|
61
|
+
class << self
|
62
|
+
# Default logger for all Life::API instances
|
63
|
+
#
|
64
|
+
# Life::API.log = Logger.new($stderr)
|
65
|
+
#
|
66
|
+
attr_accessor :log
|
67
|
+
end
|
68
|
+
|
69
|
+
# Create a new API object using the given parameters.
|
70
|
+
#
|
71
|
+
# == Required parameters
|
72
|
+
#
|
73
|
+
# * +:msisdn+ - telephone number in format '38063*******'
|
74
|
+
# * +:password+ - life:) super password
|
75
|
+
# * +:lang+ - 'uk', 'ru' or 'en'
|
76
|
+
#
|
77
|
+
def initialize(params = {})
|
78
|
+
@msisdn = params.delete(:msisdn)
|
79
|
+
@password = params.delete(:password)
|
80
|
+
@lang = params.delete(:lang) || 'uk'
|
81
|
+
|
82
|
+
@log = nil
|
83
|
+
|
84
|
+
@os_type = 'ANDROID'
|
85
|
+
|
86
|
+
@api_url = 'https://api.life.com.ua/mobile/'
|
87
|
+
@access_key_code = '7'
|
88
|
+
@application_key = 'E6j_$4UnR_)0b'
|
89
|
+
end
|
90
|
+
|
91
|
+
# The current logger. If no logger has been set Life::API.log is used.
|
92
|
+
#
|
93
|
+
def log
|
94
|
+
@log || Life::API.log
|
95
|
+
end
|
96
|
+
|
97
|
+
# Sets the +logger+ used by this instance of Life::API
|
98
|
+
#
|
99
|
+
def log= logger
|
100
|
+
@log = logger
|
101
|
+
end
|
102
|
+
|
103
|
+
def request(method, params = {})
|
104
|
+
params = { accessKeyCode: @access_key_code }.merge(params)
|
105
|
+
url = create_signed_url(method, params)
|
106
|
+
|
107
|
+
log.debug("[#{method}] request: #{url}") if log
|
108
|
+
|
109
|
+
uri = URI(url)
|
110
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
111
|
+
|
112
|
+
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
|
113
|
+
|
114
|
+
log.debug("[#{method}] response: #{response.body}") if log
|
115
|
+
|
116
|
+
xml = parse_xml(response.body)
|
117
|
+
|
118
|
+
if xml['responseCode']
|
119
|
+
if xml['responseCode'] == '0'
|
120
|
+
return xml
|
121
|
+
else
|
122
|
+
error_message = Life::RESPONSE_CODES[xml['responseCode']]
|
123
|
+
error_message ||= "Unknown error code #{xml['responseCode']}"
|
124
|
+
raise MethodError, error_message
|
125
|
+
end
|
126
|
+
else
|
127
|
+
raise MethodError, "Unknown error: #{xml}"
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def create_signed_url(method, params)
|
135
|
+
query = create_param(params)
|
136
|
+
str = method + '?' + query + '&signature='
|
137
|
+
|
138
|
+
digest = OpenSSL::Digest.new('sha1')
|
139
|
+
hash = OpenSSL::HMAC.digest(digest, @application_key, str)
|
140
|
+
|
141
|
+
hash = Base64.encode64(hash).chomp
|
142
|
+
|
143
|
+
str += urlencode(hash)
|
144
|
+
|
145
|
+
return @api_url + str
|
146
|
+
end
|
147
|
+
|
148
|
+
# Returns a string representation of the receiver suitable for use as a URL query string
|
149
|
+
#
|
150
|
+
def create_param(params)
|
151
|
+
params.map do |key, value|
|
152
|
+
"#{urlencode(key)}=#{urlencode(value)}"
|
153
|
+
end.sort * '&'
|
154
|
+
end
|
155
|
+
|
156
|
+
# URL-encode a string
|
157
|
+
#
|
158
|
+
def urlencode(str)
|
159
|
+
return CGI.escape(str.to_s)
|
160
|
+
end
|
161
|
+
|
162
|
+
def parse_xml(str)
|
163
|
+
return XmlSimple.xml_in(str, { 'ForceArray' => false })
|
164
|
+
end
|
165
|
+
|
166
|
+
def base_api_parameters
|
167
|
+
return { msisdn: @msisdn, languageId: @lang, osType: @os_type, token: @token }
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
end
|
data/life-api.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'life-api/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "life-api"
|
8
|
+
gem.version = Life::API::VERSION
|
9
|
+
gem.authors = ["Anton Maminov"]
|
10
|
+
gem.email = ["anton.linux@gmail.com"]
|
11
|
+
gem.description = %q{A Ruby interface to the life:) API}
|
12
|
+
gem.summary = %q{The Life::API library is used for interactions with a api.life.com.ua website}
|
13
|
+
gem.homepage = "https://github.com/mamantoha/life-api"
|
14
|
+
gem.license = "MIT"
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
gem.add_runtime_dependency('xml-simple', '~> 1.1.2')
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: life-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anton Maminov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: xml-simple
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.1.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.1.2
|
27
|
+
description: A Ruby interface to the life:) API
|
28
|
+
email:
|
29
|
+
- anton.linux@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- Gemfile
|
35
|
+
- LICENSE
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- examples/get_balance.rb
|
39
|
+
- lib/life-api.rb
|
40
|
+
- lib/life-api/methods.rb
|
41
|
+
- lib/life-api/version.rb
|
42
|
+
- life-api.gemspec
|
43
|
+
homepage: https://github.com/mamantoha/life-api
|
44
|
+
licenses:
|
45
|
+
- MIT
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.4.7
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: The Life::API library is used for interactions with a api.life.com.ua website
|
67
|
+
test_files: []
|