nextcaller_client 0.0.2 → 0.0.3

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.
@@ -1,11 +1,12 @@
1
1
  module NextcallerClient
2
2
  #The NextCaller API client
3
- class Client
3
+ class NextCallerClient
4
4
 
5
5
  attr_accessor :auth
6
6
 
7
- def initialize(api_key, api_secret)
8
- auth = {username: api_key, password: api_secret}
7
+ def initialize(username, password, sandbox=false)
8
+ auth = {username: username, password: password}
9
+ @sandbox = sandbox
9
10
  @transport = Transport.new(auth, DEFAULT_USER_AGENT)
10
11
  end
11
12
 
@@ -15,67 +16,203 @@ module NextcallerClient
15
16
  # debug -- boolean (default false)
16
17
  #
17
18
  def get_by_phone(phone, debug=false)
18
-
19
- method = 'GET'
20
19
  Utils.validate_phone(phone)
21
20
  url_params = {
22
- phone: phone,
23
- format: JSON_RESPONSE_FORMAT
21
+ phone: phone,
22
+ format: JSON_RESPONSE_FORMAT
24
23
  }
25
- url = Utils.prepare_url('records', url_params)
26
- response = @transport.make_http_request(url, method, debug)
27
-
28
- if block_given?
29
- yield response
30
- else
31
- JSON.parse(response.body)
32
- end
24
+ url = Utils.prepare_url('records/', @sandbox, url_params)
25
+ response = @transport.make_http_request(url, 'GET', debug)
26
+
27
+ block_given? ? yield(response) : JSON.parse(response.body)
33
28
  end
34
29
 
35
30
  # Get profile by id
36
31
  # arguments:
37
- # profile_id -- Profile identifier, required
32
+ # profile_id -- Profile identifier, required, length is 30
38
33
  # debug -- boolean (default false)
39
34
  #
40
35
  def get_by_profile_id(profile_id, debug=false)
41
-
42
- method = 'GET'
36
+ Utils.validate_profile_id(profile_id)
43
37
  url_params = {
44
- format: JSON_RESPONSE_FORMAT
38
+ format: JSON_RESPONSE_FORMAT
45
39
  }
46
- url = Utils.prepare_url('users/%s/' % profile_id, url_params)
47
- response = @transport.make_http_request(url, method, debug)
48
-
49
- if block_given?
50
- yield response
51
- else
52
- JSON.parse(response.body)
53
- end
40
+ url = Utils.prepare_url('users/%s/' % profile_id, @sandbox, url_params)
41
+ response = @transport.make_http_request(url, 'GET', debug)
42
+
43
+ block_given? ? yield(response) : JSON.parse(response.body)
54
44
  end
55
45
 
56
46
  # Update profile by id
57
47
  # arguments:
58
- # profile_id -- Profile identifier, required
48
+ # profile_id -- Profile identifier, required, length is 30
59
49
  # data -- dictionary with changed data, required
60
50
  # debug -- boolean (default false)
61
51
  #
62
52
  def update_by_profile_id(profile_id, data, debug=false)
53
+ Utils.validate_profile_id(profile_id)
54
+ url_params = {
55
+ format: JSON_RESPONSE_FORMAT
56
+ }
57
+ url = Utils.prepare_url('users/%s/' % profile_id, @sandbox, url_params)
58
+ data = Utils.prepare_json_data(data)
59
+ response = @transport.make_http_request(url, 'POST', debug, data)
63
60
 
64
- method = 'POST'
61
+ block_given? ? yield(response) : response
62
+ end
63
+
64
+ # Get fraud level for phone
65
+ # arguments:
66
+ # phone -- 10 digits phone, str ot int, required
67
+ # debug -- boolean (default false)
68
+ #
69
+ def get_fraud_level(phone, debug=false)
70
+ Utils.validate_phone(phone)
65
71
  url_params = {
66
- format: JSON_RESPONSE_FORMAT
72
+ phone: phone,
73
+ format: JSON_RESPONSE_FORMAT
67
74
  }
