sift 4.2.0 → 4.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf4d6cd2e8ea54d5ea80fdca8b5668a1f86aa2639eaa1b69a105e8e81dd31222
4
- data.tar.gz: cd087556fba6bbfd8269366fb8a7ae1c4727841a184056f09406a9c6d78658f5
3
+ metadata.gz: 3ba7bb7dc985a6f320db6c39717c90e349a16306ec2b85f7a2ba28945c5e2f64
4
+ data.tar.gz: 8665633d78bb4c9502443f241943d4fb98015ede3060d233913169f5921d528b
5
5
  SHA512:
6
- metadata.gz: 66a74c28328b082be3b0f492f0f001c998a7bc99bd95ede179a4c950974b332b4b55158cf418677ce4b904307464912f3248a56b200b88bb76038fd38cdff281
7
- data.tar.gz: e6bb108cbcbf692266ff6d87a0a426476e8ad0a4523a2436a9f3d6f201ceeab63baad1121466e6a1ef7ec16df7135a577e59e532fe3d463ea47c6c7f47955576
6
+ metadata.gz: 75ce0e5c6631fbd4aa22ad72cb2ad9cebc0cf5ee0ec7e7de1dc308d9d90d3c1ef288a75a699ac0ef04ae650700a4a7b63ad1ece30d1386da0c06ceefcea10420
7
+ data.tar.gz: 3804c62aaf0795bfce7eadc4d048ae36d3a67a0d1dd9c81548d31926f950a5908a4fb158a8363182bb14ebb77545d3c671b37292802c093ea31719176683bb26
@@ -0,0 +1,38 @@
1
+ name: Build and Publish Gem
2
+ on:
3
+ release:
4
+ types: [published]
5
+
6
+ env:
7
+ GH_TOKEN: ${{ github.token }}
8
+
9
+ jobs:
10
+ build_and_publish:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v3
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: 2.7
19
+ - name: Install Bundler
20
+ run: |
21
+ sudo gem install bundler
22
+ bundle install
23
+ - name: Build and push gem
24
+ run: |
25
+ mkdir -p $HOME/.gem
26
+ touch $HOME/.gem/credentials
27
+ chmod 0600 $HOME/.gem/credentials
28
+ printf -- "---\n:rubygems_api_key: ${{ secrets.GH_RGEMS_KEY }}\n" > $HOME/.gem/credentials
29
+ version=$(awk -F'"' '/ VERSION = / {print $2}' < lib/sift/version.rb)
30
+ all_versions=$(gem list -r -e --all sift --no-verbose)
31
+ if [[ $all_versions != *"$version"* ]]; then
32
+ echo "Gem version does not exist on RubyGems. Building and pushing!"
33
+ gem build sift.gemspec
34
+ gem push sift-$version.gem
35
+ rm -rf $HOME/.gem
36
+ else
37
+ echo "Gem version $version exists on RubyGems"
38
+ fi
data/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  .bundle
4
4
  Gemfile.lock
