sift 4.3.0 → 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 +4 -4
- data/.circleci/config.yml +17 -0
- data/.github/workflows/publishing_sift_ruby.yml +0 -12
- data/.jenkins/Jenkinsfile +103 -0
- data/HISTORY +6 -0
- data/README.md +33 -2
- data/lib/sift/client.rb +27 -2
- data/lib/sift/version.rb +1 -1
- data/spec/unit/client_spec.rb +165 -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 +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71be696ff04ffb1503d22a724241e5087809d2ffa2ab29f08666939ecd6bb98b
|
4
|
+
data.tar.gz: e2e841d8259fbea8c247b1b2bd3cdf208bd53ded613a765a75f595714a2e1e8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b578f6bccf6323d4ef53947cea5a517678920d882439da1d1df262cf5eb39e45064aab3a1dee702da01f41f29a522df0c5e7b850c68e1ac302fa0f7d9830e29
|
7
|
+
data.tar.gz: 3c4565ffc5f98626ac67a07b378adfd80aaef787e47ffc50d84780da4b62788bdfb43e1b2e4ed90ca59cb4ee0fe23ec727dad8d1c0dd9413c137d7ec1de95510
|
data/.circleci/config.yml
CHANGED
@@ -81,8 +81,25 @@ jobs:
|
|
81
81
|
- slack/notify:
|
82
82
|
<<: *slack_notify
|
83
83
|
|
84
|
+
run_integration_tests:
|
85
|
+
docker:
|
86
|
+
- image: circleci/ruby:2.4.2-jessie-node
|
87
|
+
steps:
|
88
|
+
- checkout
|
89
|
+
- run:
|
90
|
+
name: Install bundle and run the tests
|
91
|
+
command: |
|
92
|
+
bundle check || bundle install
|
93
|
+
bundle exec ruby test_integration_app/main.rb
|
94
|
+
|
84
95
|
workflows:
|
85
96
|
ruby-test:
|
86
97
|
jobs:
|
87
98
|
- build:
|
88
99
|
context: *context
|
100
|
+
ruby-integration-tests:
|
101
|
+
jobs:
|
102
|
+
- run_integration_tests:
|
103
|
+
filters:
|
104
|
+
branches:
|
105
|
+
only: master
|
@@ -12,18 +12,14 @@ jobs:
|
|
12
12
|
steps:
|
13
13
|
- name: Checkout code
|
14
14
|
uses: actions/checkout@v3
|
15
|
-
|
16
|
-
|
17
15
|
- name: Set up Ruby
|
18
16
|
uses: ruby/setup-ruby@v1
|
19
17
|
with:
|
20
18
|
ruby-version: 2.7
|
21
|
-
|
22
19
|
- name: Install Bundler
|
23
20
|
run: |
|
24
21
|
sudo gem install bundler
|
25
22
|
bundle install
|
26
|
-
|
27
23
|
- name: Build and push gem
|
28
24
|
run: |
|
29
25
|
mkdir -p $HOME/.gem
|
@@ -37,14 +33,6 @@ jobs:
|
|
37
33
|
gem build sift.gemspec
|
38
34
|
gem push sift-$version.gem
|
39
35
|
rm -rf $HOME/.gem
|
40
|
-
ls -la $HOME/
|
41
36
|
else
|
42
37
|
echo "Gem version $version exists on RubyGems"
|
43
38
|
fi
|
44
|
-
|
45
|
-
- name: Run Rake tasks
|
46
|
-
run: |
|
47
|
-
bundle exec rake -T
|
48
|
-
bundle exec rake build
|
49
|
-
bundle exec rake install
|
50
|
-
bundle exec rake release
|
@@ -0,0 +1,103 @@
|
|
1
|
+
// Load Jenkins shared library
|
2
|
+
jenkinsBranch = 'v0.37.0'
|
3
|
+
sharedLib = library("shared-lib@${jenkinsBranch}")
|
4
|
+
|
5
|
+
def siftRubyWorkflow = sharedLib.com.sift.ci.SiftRubyWorkflow.new()
|
6
|
+
def ciUtil = sharedLib.com.sift.ci.CIUtil.new()
|
7
|
+
def stackdriver = sharedLib.com.sift.ci.StackDriverMetrics.new()
|
8
|
+
|
9
|
+
// Default GitHub status context for automatically triggered builds
|
10
|
+
def defaultStatusContext = 'Jenkins:auto'
|
11
|
+
|
12
|
+
// Pod template file for Jenkins agent pod
|
13
|
+
// Pod template yaml file is defined in https://github.com/SiftScience/jenkins/tree/master/resources/jenkins-k8s-pod-templates
|
14
|
+
def ruby2PodTemplateFile = 'ruby-2-4-2-pod-template.yaml'
|
15
|
+
def ruby2PodLabel = "ruby2-${BUILD_TAG}"
|
16
|
+
|
17
|
+
|
18
|
+
// GitHub repo name
|
19
|
+
def repoName = 'sift-ruby'
|
20
|
+
|
21
|
+
pipeline {
|
22
|
+
agent none
|
23
|
+
options {
|
24
|
+
timestamps()
|
25
|
+
skipDefaultCheckout()
|
26
|
+
disableConcurrentBuilds()
|
27
|
+
disableRestartFromStage()
|
28
|
+
parallelsAlwaysFailFast()
|
29
|
+
buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '30', numToKeepStr: '')
|
30
|
+
timeout(time: 1, unit: 'HOURS')
|
31
|
+
}
|
32
|
+
environment {
|
33
|
+
GIT_BRANCH = "${env.CHANGE_BRANCH != null? env.CHANGE_BRANCH : env.BRANCH_NAME}"
|
34
|
+
}
|
35
|
+
stages {
|
36
|
+
stage('Initialize') {
|
37
|
+
steps {
|
38
|
+
script {
|
39
|
+
statusContext = defaultStatusContext
|
40
|
+
// Get the commit sha for the build
|
41
|
+
commitSha = ciUtil.commitHashForBuild()
|
42
|
+
ciUtil.updateGithubCommitStatus(repoName, statusContext, 'Started', 'pending', commitSha)
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
stage ('Build and Test Workflows') {
|
47
|
+
steps {
|
48
|
+
script {
|
49
|
+
def workflows = [:]
|
50
|
+
def stage1 = 'Run Integration Tests - ruby'
|
51
|
+
workflows[stage1] = {
|
52
|
+
stage(stage1) {
|
53
|
+
if (env.GIT_BRANCH.equals('master')) {
|
54
|
+
ciUtil.updateGithubCommitStatus(repoName, stage1, 'Started', 'pending', commitSha)
|
55
|
+
try {
|
56
|
+
siftRubyWorkflow.runSiftRubyIntegration(ruby2PodTemplateFile, ruby2PodLabel)
|
57
|
+
ciUtil.updateGithubCommitStatus(repoName, stage1, 'SUCCESS', 'success', commitSha)
|
58
|
+
} catch (Exception e) {
|
59
|
+
ciUtil.updateGithubCommitStatus(repoName, stage1, 'FAILURE', 'failure', commitSha)
|
60
|
+
print("${stage1} failed")
|
61
|
+
throw e
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
def stage2 = 'Test - ruby'
|
67
|
+
workflows[stage2] = {
|
68
|
+
stage(stage2) {
|
69
|
+
ciUtil.updateGithubCommitStatus(repoName, stage2, 'Started', 'pending', commitSha)
|
70
|
+
try {
|
71
|
+
siftRubyWorkflow.runSiftRubyTest(ruby2PodTemplateFile, ruby2PodLabel)
|
72
|
+
ciUtil.updateGithubCommitStatus(repoName, stage2, 'SUCCESS', 'success', commitSha)
|
73
|
+
} catch (Exception e) {
|
74
|
+
ciUtil.updateGithubCommitStatus(repoName, stage2, 'FAILURE', 'failure', commitSha)
|
75
|
+
print("${stage2} failed")
|
76
|
+
throw e
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
parallel workflows
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
post {
|
86
|
+
success {
|
87
|
+
script {
|
88
|
+
ciUtil.updateGithubCommitStatus(repoName, statusContext, currentBuild.currentResult, 'success', commitSha)
|
89
|
+
}
|
90
|
+
}
|
91
|
+
unsuccessful {
|
92
|
+
script {
|
93
|
+
ciUtil.updateGithubCommitStatus(repoName, statusContext, currentBuild.currentResult, 'failure', commitSha)
|
94
|
+
ciUtil.notifySlack(repoName, commitSha)
|
95
|
+
}
|
96
|
+
}
|
97
|
+
always {
|
98
|
+
script {
|
99
|
+
stackdriver.updatePipelineStatistics(this)
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
data/HISTORY
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# sift-ruby
|
2
|
-
[](https://circleci.com/gh/SiftScience/sift-ruby)
|
3
2
|
|
4
3
|
The official Ruby bindings for the latest version (v205) of the [Sift API](https://sift.com/developers/docs/java/apis-overview).
|
5
4
|
|
@@ -39,8 +38,22 @@ client = Sift::Client.new(api_key: '<your_api_key_here>', account_id: '<your_acc
|
|
39
38
|
|
40
39
|
```
|
41
40
|
|
42
|
-
### Sending
|
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).
|
43
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:**
|
44
57
|
```ruby
|
45
58
|
event = "$transaction"
|
46
59
|
|
@@ -318,3 +331,21 @@ To run the various tests use the rake command as follows:
|
|
318
331
|
```ruby
|
319
332
|
$ rake spec
|
320
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
|
+
```
|
data/lib/sift/client.rb
CHANGED
@@ -201,6 +201,12 @@ module Sift
|
|
201
201
|
#
|
202
202
|
# :path::
|
203
203
|
# Overrides the URI path for this API call.
|
204
|
+
#
|
205
|
+
# :include_score_percentiles::
|
206
|
+
# include_score_percentiles(optional) : Whether to add new parameter in the query parameter.
|
207
|
+
#
|
208
|
+
# :warnings::
|
209
|
+
# warnings(optional) : Whether to add list of warnings (if any) to response.
|
204
210
|
#
|
205
211
|
# ==== Returns:
|
206
212
|
#
|
@@ -220,6 +226,7 @@ module Sift
|
|
220
226
|
force_workflow_run = opts[:force_workflow_run]
|
221
227
|
abuse_types = opts[:abuse_types]
|
222
228
|
include_score_percentiles = opts[:include_score_percentiles]
|
229
|
+
warnings = opts[:warnings]
|
223
230
|
|
224
231
|
raise("event must be a non-empty string") if (!event.is_a? String) || event.empty?
|
225
232
|
raise("properties cannot be empty") if properties.empty?
|
@@ -232,8 +239,12 @@ module Sift
|
|
232
239
|
query["return_route_info"] = "true" if return_route_info
|
233
240
|
query["force_workflow_run"] = "true" if force_workflow_run
|
234
241
|
query["abuse_types"] = abuse_types.join(",") if abuse_types
|
235
|
-
|
236
|
-
|
242
|
+
|
243
|
+
if include_score_percentiles == "true" || warnings == "true"
|
244
|
+
fields = []
|
245
|
+
fields << "SCORE_PERCENTILES" if include_score_percentiles == "true"
|
246
|
+
fields << "WARNINGS" if warnings == "true"
|
247
|
+
query["fields"] = fields.join(",")
|
237
248
|
end
|
238
249
|
|
239
250
|
options = {
|
@@ -275,6 +286,9 @@ module Sift
|
|
275
286
|
#
|
276
287
|
# :version::
|
277
288
|
# Overrides the version of the Events API to call.
|
289
|
+
#
|
290
|
+
# :include_score_percentiles::
|
291
|
+
# include_score_percentiles(optional) : Whether to add new parameter in the query parameter.
|
278
292
|
#
|
279
293
|
# ==== Returns:
|
280
294
|
#
|
@@ -286,6 +300,7 @@ module Sift
|
|
286
300
|
api_key = opts[:api_key] || @api_key
|
287
301
|
timeout = opts[:timeout] || @timeout
|
288
302
|
version = opts[:version] || @version
|
303
|
+
include_score_percentiles = opts[:include_score_percentiles]
|
289
304
|
|
290
305
|
raise("user_id must be a non-empty string") if (!user_id.is_a? String) || user_id.to_s.empty?
|
291
306
|
raise("Bad api_key parameter") if api_key.empty?
|
@@ -293,6 +308,9 @@ module Sift
|
|
293
308
|
query = {}
|
294
309
|
query["api_key"] = api_key
|
295
310
|
query["abuse_types"] = abuse_types.join(",") if abuse_types
|
311
|
+
if include_score_percentiles == "true"
|
312
|
+
query["fields"] = "SCORE_PERCENTILES"
|
313
|
+
end
|
296
314
|
|
297
315
|
options = {
|
298
316
|
:headers => {"User-Agent" => user_agent},
|
@@ -332,6 +350,9 @@ module Sift
|
|
332
350
|
#
|
333
351
|
# :timeout::
|
334
352
|
# Overrides the timeout (in seconds) for this call.
|
353
|
+
#
|
354
|
+
# :include_score_percentiles::
|
355
|
+
# include_score_percentiles(optional) : Whether to add new parameter in the query parameter.
|
335
356
|
#
|
336
357
|
# ==== Returns:
|
337
358
|
#
|
@@ -342,6 +363,7 @@ module Sift
|
|
342
363
|
abuse_types = opts[:abuse_types]
|
343
364
|
api_key = opts[:api_key] || @api_key
|
344
365
|
timeout = opts[:timeout] || @timeout
|
366
|
+
include_score_percentiles = opts[:include_score_percentiles]
|
345
367
|
|
346
368
|
raise("user_id must be a non-empty string") if (!user_id.is_a? String) || user_id.to_s.empty?
|
347
369
|
raise("Bad api_key parameter") if api_key.empty?
|
@@ -349,6 +371,9 @@ module Sift
|
|
349
371
|
query = {}
|
350
372
|
query["api_key"] = api_key
|
351
373
|
query["abuse_types"] = abuse_types.join(",") if abuse_types
|
374
|
+
if include_score_percentiles == "true"
|
375
|
+
query["fields"] = "SCORE_PERCENTILES"
|
376
|
+
end
|
352
377
|
|
353
378
|
options = {
|
354
379
|
:headers => {"User-Agent" => user_agent},
|
data/lib/sift/version.rb
CHANGED
data/spec/unit/client_spec.rb
CHANGED
@@ -110,6 +110,69 @@ describe Sift::Client do
|
|
110
110
|
}
|
111
111
|
end
|
112
112
|
|
113
|
+
def warnings
|
114
|
+
{
|
115
|
+
:count => 1,
|
116
|
+
:items => [{
|
117
|
+
:message => 'Invalid currency'
|
118
|
+
}]
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
def percentile_response_json
|
123
|
+
{
|
124
|
+
:user_id => 'billy_jones_301',
|
125
|
+
:latest_labels => {},
|
126
|
+
:workflow_statuses => [],
|
127
|
+
:scores => {
|
128
|
+
:account_abuse => {
|
129
|
+
:score => 0.32787917675535705,
|
130
|
+
:reasons => [{
|
131
|
+
:name => 'Latest item product title',
|
132
|
+
:value => 'The Slanket Blanket-Texas Tea'
|
133
|
+
}],
|
134
|
+
:percentiles => {
|
135
|
+
:last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
|
136
|
+
}
|
137
|
+
},
|
138
|
+
:acontent_abuse => {
|
139
|
+
:score => 0.28056292905897995,
|
140
|
+
:reasons => [{
|
141
|
+
:name => 'timeSinceFirstEvent',
|
142
|
+
:value => '13.15 minutes'
|
143
|
+
}],
|
144
|
+
:percentiles => {
|
145
|
+
:last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
|
146
|
+
}
|
147
|
+
},
|
148
|
+
:payment_abuse => {
|
149
|
+
:score => 0.28610507028376797,
|
150
|
+
:reasons => [{
|
151
|
+
:name => 'Latest item currency code',
|
152
|
+
:value => 'USD'
|
153
|
+
}, {
|
154
|
+
:name => 'Latest item item ID',
|
155
|
+
:value => 'B004834GQO'
|
156
|
+
}, {
|
157
|
+
:name => 'Latest item product title',
|
158
|
+
:value => 'The Slanket Blanket-Texas Tea'
|
159
|
+
}],
|
160
|
+
:percentiles => {
|
161
|
+
:last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
|
162
|
+
}
|
163
|
+
},
|
164
|
+
:promotion_abuse => {
|
165
|
+
:score => 0.05731508921450917,
|
166
|
+
:percentiles => {
|
167
|
+
:last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
|
168
|
+
}
|
169
|
+
}
|
170
|
+
},
|
171
|
+
:status => 0,
|
172
|
+
:error_message => 'OK'
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
113
176
|
def fully_qualified_api_endpoint
|
114
177
|
Sift::Client::API_ENDPOINT + Sift.rest_api_path
|
115
178
|
end
|
@@ -554,4 +617,106 @@ describe Sift::Client do
|
|
554
617
|
expect(response.body["decisions"]["content_abuse"]["decision"]["id"]).to eq("decision7")
|
555
618
|
end
|
556
619
|
|
620
|
+
it "Successfully submits a v205 event with SCORE_PERCENTILES" do
|
621
|
+
response_json =
|
622
|
+
{ :status => 0, :error_message => "OK", :score_response => percentile_response_json}
|
623
|
+
stub_request(:post, "https://api.siftscience.com/v205/events?fields=SCORE_PERCENTILES&return_score=true").
|
624
|
+
with { | request|
|
625
|
+
parsed_body = JSON.parse(request.body)
|
626
|
+
expect(parsed_body).to include("$api_key" => "overridden")
|
627
|
+
}.to_return(:status => 200, :body => MultiJson.dump(response_json), :headers => {})
|
628
|
+
|
629
|
+
api_key = "foobar"
|
630
|
+
event = "$transaction"
|
631
|
+
properties = valid_transaction_properties
|
632
|
+
|
633
|
+
response = Sift::Client.new(:api_key => api_key, :version => "205")
|
634
|
+
.track(event, properties, :api_key => "overridden", :include_score_percentiles => "true", :return_score => "true")
|
635
|
+
expect(response.ok?).to eq(true)
|
636
|
+
expect(response.api_status).to eq(0)
|
637
|
+
expect(response.api_error_message).to eq("OK")
|
638
|
+
expect(response.body["score_response"]["scores"]["account_abuse"]["percentiles"]["last_7_days"]).to eq(-1.0)
|
639
|
+
end
|
640
|
+
|
641
|
+
it "Successfully submits a v205 event with SCORE_PERCENTILES" do
|
642
|
+
response_json =
|
643
|
+
{ :status => 0, :error_message => "OK", :score_response => percentile_response_json}
|
644
|
+
stub_request(:post, "https://api.siftscience.com/v205/events?fields=SCORE_PERCENTILES&return_score=true").
|
645
|
+
with { | request|
|
646
|
+
parsed_body = JSON.parse(request.body)
|
647
|
+
expect(parsed_body).to include("$api_key" => "overridden")
|
648
|
+
}.to_return(:status => 200, :body => MultiJson.dump(response_json), :headers => {})
|
649
|
+
|
650
|
+
api_key = "foobar"
|
651
|
+
event = "$transaction"
|
652
|
+
properties = valid_transaction_properties
|
653
|
+
|
654
|
+
response = Sift::Client.new(:api_key => api_key, :version => "205")
|
655
|
+
.track(event, properties, :api_key => "overridden", :include_score_percentiles => "true", :return_score => "true")
|
656
|
+
expect(response.ok?).to eq(true)
|
657
|
+
expect(response.api_status).to eq(0)
|
658
|
+
expect(response.api_error_message).to eq("OK")
|
659
|
+
expect(response.body["score_response"]["scores"]["account_abuse"]["percentiles"]["last_7_days"]).to eq(-1.0)
|
660
|
+
end
|
661
|
+
|
662
|
+
it "Successfully fetches a v205 score with SCORE_PERCENTILES" do
|
663
|
+
|
664
|
+
api_key = "foobar"
|
665
|
+
response_json = score_response_json
|
666
|
+
|
667
|
+
stub_request(:get, "https://api.siftscience.com/v205/score/247019/?api_key=foobar&fields=SCORE_PERCENTILES")
|
668
|
+
.to_return(:status => 200, :body => MultiJson.dump(response_json),
|
669
|
+
:headers => {"content-type"=>"application/json; charset=UTF-8",
|
670
|
+
"content-length"=> "74"})
|
671
|
+
|
672
|
+
response = Sift::Client.new(:api_key => api_key)
|
673
|
+
.score(score_response_json[:user_id], :version => 205, :include_score_percentiles => "true")
|
674
|
+
expect(response.ok?).to eq(true)
|
675
|
+
expect(response.api_status).to eq(0)
|
676
|
+
expect(response.api_error_message).to eq("OK")
|
677
|
+
|
678
|
+
expect(response.body["score"]).to eq(0.93)
|
679
|
+
end
|
680
|
+
|
681
|
+
it "Successfully executes client.get_user_score() with SCORE_PERCENTILES" do
|
682
|
+
|
683
|
+
api_key = "foobar"
|
684
|
+
response_json = user_score_response_json
|
685
|
+
|
686
|
+
stub_request(:get, "https://api.siftscience.com/v205/users/247019/score?api_key=foobar&fields=SCORE_PERCENTILES")
|
687
|
+
.to_return(:status => 200, :body => MultiJson.dump(response_json),
|
688
|
+
:headers => {"content-type"=>"application/json; charset=UTF-8",
|
689
|
+
"content-length"=> "74"})
|
690
|
+
|
691
|
+
response = Sift::Client.new(:api_key => api_key)
|
692
|
+
.get_user_score(user_score_response_json[:entity_id], :include_score_percentiles => "true")
|
693
|
+
expect(response.ok?).to eq(true)
|
694
|
+
expect(response.api_status).to eq(0)
|
695
|
+
expect(response.api_error_message).to eq("OK")
|
696
|
+
|
697
|
+
expect(response.body["entity_id"]).to eq("247019")
|
698
|
+
expect(response.body["scores"]["payment_abuse"]["score"]).to eq(0.78)
|
699
|
+
end
|
700
|
+
|
701
|
+
it "Successfully submits a v205 event with WARNINGS" do
|
702
|
+
response_json =
|
703
|
+
{ :status => 0, :error_message => "OK", :warnings => warnings}
|
704
|
+
stub_request(:post, "https://api.siftscience.com/v205/events?fields=WARNINGS").
|
705
|
+
with { | request|
|
706
|
+
parsed_body = JSON.parse(request.body)
|
707
|
+
expect(parsed_body).to include("$api_key" => "overridden")
|
708
|
+
}.to_return(:status => 200, :body => MultiJson.dump(response_json), :headers => {})
|
709
|
+
|
710
|
+
api_key = "foobar"
|
711
|
+
event = "$transaction"
|
712
|
+
properties = valid_transaction_properties
|
713
|
+
|
714
|
+
response = Sift::Client.new(:api_key => api_key, :version => "205")
|
715
|
+
.track(event, properties, :api_key => "overridden",:warnings => "true")
|
716
|
+
expect(response.ok?).to eq(true)
|
717
|
+
expect(response.api_status).to eq(0)
|
718
|
+
expect(response.api_error_message).to eq("OK")
|
719
|
+
expect(response.body["warnings"]["count"]).to eq(1)
|
720
|
+
expect(response.body["warnings"]["items"][0]["message"]).to eq("Invalid currency")
|
721
|
+
end
|
557
722
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "sift"
|
2
|
+
|
3
|
+
class DecisionAPI
|
4
|
+
|
5
|
+
@@client = Sift::Client.new(:api_key => ENV["API_KEY"], :account_id => ENV["ACCOUNT_ID"])
|
6
|
+
|
7
|
+
def apply_user_decision()
|
8
|
+
properties = {
|
9
|
+
"decision_id": "integration_app_watch_account_abuse",
|
10
|
+
"description": "User linked to three other payment abusers and ordering high value items",
|
11
|
+
"source": "manual_review",
|
12
|
+
"analyst": "analyst@example.com",
|
13
|
+
"user_id": "userId"
|
14
|
+
}
|
15
|
+
|
16
|
+
return @@client.apply_decision(properties)
|
17
|
+
end
|
18
|
+
|
19
|
+
def apply_order_decision()
|
20
|
+
properties = {
|
21
|
+
"decision_id": "block_order_payment_abuse",
|
22
|
+
"description": "applied via the high priority queue, queued user because their risk score exceeded 85",
|
23
|
+
"source": "AUTOMATED_RULE",
|
24
|
+
"user_id": "userId",
|
25
|
+
"order_id": "orderId"
|
26
|
+
}
|
27
|
+
|
28
|
+
return @@client.apply_decision(properties)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|