68
- url = Utils.prepare_url('users/%s/' % profile_id, url_params)
75
+ url = Utils.prepare_url('fraud/', @sandbox, url_params)
76
+ response = @transport.make_http_request(url, 'GET', debug)
77
+
78
+ block_given? ? yield(response) : JSON.parse(response.body)
79
+ end
80
+
81
+ end
82
+
83
+
84
+ #The NextCaller platform API client
85
+ class NextCallerPlatformClient < NextCallerClient
86
+
87
+ # Get profiles by phone
88
+ # arguments:
89
+ # phone -- 10 digits phone, str ot int, required
90
+ # platform_username -- platform username, str.
91
+ # debug -- boolean (default false)
92
+ #
93
+ def get_by_phone(phone, platform_username, debug=false)
94
+ Utils.validate_phone(phone)
95
+ Utils.validate_platform_username(platform_username)
96
+ url_params = {
97
+ phone: phone,
98
+ platform_username: platform_username,
99
+ format: JSON_RESPONSE_FORMAT
100
+ }
101
+ url = Utils.prepare_url('records/', @sandbox, url_params)
102
+ response = @transport.make_http_request(url, 'GET', debug)
103
+
104
+ block_given? ? yield(response) : JSON.parse(response.body)
105
+ end
106
+
107
+ # Get profiles by phone
108
+ # arguments:
109
+ # profile_id -- Profile identifier, required, length is 30
110
+ # platform_username -- platform username, str.
111
+ # debug -- boolean (default false)
112
+ #
113
+ def get_by_profile_id(profile_id, platform_username, debug=false)
114
+ Utils.validate_profile_id(profile_id)
115
+ Utils.validate_platform_username(platform_username)
116
+ url_params = {
117
+ platform_username: platform_username,
118
+ format: JSON_RESPONSE_FORMAT
119
+ }
120
+ url = Utils.prepare_url('users/%s/' % profile_id, @sandbox, url_params)
121
+ response = @transport.make_http_request(url, 'GET', debug)
122
+
123
+ block_given? ? yield(response) : JSON.parse(response.body)
124
+ end
125
+
126
+ # Get profiles by phone
127
+ # arguments:
128
+ # profile_id -- Profile identifier, required, length is 30
129
+ # data -- dictionary with changed data, required
130
+ # platform_username -- platform username, str.
131
+ # debug -- boolean (default false)
132
+ #
133
+ def update_by_profile_id(profile_id, platform_username, data, debug=false)
134
+ Utils.validate_profile_id(profile_id)
135
+ Utils.validate_platform_username(platform_username)
136
+ url_params = {
137
+ platform_username: platform_username,
138
+ format: JSON_RESPONSE_FORMAT
139
+ }
140
+ url = Utils.prepare_url('users/%s/' % profile_id, @sandbox, url_params)
69
141
  data = Utils.prepare_json_data(data)
70
- response = @transport.make_http_request(url, method, debug, data)
142
+ response = @transport.make_http_request(url, 'POST', debug, data)
143
+
144
+ block_given? ? yield(response) : response
145
+ end
146
+
147
+ # Get profiles by phone
148
+ # arguments:
149
+ # phone -- 10 digits phone, str ot int, required
150
+ # data -- dictionary with changed data, required
151
+ # platform_username -- platform username, str.
152
+ # debug -- boolean (default false)
153
+ #
154
+ def get_fraud_level(phone, platform_username, debug=false)
155
+ Utils.validate_phone(phone)
156
+ Utils.validate_platform_username(platform_username)
157
+ url_params = {
158
+ platform_username: platform_username,
159
+ phone: phone,
160
+ format: JSON_RESPONSE_FORMAT
161
+ }
162
+ url = Utils.prepare_url('fraud/', @sandbox, url_params)
163
+ response = @transport.make_http_request(url, 'GET', debug)
164
+
165
+ block_given? ? yield(response) : JSON.parse(response.body)
166
+ end
167
+
168
+ # Get platform statistics
169
+ # arguments:
170
+ # debug -- boolean (default false)
171
+ #
172
+ def get_platform_statistics(debug=false)
173
+ url_params = {
174
+ format: JSON_RESPONSE_FORMAT
175
+ }
176
+ url = Utils.prepare_url('platform_users/', @sandbox, url_params)
177
+ response = @transport.make_http_request(url, 'GET', debug)
178
+
179
+ block_given? ? yield(response) : JSON.parse(response.body)
180
+ end
181
+
182
+ # Get platform user
183
+ # arguments:
184
+ # platform_username -- platform username, str.
185
+ # debug -- boolean (default false)
186
+ #
187
+ def get_platform_user(platform_username, debug=false)
188
+ Utils.validate_platform_username(platform_username)
189
+ url_params = {
190
+ format: JSON_RESPONSE_FORMAT
191
+ }
192
+ url = Utils.prepare_url('platform_users/%s/' % platform_username, @sandbox, url_params)
193
+ response = @transport.make_http_request(url, 'GET', debug)
71
194
 
