sift 1.1.6.2 → 4.5.0
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 +5 -13
- data/.circleci/config.yml +105 -0
- data/.github/pull_request_template.md +12 -0
- data/.github/workflows/publishing_sift_ruby.yml +38 -0
- data/.gitignore +1 -0
- data/.jenkins/Jenkinsfile +103 -0
- data/HISTORY +104 -0
- data/README.md +351 -0
- data/examples/psp_merchant_management_apis.rb +105 -0
- data/examples/validation_apis.rb +47 -0
- data/lib/sift/client/decision/apply_to.rb +129 -0
- data/lib/sift/client/decision.rb +66 -0
- data/lib/sift/client.rb +845 -112
- data/lib/sift/error.rb +13 -0
- data/lib/sift/router.rb +41 -0
- data/lib/sift/utils/hash_getter.rb +15 -0
- data/lib/sift/validate/decision.rb +65 -0
- data/lib/sift/validate/primitive.rb +43 -0
- data/lib/sift/version.rb +2 -2
- data/lib/sift.rb +85 -11
- data/sift.gemspec +5 -3
- data/spec/fixtures/fake_responses.rb +16 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/client/decision/apply_to_spec.rb +262 -0
- data/spec/unit/client/decision_spec.rb +83 -0
- data/spec/unit/client_203_spec.rb +193 -0
- data/spec/unit/client_205_spec.rb +117 -0
- data/spec/unit/client_label_spec.rb +68 -11
- data/spec/unit/client_psp_merchant_spec.rb +133 -0
- data/spec/unit/client_spec.rb +556 -79
- data/spec/unit/client_validationapi_spec.rb +91 -0
- data/spec/unit/router_spec.rb +37 -0
- data/spec/unit/validate/decision_spec.rb +85 -0
- data/spec/unit/validate/primitive_spec.rb +73 -0
- data/test_integration_app/decisions_api/test_decisions_api.rb +31 -0
- data/test_integration_app/events_api/test_events_api.rb +843 -0
- data/test_integration_app/globals.rb +2 -0
- data/test_integration_app/main.rb +67 -0
- data/test_integration_app/psp_merchants_api/test_psp_merchant_api.rb +44 -0
- data/test_integration_app/score_api/test_score_api.rb +11 -0
- data/test_integration_app/verification_api/test_verification_api.rb +32 -0
- metadata +85 -28
- data/.travis.yml +0 -13
- data/README.rdoc +0 -85
- data/spec/unit/sift_spec.rb +0 -6
data/README.md
ADDED
@@ -0,0 +1,351 @@
|
|
1
|
+
# sift-ruby
|
2
|
+
|
3
|
+
The official Ruby bindings for the latest version (v205) of the [Sift API](https://sift.com/developers/docs/java/apis-overview).
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
* Ruby 2.0.0 or above.
|
8
|
+
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
If you want to build the gem from source:
|
13
|
+
|
14
|
+
```
|
15
|
+
$ gem build sift.gemspec
|
16
|
+
```
|
17
|
+
|
18
|
+
Alternatively, you can install the gem from rubygems.org:
|
19
|
+
|
20
|
+
```
|
21
|
+
gem install sift
|
22
|
+
```
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
### Creating a Client:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
require "sift"
|
30
|
+
|
31
|
+
Sift.api_key = '<your_api_key_here>'
|
32
|
+
Sift.account_id = '<your_account_id_here>'
|
33
|
+
client = Sift::Client.new()
|
34
|
+
|
35
|
+
##### OR
|
36
|
+
|
37
|
+
client = Sift::Client.new(api_key: '<your_api_key_here>', account_id: '<your_account_id_here>')
|
38
|
+
|
39
|
+
```
|
40
|
+
|
41
|
+
### Sending an event
|
42
|
+
Send event to Sift.
|
43
|
+
To learn more about the Events API visit our [developer docs](https://developers.sift.com/docs/ruby/events-api/overview).
|
44
|
+
|
45
|
+
|
46
|
+
**Optional Params**
|
47
|
+
- `return_score`: `:true` or `:false`
|
48
|
+
- `return_action`: `:true` or `:false`
|
49
|
+
- `return_workflow_status`: `:true` or `:false`
|
50
|
+
- `return_route_info`: `:true` or `:false`
|
51
|
+
- `force_workflow_run`: `:true` or `:false`
|
52
|
+
- `include_score_percentiles`: `:true` or `:false`
|
53
|
+
- `warnings`: `:true` or `:false`
|
54
|
+
- `abuse_types`: `["payment_abuse", "content_abuse", "content_abuse", "account_abuse", "legacy", "account_takeover"]`
|
55
|
+
|
56
|
+
**Example:**
|
57
|
+
```ruby
|
58
|
+
event = "$transaction"
|
59
|
+
|
60
|
+
user_id = "23056" # User ID's may only contain a-z, A-Z, 0-9, =, ., -, _, +, @, :, &, ^, %, !, $
|
61
|
+
|
62
|
+
properties = {
|
63
|
+
"$user_id" => user_id,
|
64
|
+
"$user_email" => "buyer@gmail.com",
|
65
|
+
"$seller_user_id" => "2371",
|
66
|
+
"seller_user_email" => "seller@gmail.com",
|
67
|
+
"$transaction_id" => "573050",
|
68
|
+
"$payment_method" => {
|
69
|
+
"$payment_type" => "$credit_card",
|
70
|
+
"$payment_gateway" => "$braintree",
|
71
|
+
"$card_bin" => "542486",
|
72
|
+
"$card_last4" => "4444"
|
73
|
+
},
|
74
|
+
"$currency_code" => "USD",
|
75
|
+
"$amount" => 15230000,
|
76
|
+
}
|
77
|
+
|
78
|
+
response = client.track(event, properties)
|
79
|
+
|
80
|
+
response.ok? # returns true or false
|
81
|
+
response.body # API response body
|
82
|
+
response.http_status_code # HTTP response code, 200 is ok.
|
83
|
+
response.api_status # status field in the return body, Link to Error Codes
|
84
|
+
response.api_error_message # Error message associated with status Error Code
|
85
|
+
|
86
|
+
# Request a score for the user with user_id 23056
|
87
|
+
response = client.score(user_id)
|
88
|
+
```
|
89
|
+
|
90
|
+
## Decisions
|
91
|
+
|
92
|
+
To learn more about the decisions endpoint visit our [developer docs](https://sift.com/developers/docs/ruby/decisions-api/get-decisions).
|
93
|
+
|
94
|
+
### List of Configured Decisions
|
95
|
+
|
96
|
+
Get a list of your decisions.
|
97
|
+
|
98
|
+
**Optional Params**
|
99
|
+
- `entity_type`: `:user` or `:order` or `:session` or `:content`
|
100
|
+
- `abuse_types`: `["payment_abuse", "content_abuse", "content_abuse",
|
101
|
+
"account_abuse", "legacy", "account_takeover"]`
|
102
|
+
|
103
|
+
**Returns**
|
104
|
+
|
105
|
+
A `Response` object
|
106
|
+
|
107
|
+
**Example:**
|
108
|
+
```ruby
|
109
|
+
# fetch a list of all your decisions
|
110
|
+
response = client.decisions({
|
111
|
+
entity_type: :user,
|
112
|
+
abuse_types: ["payment_abuse", "content_abuse"]
|
113
|
+
})
|
114
|
+
|
115
|
+
# Check that response is okay.
|
116
|
+
unless response.ok?
|
117
|
+
raise "Unable to fetch decisions #{response.api_error_message} " +
|
118
|
+
"#{response.api_error_description}"
|
119
|
+
end
|
120
|
+
|
121
|
+
# find a decisions with the id "block_bad_user"
|
122
|
+
user_decision = response.body["data"].find do |decision|
|
123
|
+
decision["id"] == "block_bad_user"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Get the next page
|
127
|
+
|
128
|
+
if response.body["has_more"]
|
129
|
+
client.decisions(response.body)
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
|
134
|
+
### Apply a decision
|
135
|
+
|
136
|
+
Applies a decision to an entity. Visit our [developer docs](http://sift.com/developers/docs/ruby/decisions-api/apply-decision) for more information.
|
137
|
+
|
138
|
+
**Required Params:**
|
139
|
+
- `decision_id`, `source`, `user_id`
|
140
|
+
|
141
|
+
**Other Params**
|
142
|
+
- `order_id`: when applying a decision to an order, you must pass in the `order_id`
|
143
|
+
- `session_id`: when applying a decision to a session, you must pass in the `session_id`
|
144
|
+
- `analyst`: when `source` is set to `manual_review`, this field *is required*
|
145
|
+
|
146
|
+
**Returns**
|
147
|
+
`Response` object.
|
148
|
+
|
149
|
+
**Examples:**
|
150
|
+
```ruby
|
151
|
+
# apply decision to a user
|
152
|
+
response = client.apply_decision({
|
153
|
+
decision_id: "block_bad_user",
|
154
|
+
source: "manual_review",
|
155
|
+
analyst: "bob@your_company.com",
|
156
|
+
user_id: "john@example.com"
|
157
|
+
})
|
158
|
+
|
159
|
+
# apply decision to "john@example.com"'s order
|
160
|
+
response = client.apply_decision({
|
161
|
+
decision_id: "block_bad_order",
|
162
|
+
source: "manual_review",
|
163
|
+
analyst: "bob@your_company.com",
|
164
|
+
user_id: "john@example.com",
|
165
|
+
order_id: "ORDER_1234"
|
166
|
+
})
|
167
|
+
|
168
|
+
# apply decision to "john@example.com"'s session
|
169
|
+
response = client.apply_decision({
|
170
|
+
decision_id: "block_bad_session",
|
171
|
+
source: "manual_review",
|
172
|
+
analyst: "bob@your_company.com",
|
173
|
+
user_id: "john@example.com",
|
174
|
+
session_id: "SESSION_ID_1234"
|
175
|
+
})
|
176
|
+
|
177
|
+
# apply decision to "john@example.com"'s content
|
178
|
+
response = client.apply_decision({
|
179
|
+
decision_id: "block_bad_session",
|
180
|
+
source: "manual_review",
|
181
|
+
analyst: "bob@your_company.com",
|
182
|
+
user_id: "john@example.com",
|
183
|
+
content_id: "CONTENT_ID_1234"
|
184
|
+
})
|
185
|
+
|
186
|
+
|
187
|
+
# Make sure you handle the response after applying a decision:
|
188
|
+
|
189
|
+
if response.ok?
|
190
|
+
# do stuff
|
191
|
+
else
|
192
|
+
# Error message
|
193
|
+
response.api_error_message
|
194
|
+
|
195
|
+
# Summary of the error
|
196
|
+
response.api_error_description
|
197
|
+
|
198
|
+
# hash of errors:
|
199
|
+
# key: field in question
|
200
|
+
# value: description of the issue
|
201
|
+
response.api_error_issues
|
202
|
+
end
|
203
|
+
```
|
204
|
+
|
205
|
+
## Sending a Label
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
# Label the user with user_id 23056 as Bad with all optional fields
|
209
|
+
response = client.label(user_id, {
|
210
|
+
"$is_bad" => true,
|
211
|
+
"$abuse_type" => "payment_abuse",
|
212
|
+
"$description" => "Chargeback issued",
|
213
|
+
"$source" => "Manual Review",
|
214
|
+
"$analyst" => "analyst.name@your_domain.com"
|
215
|
+
})
|
216
|
+
|
217
|
+
# Get the status of a workflow run
|
218
|
+
response = client.get_workflow_status('my_run_id')
|
219
|
+
|
220
|
+
# Get the latest decisions for a user
|
221
|
+
response = client.get_user_decisions('example_user_id')
|
222
|
+
|
223
|
+
# Get the latest decisions for an order
|
224
|
+
response = client.get_order_decisions('example_order_id')
|
225
|
+
|
226
|
+
# Get the latest decisions for a session
|
227
|
+
response = client.get_session_decisions('example_user_id', 'example_session_id')
|
228
|
+
|
229
|
+
# Get the latest decisions for an content
|
230
|
+
response = client.get_content_decisions('example_user_id', 'example_order_id')
|
231
|
+
```
|
232
|
+
|
233
|
+
## PSP Merchant Management API
|
234
|
+
|
235
|
+
To learn more about the decisions endpoint visit our [developer docs](https://sift.com/developers/docs/ruby/psp-merchant-management-api).
|
236
|
+
|
237
|
+
```ruby
|
238
|
+
# On-board a PSP merchant summary to Sift Platform.
|
239
|
+
# Sample psp_merchant_profile
|
240
|
+
properties = {
|
241
|
+
"id": "merchant_id_01000",
|
242
|
+
"name": "Wonderful Payments Inc.",
|
243
|
+
"description": "Wonderful Payments payment provider.",
|
244
|
+
"address": {
|
245
|
+
"name": "Alany",
|
246
|
+
"address_1": "Big Payment blvd, 22",
|
247
|
+
"address_2": "apt, 8",
|
248
|
+
"city": "New Orleans",
|
249
|
+
"region": "NA",
|
250
|
+
"country": "US",
|
251
|
+
"zipcode": "76830",
|
252
|
+
"phone": "0394888320"
|
253
|
+
},
|
254
|
+
"category": "1002",
|
255
|
+
"service_level": "Platinum",
|
256
|
+
"status": "active",
|
257
|
+
"risk_profile": {
|
258
|
+
"level": "low",
|
259
|
+
"score": 10
|
260
|
+
}
|
261
|
+
}
|
262
|
+
response = client.create_psp_merchant_profile(properties)
|
263
|
+
|
264
|
+
# Update a merchant summary to reflect changes in the status or service level or address etc.
|
265
|
+
properties = {
|
266
|
+
"id": "merchant_id_01000",
|
267
|
+
"name": "Wonderful Payments Inc.",
|
268
|
+
"description": "Wonderful Payments payment provider.",
|
269
|
+
"address": {
|
270
|
+
"name": "Alany",
|
271
|
+
"address_1": "Big Payment blvd, 22",
|
272
|
+
"address_2": "apt, 8",
|
273
|
+
"city": "New Orleans",
|
274
|
+
"region": "NA",
|
275
|
+
"country": "US",
|
276
|
+
"zipcode": "76830",
|
277
|
+
"phone": "0394888320"
|
278
|
+
},
|
279
|
+
"category": "1002",
|
280
|
+
"service_level": "Platinum",
|
281
|
+
"status": "active",
|
282
|
+
"risk_profile": {
|
283
|
+
"level": "low",
|
284
|
+
"score": 10
|
285
|
+
}
|
286
|
+
}
|
287
|
+
response = client.update_psp_merchant_profile('merchant_id', properties)
|
288
|
+
|
289
|
+
# Get the existing PSP merchant summaries.
|
290
|
+
response = client.get_a_psp_merchant_profile('merchant_id')
|
291
|
+
|
292
|
+
# Get all PSP merchant summaries
|
293
|
+
response = client.get_psp_merchant_profiles()
|
294
|
+
|
295
|
+
# Get PSP merchant summaries paginated
|
296
|
+
response = client.get_psp_merchant_profiles('batch_size', 'batch_token')
|
297
|
+
```
|
298
|
+
|
299
|
+
## Response Object
|
300
|
+
|
301
|
+
All requests to our apis will return a `Response` instance.
|
302
|
+
|
303
|
+
### Public Methods:
|
304
|
+
- `ok?` returns `true` when the response is a `200`-`299`, `false` if it isn't
|
305
|
+
- `body` returns a hash representation of the json body returned.
|
306
|
+
- `api_error_message` returns a string describing the api error code.
|
307
|
+
- `api_error_description` a summary of the error that occured.
|
308
|
+
- `api_error_issues` a hash describing the items the error occured. The `key` is the item and the `value` is the description of the error.
|
309
|
+
|
310
|
+
|
311
|
+
## Building
|
312
|
+
|
313
|
+
Building and publishing the gem is captured by the following steps:
|
314
|
+
|
315
|
+
```ruby
|
316
|
+
$ gem build sift.gemspec
|
317
|
+
$ gem push sift-<current version>.gem
|
318
|
+
|
319
|
+
$ bundle
|
320
|
+
$ rake -T
|
321
|
+
$ rake build
|
322
|
+
$ rake install
|
323
|
+
$ rake release
|
324
|
+
```
|
325
|
+
|
326
|
+
|
327
|
+
## Testing
|
328
|
+
|
329
|
+
To run the various tests use the rake command as follows:
|
330
|
+
|
331
|
+
```ruby
|
332
|
+
$ rake spec
|
333
|
+
```
|
334
|
+
|
335
|
+
## Integration testing app
|
336
|
+
|
337
|
+
For testing the app with real calls it is possible to run the integration testing app,
|
338
|
+
it makes calls to almost all our public endpoints to make sure the library integrates
|
339
|
+
well. At the moment, the app is run on every merge to master
|
340
|
+
|
341
|
+
#### How to run it locally
|
342
|
+
|
343
|
+
1. Add env variable `ACCOUNT_ID` with the valid account id
|
344
|
+
2. Add env variable `API_KEY` with the valid Api Key associated from the account
|
345
|
+
3. Run the following under the project root folder
|
346
|
+
```
|
347
|
+
# Install the budle locally
|
348
|
+
bundle check || bundle install
|
349
|
+
# Run the app
|
350
|
+
bundle exec ruby test_integration_app/main.rb
|
351
|
+
```
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sift'
|
3
|
+
require 'multi_json'
|
4
|
+
|
5
|
+
class MyLogger
|
6
|
+
def warn(e)
|
7
|
+
puts "[WARN] " + e.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def error(e)
|
11
|
+
puts "[ERROR] " + e.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def fatal(e)
|
15
|
+
puts "[FATAL] " + e.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
def info(e)
|
19
|
+
puts "[INFO] " + e.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle_response(response)
|
24
|
+
if response.nil?
|
25
|
+
puts 'Error: there was an HTTP error calling through the API'
|
26
|
+
else
|
27
|
+
puts 'Successfully sent request; was ok? : ' + response.ok?.to_s
|
28
|
+
puts 'API error message : ' + response.api_error_message.to_s
|
29
|
+
puts 'API status code : ' + response.api_status.to_s
|
30
|
+
puts 'HTTP status code : ' + response.http_status_code.to_s
|
31
|
+
puts 'original request : ' + response.original_request.to_s
|
32
|
+
puts 'response body : ' + response.body.to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Sift.logger = MyLogger.new
|
37
|
+
|
38
|
+
$api_key = 'put-valid-api-key'
|
39
|
+
$account_id = 'put-valid-account-id'
|
40
|
+
|
41
|
+
def post_merchant_properties
|
42
|
+
# Sample psp_merchant_profile
|
43
|
+
{
|
44
|
+
"id": "merchant_id_01004",
|
45
|
+
"name": "Wonderful Payments Inc.",
|
46
|
+
"description": "Wonderful Payments payment provider.",
|
47
|
+
"address": {
|
48
|
+
"name": "Alany",
|
49
|
+
"address_1": "Big Payment blvd, 22",
|
50
|
+
"address_2": "apt, 8",
|
51
|
+
"city": "New Orleans",
|
52
|
+
"region": "NA",
|
53
|
+
"country": "US",
|
54
|
+
"zipcode": "76830",
|
55
|
+
"phone": "0394888320"
|
56
|
+
},
|
57
|
+
"category": "1002",
|
58
|
+
"service_level": "Platinum",
|
59
|
+
"status": "active",
|
60
|
+
"risk_profile": {
|
61
|
+
"level": "low",
|
62
|
+
"score": 10
|
63
|
+
}
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def put_merchant_properties
|
68
|
+
# Sample update psp_merchant_profile
|
69
|
+
{
|
70
|
+
"id": "merchant_id_01004",
|
71
|
+
"name": "Wonderful Payments Inc. update",
|
72
|
+
"description": "Wonderful Payments payment provider. update",
|
73
|
+
"address": {
|
74
|
+
"name": "Alany",
|
75
|
+
"address_1": "Big Payment blvd, 22",
|
76
|
+
"address_2": "apt, 8",
|
77
|
+
"city": "New Orleans",
|
78
|
+
"region": "NA",
|
79
|
+
"country": "US",
|
80
|
+
"zipcode": "76830",
|
81
|
+
"phone": "0394888320"
|
82
|
+
},
|
83
|
+
"category": "1002",
|
84
|
+
"service_level": "Platinum",
|
85
|
+
"status": "active",
|
86
|
+
"risk_profile": {
|
87
|
+
"level": "low",
|
88
|
+
"score": 10
|
89
|
+
}
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
# handle_response Sift::Client.new(:api_key => $api_key, :account_id => $account_id).create_psp_merchant_profile(post_merchant_properties)
|
94
|
+
|
95
|
+
# handle_response Sift::Client.new(:api_key => $api_key, :account_id => $account_id).update_psp_merchant_profile("merchant_id_01004", put_merchant_properties)
|
96
|
+
|
97
|
+
# handle_response Sift::Client.new(:api_key => $api_key, :account_id => $account_id).get_a_psp_merchant_profile("merchant_id_01004")
|
98
|
+
|
99
|
+
# handle_response Sift::Client.new(:api_key => $api_key, :account_id => $account_id).get_psp_merchant_profiles()
|
100
|
+
|
101
|
+
# handle_response Sift::Client.new(:api_key => $api_key, :account_id => $account_id).get_psp_merchant_profiles(2)
|
102
|
+
|
103
|
+
handle_response Sift::Client.new(:api_key => $api_key, :account_id => $account_id).get_psp_merchant_profiles(5, "next_ref")
|
104
|
+
|
105
|
+
puts "request completed"
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "sift"
|
2
|
+
require 'multi_json'
|
3
|
+
|
4
|
+
#$api_key = "put-a-valid-apikey"
|
5
|
+
#$user_id = "put-a-valid-userid"
|
6
|
+
|
7
|
+
def valid_send_properties
|
8
|
+
{
|
9
|
+
:$user_id => $user_id,
|
10
|
+
:$send_to => $user_id,
|
11
|
+
:$verification_type => '$email',
|
12
|
+
:$brand_name => 'all',
|
13
|
+
:$language => 'en',
|
14
|
+
:$event => {
|
15
|
+
:$session_id => 'gigtleqddo84l8cm15qe4il',
|
16
|
+
:$verified_event => '$login',
|
17
|
+
:$reason => '$automated_rule',
|
18
|
+
:$ip => '192.168.1.1',
|
19
|
+
:$browser => {
|
20
|
+
:$user_agent => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid_resend_properties
|
27
|
+
{
|
28
|
+
:$user_id => $user_id,
|
29
|
+
:$verified_event => '$login'
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def valid_check_properties
|
34
|
+
{
|
35
|
+
:$user_id => $user_id,
|
36
|
+
:$code => '668316'
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
#response = Sift::Client.new(:api_key => $api_key,:user_id => $user_id,:version=>1.1).verification_send(valid_send_properties)
|
41
|
+
|
42
|
+
#response = Sift::Client.new(:api_key => $api_key,:user_id => $user_id,:version=>1.1).verification_resend(valid_resend_properties)
|
43
|
+
response = Sift::Client.new(:api_key => $api_key,:user_id => $user_id,:version=>1.1).verification_check(valid_check_properties)
|
44
|
+
|
45
|
+
p response
|
46
|
+
|
47
|
+
puts "completed"
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require "multi_json"
|
2
|
+
|
3
|
+
require_relative "../../validate/decision"
|
4
|
+
require_relative "../../client"
|
5
|
+
require_relative "../../router"
|
6
|
+
require_relative "../../utils/hash_getter"
|
7
|
+
|
8
|
+
module Sift
|
9
|
+
class Client
|
10
|
+
class Decision
|
11
|
+
class ApplyTo
|
12
|
+
PROPERTIES = %w{
|
13
|
+
source
|
14
|
+
analyst
|
15
|
+
description
|
16
|
+
order_id
|
17
|
+
session_id
|
18
|
+
content_id
|
19
|
+
user_id
|
20
|
+
account_id
|
21
|
+
time
|
22
|
+
}
|
23
|
+
|
24
|
+
attr_reader :decision_id, :configs, :getter, :api_key
|
25
|
+
|
26
|
+
PROPERTIES.each do |attribute|
|
27
|
+
class_eval %{
|
28
|
+
def #{attribute}
|
29
|
+
getter.get(:#{attribute})
|
30
|
+
end
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(api_key, decision_id, configs)
|
35
|
+
@api_key = api_key
|
36
|
+
@decision_id = decision_id
|
37
|
+
@configs = configs
|
38
|
+
@getter = Utils::HashGetter.new(configs)
|
39
|
+
end
|
40
|
+
|
41
|
+
def run
|
42
|
+
if errors.empty?
|
43
|
+
send_request
|
44
|
+
else
|
45
|
+
Response.new(
|
46
|
+
MultiJson.dump({
|
47
|
+
status: 55,
|
48
|
+
error_message: errors.join(", ")
|
49
|
+
}),
|
50
|
+
400,
|
51
|
+
nil
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def send_request
|
59
|
+
Router.post(path, {
|
60
|
+
body: request_body,
|
61
|
+
headers: headers
|
62
|
+
})
|
63
|
+
end
|
64
|
+
|
65
|
+
def request_body
|
66
|
+
{
|
67
|
+
source: source,
|
68
|
+
description: description,
|
69
|
+
analyst: analyst,
|
70
|
+
decision_id: decision_id,
|
71
|
+
time: time
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def errors
|
76
|
+
validator = Validate::Decision.new(configs)
|
77
|
+
|
78
|
+
if applying_to_order?
|
79
|
+
validator.valid_order?
|
80
|
+
elsif applying_to_session?
|
81
|
+
validator.valid_session?
|
82
|
+
else
|
83
|
+
validator.valid_user?
|
84
|
+
end
|
85
|
+
|
86
|
+
validator.error_messages
|
87
|
+
end
|
88
|
+
|
89
|
+
def applying_to_order?
|
90
|
+
configs.has_key?("order_id") || configs.has_key?(:order_id)
|
91
|
+
end
|
92
|
+
|
93
|
+
def applying_to_session?
|
94
|
+
configs.has_key?("session_id") || configs.has_key?(:session_id)
|
95
|
+
end
|
96
|
+
|
97
|
+
def applying_to_content?
|
98
|
+
configs.has_key?("content_id") || configs.has_key?(:content_id)
|
99
|
+
end
|
100
|
+
|
101
|
+
def path
|
102
|
+
if applying_to_order?
|
103
|
+
"#{user_path}/orders/#{CGI.escape(order_id)}/decisions"
|
104
|
+
elsif applying_to_session?
|
105
|
+
"#{user_path}/sessions/#{CGI.escape(session_id)}/decisions"
|
106
|
+
elsif applying_to_content?
|
107
|
+
"#{user_path}/content/#{CGI.escape(content_id)}/decisions"
|
108
|
+
else
|
109
|
+
"#{user_path}/decisions"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def user_path
|
114
|
+
"#{base_path}/users/#{CGI.escape(user_id)}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def base_path
|
118
|
+
"#{Client::API3_ENDPOINT}/v3/accounts/#{account_id}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def headers
|
122
|
+
{
|
123
|
+
"Content-type" => "application/json"
|
124
|
+
}.merge(Client.build_auth_header(api_key))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "cgi"
|
2
|
+
|
3
|
+
require_relative "../router"
|
4
|
+
require_relative "../validate/decision"
|
5
|
+
require_relative "../utils/hash_getter"
|
6
|
+
require_relative "./decision/apply_to"
|
7
|
+
|
8
|
+
module Sift
|
9
|
+
class Client
|
10
|
+
class Decision
|
11
|
+
FILTER_PARAMS = %w{ limit entity_type abuse_types from }
|
12
|
+
|
13
|
+
attr_reader :account_id, :api_key
|
14
|
+
|
15
|
+
def initialize(api_key, account_id)
|
16
|
+
@account_id = account_id
|
17
|
+
@api_key = api_key
|
18
|
+
end
|
19
|
+
|
20
|
+
def list(options = {})
|
21
|
+
getter = Utils::HashGetter.new(options)
|
22
|
+
|
23
|
+
if path = getter.get(:next_ref)
|
24
|
+
request_next_page(path)
|
25
|
+
else
|
26
|
+
Router.get(index_path, {
|
27
|
+
query: build_query(getter),
|
28
|
+
headers: auth_header
|
29
|
+
})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_query(getter)
|
34
|
+
FILTER_PARAMS.inject({}) do |result, filter|
|
35
|
+
if value = getter.get(filter)
|
36
|
+
result[filter] = value.is_a?(Array) ? value.join(",") : value
|
37
|
+
end
|
38
|
+
|
39
|
+
result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def apply_to(configs = {})
|
44
|
+
getter = Utils::HashGetter.new(configs)
|
45
|
+
configs[:account_id] = account_id
|
46
|
+
|
47
|
+
ApplyTo.new(api_key, getter.get(:decision_id), configs).run
|
48
|
+
end
|
49
|
+
|
50
|
+
def index_path
|
51
|
+
"#{Client::API3_ENDPOINT}/v3/accounts/#{account_id}/decisions"
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def request_next_page(path)
|
57
|
+
Router.get(path, headers: auth_header)
|
58
|
+
end
|
59
|
+
|
60
|
+
def auth_header
|
61
|
+
Client.build_auth_header(api_key)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|