5
5
  pkg/*
6
+ .idea
data/HISTORY CHANGED
@@ -1,3 +1,9 @@
1
+ === 4.4.0 2023-10-05
2
+ - Score percentiles in Score API
3
+
4
+ === 4.3.0 2023-08-21
5
+ - PSP Merchant Management API
6
+
1
7
  === 4.2.0 2023-06-20
2
8
  - Verification API support [Verification API](https://sift.com/developers/docs/curl/verification-api/overview)
3
9
  - Support for score percentiles (only applicable for the accounts with the feature enabled)
data/README.md CHANGED
@@ -217,6 +217,72 @@ response = client.get_session_decisions('example_user_id', 'example_session_id')
217
217
  response = client.get_content_decisions('example_user_id', 'example_order_id')
218
218
  ```
219
219
 
220
+ ## PSP Merchant Management API
221
+
222
+ To learn more about the decisions endpoint visit our [developer docs](https://sift.com/developers/docs/ruby/psp-merchant-management-api).
223
+
224
+ ```ruby
225
+ # On-board a PSP merchant summary to Sift Platform.
226
+ # Sample psp_merchant_profile
227
+ properties = {
228
+ "id": "merchant_id_01000",
229
+ "name": "Wonderful Payments Inc.",
230
+ "description": "Wonderful Payments payment provider.",
231
+ "address": {
232
+ "name": "Alany",
233
+ "address_1": "Big Payment blvd, 22",
234
+ "address_2": "apt, 8",
235
+ "city": "New Orleans",
236
+ "region": "NA",
237
+ "country": "US",
238
+ "zipcode": "76830",
239
+ "phone": "0394888320"
240
+ },
241
+ "category": "1002",
242
+ "service_level": "Platinum",
243
+ "status": "active",
244
+ "risk_profile": {
245
+ "level": "low",
246
+ "score": 10
247
+ }
248
+ }
249
+ response = client.create_psp_merchant_profile(properties)
250
+
251
+ # Update a merchant summary to reflect changes in the status or service level or address etc.
252
+ properties = {
253
+ "id": "merchant_id_01000",
254
+ "name": "Wonderful Payments Inc.",
255
+ "description": "Wonderful Payments payment provider.",
256
+ "address": {
257
+ "name": "Alany",
258
+ "address_1": "Big Payment blvd, 22",
259
+ "address_2": "apt, 8",
260
+ "city": "New Orleans",
261
+ "region": "NA",
262
+ "country": "US",
263
+ "zipcode": "76830",
264
+ "phone": "0394888320"
265
+ },
266
+ "category": "1002",
267
+ "service_level": "Platinum",
268
+ "status": "active",
269
+ "risk_profile": {
270
+ "level": "low",
271
+ "score": 10
272
+ }
273
+ }
274
+ response = client.update_psp_merchant_profile('merchant_id', properties)
275
+
276
+ # Get the existing PSP merchant summaries.
277
+ response = client.get_a_psp_merchant_profile('merchant_id')
278
+
279
+ # Get all PSP merchant summaries
280
+ response = client.get_psp_merchant_profiles()
281
+
282
+ # Get PSP merchant summaries paginated
283
+ response = client.get_psp_merchant_profiles('batch_size', 'batch_token')
284
+ ```
285
+
220
286
  ## Response Object
221
287
 
222
288
  All requests to our apis will return a `Response` instance.
@@ -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"
data/lib/sift/client.rb CHANGED
@@ -201,6 +201,9 @@ 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.
204
207
  #
205
208
  # ==== Returns:
206
209
  #
@@ -275,6 +278,9 @@ module Sift
275
278
  #
276
279
  # :version::
277
280
  # Overrides the version of the Events API to call.
281
+ #
282
+ # :include_score_percentiles::
283
+ # include_score_percentiles(optional) : Whether to add new parameter in the query parameter.
278
284
  #
279
285
  # ==== Returns:
280
286
  #
@@ -286,6 +292,7 @@ module Sift
286
292
  api_key = opts[:api_key] || @api_key
287
293
  timeout = opts[:timeout] || @timeout
288
294
  version = opts[:version] || @version
295
+ include_score_percentiles = opts[:include_score_percentiles]
289
296
 
290
297
  raise("user_id must be a non-empty string") if (!user_id.is_a? String) || user_id.to_s.empty?
291
298
  raise("Bad api_key parameter") if api_key.empty?
@@ -293,6 +300,9 @@ module Sift
293
300
  query = {}
294
301
  query["api_key"] = api_key
295
302
  query["abuse_types"] = abuse_types.join(",") if abuse_types
303
+ if include_score_percentiles == "true"
304
+ query["fields"] = "SCORE_PERCENTILES"
305
+ end
296
306
 
297
307
  options = {
298
308
  :headers => {"User-Agent" => user_agent},
@@ -332,6 +342,9 @@ module Sift
332
342
  #
333
343
  # :timeout::
334
344
  # Overrides the timeout (in seconds) for this call.
345
+ #
346
+ # :include_score_percentiles::
347
+ # include_score_percentiles(optional) : Whether to add new parameter in the query parameter.
335
348
  #
336
349
  # ==== Returns:
337
350
  #
@@ -342,6 +355,7 @@ module Sift
342
355
  abuse_types = opts[:abuse_types]
343
356
  api_key = opts[:api_key] || @api_key
344
357
  timeout = opts[:timeout] || @timeout
358
+ include_score_percentiles = opts[:include_score_percentiles]
345
359
 
346
360
  raise("user_id must be a non-empty string") if (!user_id.is_a? String) || user_id.to_s.empty?
347
361
  raise("Bad api_key parameter") if api_key.empty?
@@ -349,6 +363,9 @@ module Sift
349
363
  query = {}
350
364
  query["api_key"] = api_key
351
365
  query["abuse_types"] = abuse_types.join(",") if abuse_types
366
+ if include_score_percentiles == "true"
367
+ query["fields"] = "SCORE_PERCENTILES"
368
+ end
352
369
 
353
370
  options = {
354
371
  :headers => {"User-Agent" => user_agent},
@@ -785,6 +802,111 @@ module Sift
785
802
  Response.new(response.body, response.code, response.response)
786
803
  end
787
804
 
805
+ def create_psp_merchant_profile(properties = {}, opts = {})
806
+ # Create a new PSP Merchant profile
807
+ # Args:
808
+ # properties: A dict of merchant profile data.
809
+ # Returns
810
+ # A sift.client.Response object if the call succeeded, else raises an ApiException
811
+
812
+ account_id = opts[:account_id] || @account_id
813
+ api_key = opts[:api_key] || @api_key
814
+ timeout = opts[:timeout] || @timeout
815
+
816
+ raise("api_key cannot be empty") if api_key.empty?
817
+ raise("account_id cannot be empty") if account_id.empty?
818
+ raise("properties cannot be empty") if properties.empty?
819
+
820
+ options = {
821
+ :body => MultiJson.dump(delete_nils(properties)),
822
+ :headers => { "User-Agent" => user_agent, "Content-Type" => "application/json" },
823
+ :basic_auth => { :username => api_key, :password => "" }
824
+ }
825
+ options.merge!(:timeout => timeout) unless timeout.nil?
826
+ response = self.class.post(API_ENDPOINT + Sift.psp_merchant_api_path(account_id), options)
827
+ Response.new(response.body, response.code, response.response)
828
+ end
829
+
830
+ def update_psp_merchant_profile(merchant_id, properties = {}, opts = {})
831
+ # Update an existing PSP Merchant profile
832
+ # Args:
833
+ # merchant_id: id of merchant
834
+ # properties: A dict of merchant profile data.
835
+ # Returns
836
+ # A sift.client.Response object if the call succeeded, else raises an ApiException
837
+
838
+ account_id = opts[:account_id] || @account_id
839
+ api_key = opts[:api_key] || @api_key
840
+ timeout = opts[:timeout] || @timeout
841
+
842
+ raise("api_key cannot be empty") if api_key.empty?
843
+ raise("account_id cannot be empty") if account_id.empty?
844
+ raise("merchant_id cannot be empty") if merchant_id.empty?
845
+ raise("properties cannot be empty") if properties.empty?
846
+
847
+ options = {
848
+ :body => MultiJson.dump(delete_nils(properties)),
849
+ :headers => { "User-Agent" => user_agent, "Content-Type" => "application/json" },
850
+ :basic_auth => { :username => api_key, :password => "" }
851
+ }
852
+ options.merge!(:timeout => timeout) unless timeout.nil?
853
+ response = self.class.put(API_ENDPOINT + Sift.psp_merchant_id_api_path(account_id, merchant_id), options)
854
+ Response.new(response.body, response.code, response.response)
855
+ end
856
+
857
+ def get_a_psp_merchant_profile(merchant_id, opts = {})
858
+ # Gets a PSP merchant profile using merchant id.
859
+ # Args:
860
+ # merchant_id: id of merchant
861
+ # Returns
862
+ # A sift.client.Response object if the call succeeded, else raises an ApiException
863
+
864
+ account_id = opts[:account_id] || @account_id
865
+ api_key = opts[:api_key] || @api_key
866
+ timeout = opts[:timeout] || @timeout
867
+
868
+ raise("api_key cannot be empty") if api_key.empty?
869
+ raise("account_id cannot be empty") if account_id.empty?
870
+ raise("merchant_id cannot be empty") if merchant_id.empty?
871
+
872
+ options = {
873
+ :headers => { "User-Agent" => user_agent, "Content-Type" => "application/json" },
874
+ :basic_auth => { :username => api_key, :password => "" }
875
+ }
876
+ options.merge!(:timeout => timeout) unless timeout.nil?
877
+ response = self.class.get(API_ENDPOINT + Sift.psp_merchant_id_api_path(account_id, merchant_id), options)
878
+ Response.new(response.body, response.code, response.response)
879
+ end
880
+
881
+ def get_psp_merchant_profiles(batch_size = nil, batch_token = nil, opts = {})
882
+ # Get all PSP merchant profiles.
883
+ # Args:
884
+ # batch_size : Batch or page size of the paginated sequence.
885
+ # batch_token : Batch or page position of the paginated sequence.
886
+ # Returns
887
+ # A sift.client.Response object if the call succeeded, else raises an ApiException
888
+
889
+ account_id = opts[:account_id] || @account_id
890
+ api_key = opts[:api_key] || @api_key
891
+ timeout = opts[:timeout] || @timeout
892
+
893
+ raise("api_key cannot be empty") if api_key.empty?
894
+ raise("account_id cannot be empty") if account_id.empty?
895
+
896
+ query = {}
897
+ query["batch_size"] = batch_size if batch_size
898
+ query["batch_token"] = batch_token if batch_token
899
+
900
+ options = {
901
+ :headers => { "User-Agent" => user_agent, "Content-Type" => "application/json" },
902
+ :basic_auth => { :username => api_key, :password => "" },
903
+ :query => query
904
+ }
905
+ options.merge!(:timeout => timeout) unless timeout.nil?
906
+ response = self.class.get(API_ENDPOINT + Sift.psp_merchant_api_path(account_id), options)
907
+ Response.new(response.body, response.code, response.response)
908
+ end
909
+
788
910
  private
789
911
 
790
912
  def handle_response(response)
data/lib/sift/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Sift
2
- VERSION = "4.2.0"
2
+ VERSION = "4.4.0"
3
3
  API_VERSION = "205"
4
4
  end
data/lib/sift.rb CHANGED
@@ -71,6 +71,18 @@ module Sift
71
71
  "/content/#{ERB::Util.url_encode(content_id)}/decisions"
72
72
  end
73
73
 
74
+ # Returns the path for psp Merchant API
75
+ def self.psp_merchant_api_path(account_id)
76
+ "/v3/accounts/#{ERB::Util.url_encode(account_id)}" \
77
+ "/psp_management/merchants"
78
+ end
79
+
80
+ # Returns the path for psp Merchant with id
81
+ def self.psp_merchant_id_api_path(account_id, merchant_id)
82
+ "/v3/accounts/#{ERB::Util.url_encode(account_id)}" \
83
+ "/psp_management/merchants/#{ERB::Util.url_encode(merchant_id)}"
84
+ end
85
+
74
86
  # Module-scoped public API key
75
87
  class << self
76
88
  attr_accessor :api_key
@@ -0,0 +1,133 @@
1
+ require_relative "../spec_helper"
2
+ require "sift"
3
+
4
+ describe Sift::Client do
5
+
6
+ before :each do
7
+ Sift.api_key = nil
8
+ end
9
+
10
+ def post_psp_merchant_properties
11
+ {
12
+ "id": "api-key1-6",
13
+ "name": "Wonderful Payments Inc.",
14
+ "description": "Wonderful Payments payment provider.",
15
+ "address": {
16
+ "name": "Alany",
17
+ "address_1": "Big Payment blvd, 22",
18
+ "address_2": "apt, 8",
19
+ "city": "New Orleans",
20
+ "region": "NA",
21
+ "country": "US",
22
+ "zipcode": "76830",
23
+ "phone": "0394888320"
24
+ },
25
+ "category": "1002",
26
+ "service_level": "Platinum",
27
+ "status": "active",
28
+ "risk_profile": {
29
+ "level": "low",
30
+ "score": 10
31
+ }
32
+ }
33
+ end
34
+
35
+ def put_psp_merchant_properties
36
+ {
37
+ "id": "api-key1-7",
38
+ "name": "Wonderful Payments Inc.",
39
+ "description": "Wonderful Payments payment provider.",
40
+ "address": {
41
+ "name": "Alany",
42
+ "address_1": "Big Payment blvd, 22",
43
+ "address_2": "apt, 8",
44
+ "city": "New Orleans",
45
+ "region": "NA",
46
+ "country": "US",
47
+ "zipcode": "76830",
48
+ "phone": "0394888320"
49
+ },
50
+ "category": "1002",
51
+ "service_level": "Platinum",
52
+ "status": "active",
53
+ "risk_profile": {
54
+ "level": "low",
55
+ "score": 10
56
+ }
57
+ }
58
+ end
59
+
60
+ it "Successfully sumit create psp merchant" do
61
+ api_key = "foobar1"
62
+
63
+ response_json = { :status => 0, :error_message => "OK" }
64
+
65
+ stub_request(:post, "https://foobar1:@api.siftscience.com/v3/accounts/ACCT/psp_management/merchants")
66
+ .to_return(:status => 200, :body => MultiJson.dump(response_json))
67
+
68
+ response = Sift::Client.new(:api_key => api_key, :account_id => "ACCT").create_psp_merchant_profile(post_psp_merchant_properties)
69
+ expect(response.ok?).to eq(true)
70
+ expect(response.api_status).to eq(0)
71
+ expect(response.api_error_message).to eq("OK")
72
+ end
73
+
74
+ it "Successfully submit update psp merchant" do
75
+ api_key = "foobar1"
76
+ merchant_id = "api-key1-7"
77
+
78
+ response_json = { :status => 0, :error_message => "OK"}
79
+
80
+ stub_request(:put, "https://foobar1:@api.siftscience.com/v3/accounts/ACCT/psp_management/merchants/api-key1-7")
81
+ .to_return(:status => 200, :body => MultiJson.dump(response_json))
82
+
83
+ response = Sift::Client.new(:api_key => api_key, :account_id => "ACCT").update_psp_merchant_profile(merchant_id, put_psp_merchant_properties)
84
+ expect(response.ok?).to eq(true)
85
+ expect(response.api_status).to eq(0)
86
+ expect(response.api_error_message).to eq("OK")
87
+ end
88
+
89
+ it "Successfully get a psp merchant profile" do
90
+ api_key = "foobar1"
91
+ merchant_id = "api-key1-7"
92
+
93
+ response_json = { :status => 0, :error_message => "OK"}
94
+
95
+ stub_request(:get, "https://foobar1:@api.siftscience.com/v3/accounts/ACCT/psp_management/merchants/api-key1-7")
96
+ .to_return(:status => 200, :body => MultiJson.dump(response_json))
97
+
98
+ response = Sift::Client.new(:api_key => api_key, :account_id => "ACCT").get_a_psp_merchant_profile(merchant_id)
99
+ expect(response.ok?).to eq(true)
100
+ expect(response.api_status).to eq(0)
101
+ expect(response.api_error_message).to eq("OK")
102
+ end
103
+
104
+ it "Successfully get all psp merchant profile with batch size" do
105
+ api_key = "foobar1"
106
+
107
+ response_json = { :status => 0, :error_message => "OK"}
108
+
109
+ stub_request(:get, "https://foobar1:@api.siftscience.com/v3/accounts/ACCT/psp_management/merchants?batch_size=2")
110
+ .to_return(:status => 200, :body => MultiJson.dump(response_json))
111
+
112
+ response = Sift::Client.new(:api_key => api_key, :account_id => "ACCT").get_psp_merchant_profiles(2)
113
+ expect(response.ok?).to eq(true)
114
+ expect(response.api_status).to eq(0)
115
+ expect(response.api_error_message).to eq("OK")
116
+ end
117
+
118
+ it "Successfully get all psp merchant profile with batch size and batch token" do
119
+ api_key = "foobar1"
120
+ batch_size = 2
121
+ batch_token = "batch_token"
122
+ response_json = { :status => 0, :error_message => "OK"}
123
+
124
+ stub_request(:get, "https://foobar1:@api.siftscience.com/v3/accounts/ACCT/psp_management/merchants?batch_size=2&batch_token=batch_token")
125
+ .to_return(:status => 200, :body => MultiJson.dump(response_json))
126
+
127
+ response = Sift::Client.new(:api_key => api_key, :account_id => "ACCT").get_psp_merchant_profiles(batch_size, batch_token)
128
+ expect(response.ok?).to eq(true)
129
+ expect(response.api_status).to eq(0)
130
+ expect(response.api_error_message).to eq("OK")
131
+ end
132
+
133
+ end
@@ -110,6 +110,60 @@ describe Sift::Client do
110
110
  }
111
111
  end
112
112
 
113
+ def percentile_response_json
114
+ {
115
+ :user_id => 'billy_jones_301',
116
+ :latest_labels => {},
117
+ :workflow_statuses => [],
118
+ :scores => {
119
+ :account_abuse => {
120
+ :score => 0.32787917675535705,
121
+ :reasons => [{
122
+ :name => 'Latest item product title',
123
+ :value => 'The Slanket Blanket-Texas Tea'
124
+ }],
125
+ :percentiles => {
126
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
127
+ }
128
+ },
129
+ :acontent_abuse => {
130
+ :score => 0.28056292905897995,
131
+ :reasons => [{
132
+ :name => 'timeSinceFirstEvent',
133
+ :value => '13.15 minutes'
134
+ }],
135
+ :percentiles => {
136
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
137
+ }
138
+ },
139
+ :payment_abuse => {
140
+ :score => 0.28610507028376797,
141
+ :reasons => [{
142
+ :name => 'Latest item currency code',
143
+ :value => 'USD'
144
+ }, {
145
+ :name => 'Latest item item ID',
146
+ :value => 'B004834GQO'
147
+ }, {
148
+ :name => 'Latest item product title',
149
+ :value => 'The Slanket Blanket-Texas Tea'
150
+ }],
151
+ :percentiles => {
152
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
153
+ }
154
+ },
155
+ :promotion_abuse => {
156
+ :score => 0.05731508921450917,
157
+ :percentiles => {
158
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
159
+ }
160
+ }
161
+ },
162
+ :status => 0,
163
+ :error_message => 'OK'
164
+ }
165
+ end
166
+
113
167
  def fully_qualified_api_endpoint
114
168
  Sift::Client::API_ENDPOINT + Sift.rest_api_path
115
169
  end
@@ -554,4 +608,85 @@ describe Sift::Client do
554
608
  expect(response.body["decisions"]["content_abuse"]["decision"]["id"]).to eq("decision7")
555
609
  end
556
610
 
611
+ it "Successfully submits a v205 event with SCORE_PERCENTILES" do
612
+ response_json =
613
+ { :status => 0, :error_message => "OK", :score_response => percentile_response_json}
614
+ stub_request(:post, "https://api.siftscience.com/v205/events?fields=SCORE_PERCENTILES&return_score=true").
615
+ with { | request|
616
+ parsed_body = JSON.parse(request.body)
617
+ expect(parsed_body).to include("$api_key" => "overridden")
618
+ }.to_return(:status => 200, :body => MultiJson.dump(response_json), :headers => {})
619
+
620
+ api_key = "foobar"
621
+ event = "$transaction"
622
+ properties = valid_transaction_properties
623
+
624
+ response = Sift::Client.new(:api_key => api_key, :version => "205")
625
+ .track(event, properties, :api_key => "overridden", :include_score_percentiles => "true", :return_score => "true")
626
+ expect(response.ok?).to eq(true)
627
+ expect(response.api_status).to eq(0)
628
+ expect(response.api_error_message).to eq("OK")
629
+ expect(response.body["score_response"]["scores"]["account_abuse"]["percentiles"]["last_7_days"]).to eq(-1.0)
630
+ end
631
+
632
+ it "Successfully submits a v205 event with SCORE_PERCENTILES" do
633
+ response_json =
634
+ { :status => 0, :error_message => "OK", :score_response => percentile_response_json}
635
+ stub_request(:post, "https://api.siftscience.com/v205/events?fields=SCORE_PERCENTILES&return_score=true").
636
+ with { | request|
637
+ parsed_body = JSON.parse(request.body)
638
+ expect(parsed_body).to include("$api_key" => "overridden")
639
+ }.to_return(:status => 200, :body => MultiJson.dump(response_json), :headers => {})
640
+
641
+ api_key = "foobar"
642
+ event = "$transaction"
643
+ properties = valid_transaction_properties
644
+
645
+ response = Sift::Client.new(:api_key => api_key, :version => "205")
646
+ .track(event, properties, :api_key => "overridden", :include_score_percentiles => "true", :return_score => "true")
647
+ expect(response.ok?).to eq(true)
648
+ expect(response.api_status).to eq(0)
649
+ expect(response.api_error_message).to eq("OK")
650
+ expect(response.body["score_response"]["scores"]["account_abuse"]["percentiles"]["last_7_days"]).to eq(-1.0)
651
+ end
652
+
653
+ it "Successfully fetches a v205 score with SCORE_PERCENTILES" do
654
+
655
+ api_key = "foobar"
656
+ response_json = score_response_json
657
+
658
+ stub_request(:get, "https://api.siftscience.com/v205/score/247019/?api_key=foobar&fields=SCORE_PERCENTILES")
659
+ .to_return(:status => 200, :body => MultiJson.dump(response_json),
660
+ :headers => {"content-type"=>"application/json; charset=UTF-8",
661
+ "content-length"=> "74"})
662
+
663
+ response = Sift::Client.new(:api_key => api_key)
664
+ .score(score_response_json[:user_id], :version => 205, :include_score_percentiles => "true")
665
+ expect(response.ok?).to eq(true)
666
+ expect(response.api_status).to eq(0)
667
+ expect(response.api_error_message).to eq("OK")
668
+
669
+ expect(response.body["score"]).to eq(0.93)
670
+ end
671
+
672
+ it "Successfully executes client.get_user_score() with SCORE_PERCENTILES" do
673
+
674
+ api_key = "foobar"
675
+ response_json = user_score_response_json
676
+
677
+ stub_request(:get, "https://api.siftscience.com/v205/users/247019/score?api_key=foobar&fields=SCORE_PERCENTILES")
678
+ .to_return(:status => 200, :body => MultiJson.dump(response_json),
679
+ :headers => {"content-type"=>"application/json; charset=UTF-8",
680
+ "content-length"=> "74"})
681
+
682
+ response = Sift::Client.new(:api_key => api_key)
683
+ .get_user_score(user_score_response_json[:entity_id], :include_score_percentiles => "true")
684
+ expect(response.ok?).to eq(true)
685
+ expect(response.api_status).to eq(0)
686
+ expect(response.api_error_message).to eq("OK")
687
+
688
+ expect(response.body["entity_id"]).to eq("247019")
689
+ expect(response.body["scores"]["payment_abuse"]["score"]).to eq(0.78)
690
+ end
691
+
557
692
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sift
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Sadaghiani
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-07-07 00:00:00.000000000 Z
13
+ date: 2023-10-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -125,12 +125,14 @@ extra_rdoc_files: []
125
125
  files:
126
126
  - ".circleci/config.yml"
127
127
  - ".github/pull_request_template.md"
128
+ - ".github/workflows/publishing_sift_ruby.yml"
128
129
  - ".gitignore"
129
130
  - Gemfile
130
131
  - HISTORY
131
132
  - LICENSE
132
133
  - README.md
133
134
  - Rakefile
135
+ - examples/psp_merchant_management_apis.rb
134
136
  - examples/simple.rb
135
137
  - examples/validation_apis.rb
136
138
  - lib/sift.rb
@@ -152,6 +154,7 @@ files:
152
154
  - spec/unit/client_203_spec.rb
153
155
  - spec/unit/client_205_spec.rb
154
156
  - spec/unit/client_label_spec.rb
157
+ - spec/unit/client_psp_merchant_spec.rb
155
158
  - spec/unit/client_spec.rb
156
159
  - spec/unit/client_validationapi_spec.rb
157
160
  - spec/unit/router_spec.rb
@@ -175,21 +178,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
178
  - !ruby/object:Gem::Version
176
179
  version: '0'
177
180
  requirements: []
178
- rubygems_version: 3.0.3.1
181
+ rubygems_version: 3.1.6
179
182
  signing_key:
180
183
  specification_version: 4
181
184
  summary: Sift Science Ruby API Gem
182
- test_files:
183
- - spec/fixtures/fake_responses.rb
184
- - spec/integration/sift_spec.rb
185
- - spec/spec_helper.rb
186
- - spec/unit/client/decision/apply_to_spec.rb
187
- - spec/unit/client/decision_spec.rb
188
- - spec/unit/client_203_spec.rb
189
- - spec/unit/client_205_spec.rb
190
- - spec/unit/client_label_spec.rb
191
- - spec/unit/client_spec.rb
192
- - spec/unit/client_validationapi_spec.rb
193
- - spec/unit/router_spec.rb
194
- - spec/unit/validate/decision_spec.rb
195
- - spec/unit/validate/primitive_spec.rb
185
+ test_files: []