72
- if block_given?
73
- yield response
74
- else
75
- response
76
- end
195
+ block_given? ? yield(response) : JSON.parse(response.body)
77
196
  end
78
197
 
198
+ # Update platform user data
199
+ # arguments:
200
+ # platform_username -- platform username, str.
201
+ # data -- dictionary with changed data, required
202
+ # debug -- boolean (default false)
203
+ #
204
+ def update_platform_user(platform_username, data, debug=false)
205
+ Utils.validate_platform_username(platform_username)
206
+ url_params = {
207
+ format: JSON_RESPONSE_FORMAT
208
+ }
209
+ url = Utils.prepare_url('platform_users/%s/' % platform_username, @sandbox, url_params)
210
+ data = Utils.prepare_json_data(data)
211
+ response = @transport.make_http_request(url, 'POST', debug, data)
212
+
213
+ block_given? ? yield(response) : response
214
+ end
215
+
79
216
  end
80
217
 
81
218
  end
@@ -3,10 +3,12 @@ module NextcallerClient
3
3
  DEFAULT_REQUEST_TIMEOUT = 60
4
4
  JSON_RESPONSE_FORMAT = 'json'
5
5
  DEFAULT_PHONE_LENGTH = 10
6
+ DEFAULT_PROFILE_ID_LENGTH = 30
6
7
  DEFAULT_USER_AGENT = 'nextcaller/ruby/%s' % VERSION
7
8
 
8
9
  # urls
9
10
  BASE_URL = 'api.nextcaller.com/v2/'
10
11
  FULL_URL = 'https://api.nextcaller.com/v2/'
12
+ FULL_SANDBOX_URL = 'https://api.sandbox.nextcaller.com/v2/'
11
13
 
12
14
  end
@@ -34,20 +34,22 @@ module NextcallerClient
34
34
  @log.debug('Request url: %s' % url) if debug
35
35
  @log.debug('Request body: %s' % data.to_s) if debug && method == 'POST'
36
36
 
37
- response = https.start { |http| http.request(request) }
38
- case response
39
- when Net::HTTPSuccess then
40
- response
41
- else
42
- if response.code.to_i.between?(400, 499)
43
- raise HttpException.new(Utils.parse_error_response(response)), '%s Client Error: %s' % [response.code, response.message]
44
- elsif response.code.to_i.between?(500, 599)
45
- raise HttpException.new(Utils.parse_error_response(response)), '%s Server Error: %s' % [response.code, response.message]
46
- end
37
+ begin
38
+ response = https.start { |http| http.request(request) }
39
+ case response
40
+ when Net::HTTPSuccess then response
41
+ else
42
+ if response.code.to_i.between?(400, 499)
43
+ raise HttpException.new(Utils.parse_error_response(response)), '%s Client Error: %s' % [response.code, response.message]
44
+ elsif response.code.to_i.between?(500, 599)
45
+ raise HttpException.new(Utils.parse_error_response(response)), '%s Server Error: %s' % [response.code, response.message]
46
+ end
47
+ end
48
+ rescue Net::ReadTimeout
49
+ raise HttpException.new({}), 'Server Error: read timeout error'
47
50
  end
48
51
  end
49
52
 
50
53
  end
51
54
 
52
- end
53
-
55
+ end
@@ -20,14 +20,30 @@ module NextcallerClient
20
20
  #Validate phone format
21
21
  def self.validate_phone(value, length=DEFAULT_PHONE_LENGTH)
22
22
  value = value.to_s
