sift 4.2.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
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: []