23
- unless value =~ /^[0-9]{10}$/
24
- raise ArgumentError, 'Invalid phone number: %s. Phone should consists of 10 digits.' % value
23
+ unless value =~ /^[0-9]{#{length}}$/
24
+ raise ArgumentError, 'Invalid phone number: %s. Phone should consists of #{length} digits.' % value
25
+ end
26
+ end
27
+
28
+ #Validate porfile id
29
+ def self.validate_profile_id(value, length=DEFAULT_PROFILE_ID_LENGTH)
30
+ value = value.to_s
31
+ unless value =~ /^[0-9a-zA-Z]{#{length}}$/
32
+ raise ArgumentError, 'Invalid profile id: %s. Profile id should consists of #{length} characters.' % value
33
+ end
34
+ end
35
+
36
+ #Validate platform_username
37
+ def self.validate_platform_username(value)
38
+ value = value.to_s
39
+ if value =~ /\W/
40
+ raise ArgumentError, 'Invalid platform name: %s. Platfrom name should contain only an alphanumeric character, including _.' % value
25
41
  end
26
42
  end
27
43
 
28
44
  #Prepare url from path and params
29
- def self.prepare_url(path, url_params={})
30
- url = '%s%s' % [FULL_URL, path]
45
+ def self.prepare_url(path, sandbox, url_params={})
46
+ url = '%s%s' % [sandbox ? FULL_SANDBOX_URL : FULL_URL, path]
31
47
  unless url.end_with?('/')
32
48
  url += '/'
33
49
  end
@@ -1,3 +1,3 @@
1
1
  module NextcallerClient
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/test/constants.rb ADDED
@@ -0,0 +1,206 @@
1
+ # encoding: utf-8
2
+
3
+ TEST_USERNAME = 'username'
4
+ TEST_PASSWORD = 'password'
5
+
6
+ PHONE_JSON_RESULT_EXAMPLE = '
7
+ {
8
+ "records": [
9
+ {
10
+ "id": "97d949a413f4ea8b85e9586e1f2d9a",
11
+ "first_name": "Jerry",
12
+ "last_name": "Seinfeld",
13
+ "name": "Jerry Seinfeld",
14
+ "language": "English",
15
+ "fraud_threat": "low",
16
+ "spoof": "false",
17
+ "phone": [
18
+ {
19
+ "number": "2125558383"
20
+ }
21
+ ],
22
+ "carrier": "Verizon Wireless",
23
+ "line_type": "LAN",
24
+ "address": [
25
+ {
26
+ "city": "New York",
27
+ "extended_zip": "",
28
+ "country": "USA",
29
+ "line2": "Apt 5a",
30
+ "line1": "129 West 81st Street",
31
+ "state": "NY",
32
+ "zip_code": "10024"
33
+ }
34
+ ],
35
+ "email": "demo@nextcaller.com",
36
+ "age": "45-54",
37
+ "gender": "Male",
38
+ "household_income": "50k-75k",
39
+ "marital_status": "Single",
40
+ "presence_of_children": "No",
41
+ "home_owner_status": "Rent",
42
+ "market_value": "350k-500k",
43
+ "length_of_residence": "12 Years",
44
+ "high_net_worth": "No",
45
+ "occupation": "Entertainer",
46
+ "education": "Completed College",
47
+ "department": "not specified"
48
+ }
49
+ ]
50
+ }'
51
+
52
+ PROFILE_JSON_REQUEST_EXAMPLE =
53
+ {
54
+ first_name: 'Clark',
55
+ last_name: 'Kent',
56
+ shipping_address1:
57
+ {
58
+ line1: '225 Kryptonite Ave.',
59
+ line2: '',
60
+ city: 'Smallville',
61
+ state: 'KS',
62
+ zip_code: '66002'
63
+ }
64
+ }
65
+
66
+ PROFILE_JSON_RESULT_EXAMPLE = '
67
+ {
68
+ "id": "97d949a413f4ea8b85e9586e1f2d9a",
69
+ "first_name": "Jerry",
70
+ "last_name": "Seinfeld",
71
+ "name": "Jerry Seinfeld",
72
+ "language": "English",
73
+ "fraud_threat": "low",
74
+ "spoof": "false",
75
+ "phone": [
76
+ {
77
+ "number": "2125558383"
78
+ }
79
+ ],
80
+ "carrier": "Verizon Wireless",
81
+ "line_type": "LAN",
82
+ "address": [
83
+ {
84
+ "city": "New York",
85
+ "extended_zip": "",
86
+ "country": "USA",
87
+ "line2": "Apt 5a",
88
+ "line1": "129 West 81st Street",
89
+ "state": "NY",
90
+ "zip_code": "10024"
91
+ }
92
+ ],
93
+ "email": "demo@nextcaller.com",
94
+ "age": "45-54",
95
+ "gender": "Male",
96
+ "household_income": "50k-75k",
97
+ "marital_status": "Single",
98
+ "presence_of_children": "No",
99
+ "home_owner_status": "Rent",
100
+ "market_value": "350k-500k",
101
+ "length_of_residence": "12 Years",
102
+ "high_net_worth": "No",
103
+ "occupation": "Entertainer",
104
+ "education": "Completed College",
105
+ "department": "not specified"
106
+ }'
107
+
108
+ FRAUD_LEVEL_JSON_RESULT_EXAMPLE = '
109
+ {
110
+ "spoofed": "false",
111
+ "fraud_risk": "low"
112
+ }'
113
+
114
+ PLATFORM_STATISTICS_JSON_RESULT = '
115
+ {
116
+ "platform_users": [
117
+ {
118
+ "created_time": "2014­03­16T10:40:12",
119
+ "number_of_operations": 1,
120
+ "resource_uri": "/api/v2/platform_users/pl2_un2/",
121
+ "total_calls":
122
+ {
123
+ "2014­05": 2
124
+ },
125
+ "successful_calls":
126
+ {
127
+ "2014­05": 1
128
+ },
129
+ "billable_calls": { },
130
+ "username": "pl2_un1"
131
+ },
132
+ {
133
+ "created_time": "2014­04­16T13:42:00",
134
+ "number_of_operations": 24,
135
+ "resource_uri": "/api/v2/platform_users/pl2_un1/",
136
+ "total_calls":
137
+ {
138
+ "2014­03": 7,
139
+ "2014­04": 12,
140
+ "2014­05": 10
141
+ },
142
+ "successful_calls":
143
+ {
144
+ "2014­03": 6,
145
+ "2014­04": 10,
146
+ "2014­05": 8
147
+ },
148
+ "billable_calls":
149
+ {
150
+ "2014­04": 1,
151
+ "2014­05": 1
152
+ },
153
+ "username": "pl2_un2"
154
+ }
155
+ ],
156
+ "total_platform_calls":
157
+ {
158
+ "2014­03": 7,
159
+ "2014­04": 12,
160
+ "2014­05": 2
161
+ },
162
+ "successful_platform_calls":
163
+ {
164
+ "2014­03": 6,
165
+ "2014­04": 10,
166
+ "2014­05": 9
167
+ },
168
+ "billable_platform_calls":
169
+ {
170
+ "2014­04": 1,
171
+ "2014­05": 1
172
+ }
173
+ }'
174
+
175
+ PLATFORM_USER_JSON_REQUEST_EXAMPLE =
176
+ {
177
+ first_name: "platform_user1_fname",
178
+ last_name: "platform_user1_lname",
179
+ company_name: "platform_company1_name",
180
+ email: "company_email@company1.com"
181
+ }
182
+
183
+ PLATFORM_USER_JSON_RESULT = '
184
+ {
185
+ "created_time": "2014­04­16T13:42:00",
186
+ "number_of_operations": 24,
187
+ "resource_uri": "/api/v2/platform_users/user12345/",
188
+ "total_calls":
189
+ {
190
+ "2014­03": 7,
191
+ "2014­04": 12,
192
+ "2014­05": 10
193
+ },
194
+ "successful_calls":
195
+ {
196
+ "2014­03": 6,
197
+ "2014­04": 10,
198
+ "2014­05": 8
199
+ },
200
+ "billable_calls":
201
+ {
202
+ "2014­04": 1,
203
+ "2014­05": 1
204
+ },
205
+ "username": "user12345"
206
+ }'
data/test/test_base.rb CHANGED
@@ -1,9 +1,7 @@
1
1
  require 'nextcaller_client'
2
2
  require 'webmock/minitest'
3
3
  require 'minitest/autorun'
4
-
5
- TEST_USERNAME = 'username'
6
- TEST_PASSWORD = 'password'
4
+ require_relative './constants'
7
5
 
8
6
  def prepare_url_for_test(path)
9
7
  return Regexp.new 'https://%s:%s@%s%s*' %[TEST_USERNAME, TEST_PASSWORD, NextcallerClient::BASE_URL, path]
@@ -12,7 +10,8 @@ end
12
10
  class BaseTestCase < Minitest::Test
13
11
 
14
12
  def initialize(name)
15
- @client = NextcallerClient::Client.new(TEST_USERNAME, TEST_PASSWORD)
13
+ @client = NextcallerClient::NextCallerClient.new(TEST_USERNAME, TEST_PASSWORD)
14
+ @client_platform = NextcallerClient::NextCallerPlatformClient.new(TEST_USERNAME, TEST_PASSWORD)
16
15
  super(name)
17
16
  end
18
17
 
@@ -1,69 +1,28 @@
1
1
  require_relative './test_base'
2
-
3
- PHONE_JSON_RESULT_EXAMPLE = '
4
- {
5
- "records": [
6
- {
7
- "id": "97d949a413f4ea8b85e9586e1f2d9a",
8
- "first_name": "Jerry",
9
- "last_name": "Seinfeld",
10
- "name": "Jerry Seinfeld",
11
- "language": "English",
12
- "fraud_threat": "low",
13
- "spoof": "false",
14
- "phone": [
15
- {
16
- "number": "2125558383"
17
- }
18
- ],
19
- "carrier": "Verizon Wireless",
20
- "line_type": "LAN",
21
- "address": [
22
- {
23
- "city": "New York",
24
- "extended_zip": "",
25
- "country": "USA",
26
- "line2": "Apt 5a",
27
- "line1": "129 West 81st Street",
28
- "state": "NY",
29
- "zip_code": "10024"
30
- }
31
- ],
32
- "email": "demo@nextcaller.com",
33
- "age": "45-54",
34
- "gender": "Male",
35
- "household_income": "50k-75k",
36
- "marital_status": "Single",
37
- "presence_of_children": "No",
38
- "home_owner_status": "Rent",
39
- "market_value": "350k-500k",
40
- "length_of_residence": "12 Years",
41
- "high_net_worth": "No",
42
- "occupation": "Entertainer",
43
- "education": "Completed College",
44
- "department": "not specified"
45
- }
46
- ]
47
- }'
2
+ require_relative './constants'
48
3
 
49
4
  class PhoneTestCase < BaseTestCase
50
5
 
6
+ def initialize(name)
7
+ @phone = '2125558383'
8
+ super(name)
9
+ end
10
+
51
11
  def test_by_short_phone
52
- phone = '212555838'
12
+ @phone = '212555838'
53
13
  stub_request(:get, prepare_url_for_test('records')).to_return(:body => PHONE_JSON_RESULT_EXAMPLE, :status => 200)
54
- assert_raises(ArgumentError) { @client.get_by_phone(phone)}
14
+ assert_raises(ArgumentError) { @client.get_by_phone(@phone) }
55
15
  end
56
16
 
57
17
  def test_by_wrong_phone
58
- phone = 'XXXXXXXXXX'
18
+ @phone = 'XXXXXXXXXX'
59
19
  stub_request(:get, prepare_url_for_test('records')).to_return(:body => PHONE_JSON_RESULT_EXAMPLE, :status => 200)
60
- assert_raises(ArgumentError) { @client.get_by_phone(phone)}
20
+ assert_raises(ArgumentError) { @client.get_by_phone(@phone) }
61
21
  end
62
22
 
63
23
  def test_by_phone_json_request
64
- phone = '2125558383'
65
24
  stub_request(:get, prepare_url_for_test('records')).to_return(:body => PHONE_JSON_RESULT_EXAMPLE, :status => 200)
66
- res = @client.get_by_phone(phone)
25
+ res = @client.get_by_phone(@phone)
67
26
  refute_nil(res['records'])
68
27
  assert_equal(res['records'][0]['email'], 'demo@nextcaller.com')
69
28
  assert_equal(res['records'][0]['first_name'], 'Jerry')