sift 4.1.0 → 4.3.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: 4b20b0230176dc6340e5ea4939e51b6e1ed2642e788c25fa2f7f4e829b5c61ff
4
- data.tar.gz: 28932a0fddd658fe868c6c6b6b408ab1d8529060cfbe0766ffeef76e2398e43e
3
+ metadata.gz: e538e799471ba36d0c73d8b6bdea81f56e5928ef018a01a8aa0d1d376151ba97
4
+ data.tar.gz: 7ba73b5ea722594550ce5fb2b9259c8728b6658ac393206f991ac182e6216fd1
5
5
  SHA512:
6
- metadata.gz: b905f6002c28777a4cf82cc6b0e59b2c79c300fdf1f4b4b3bf8b0bff8691946325d83794da812d5abc4b344b5e35d24f72b720aae1ddc0783b7e935117f35588
7
- data.tar.gz: e161d32f1c210f3fc4562b985537ceb6e2f304330a3fb14ddbce142cd105b0a0c567f6e177dd3c29c99e6c50133e3a7eb40c5ba922071914d9cf56b540c8f427
6
+ metadata.gz: d6a650d190c215fa627b364e134e51d35012edd1b40682c8d24e8ea446e7bbbcfc2121189d9ef1335a5f67ee5aeb4472c42823e99737bd5879ea14a51c4f0e2c
7
+ data.tar.gz: 1569ecf84bf4bfee1991a7664922293a24ab6993ac56766b28a10183cd8cc593641ff301c3e68fbdc1e8f2f51b3425b1ad64131332c12c4ded51489e54703eb3
data/.circleci/config.yml CHANGED
@@ -1,4 +1,40 @@
1
- version: 2
1
+ version: 2.1
2
+
3
+ orbs:
4
+ slack: circleci/slack@4.4.2
5
+
6
+ commands:
7
+ export_slack_id:
8
+ steps:
9
+ - run:
10
+ name : Exporting circleci username as slack id.
11
+ command: echo 'export SLACK_PARAM_MENTIONS="$CIRCLE_USERNAME"' >> "$BASH_ENV"
12
+ - run:
13
+ name : CircleCi To Slack user mapping.
14
+ command: |
15
+ echo $GITHUB_SLACK_USERMAPPING | base64 --decode > github_slack
16
+ while read -r line || [[ -n $line ]];
17
+ do
18
+ [[ ${line//[[:space:]]/} =~ ^#.* || -z "$line" ]] && continue
19
+ echo "$line" | tr "=" "\n" | while read -r key; do
20
+ read -r value
21
+ if [ "$CIRCLE_USERNAME" = "${key}" ]; then
22
+ echo "export SLACK_PARAM_MENTIONS='<@${value}>'" >> $BASH_ENV
23
+ fi
24
+ done
25
+ done < github_slack
26
+ rm github_slack
27
+
28
+ slack/notify: &slack_notify
29
+ branch_pattern: master
30
+ event: fail
31
+ channel: ci-build-status
32
+ template: SLACK_TAG_CI_FAILURE_TEMPLATE
33
+
34
+ context: &context
35
+ - slack-templates
36
+ - slack_Oauth
37
+ - Github_Slack_UserMapping
2
38
 
3
39
  jobs:
4
40
  build:
@@ -11,6 +47,7 @@ jobs:
11
47
  BUNDLE_PATH: vendor/bundle
12
48
  steps:
13
49
  - checkout
50
+ - export_slack_id
14
51
 
15
52
  - run:
16
53
  name: Which bundler?
@@ -41,3 +78,11 @@ jobs:
41
78
 
42
79
  - store_test_results:
43
80
  path: test_results
81
+ - slack/notify:
82
+ <<: *slack_notify
83
+
84
+ workflows:
85
+ ruby-test:
86
+ jobs:
87
+ - build:
88
+ context: *context
@@ -0,0 +1,12 @@
1
+ ## Purpose
2
+
3
+ ## Summary
4
+
5
+ ## Testing
6
+
7
+ ## Checklist
8
+ - [ ] The change was thoroughly tested manually
9
+ - [ ] The change was covered with unit tests
10
+ - [ ] The change was tested with real API calls (if applicable)
11
+ - [ ] Necessary changes were made in the integration tests (if applicable)
12
+ - [ ] New functionality is reflected in README
@@ -0,0 +1,50 @@
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
+
16
+
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: 2.7
21
+
22
+ - name: Install Bundler
23
+ run: |
24
+ sudo gem install bundler
25
+ bundle install
26
+
27
+ - name: Build and push gem
28
+ run: |
29
+ mkdir -p $HOME/.gem
30
+ touch $HOME/.gem/credentials
31
+ chmod 0600 $HOME/.gem/credentials
32
+ printf -- "---\n:rubygems_api_key: ${{ secrets.GH_RGEMS_KEY }}\n" > $HOME/.gem/credentials
33
+ version=$(awk -F'"' '/ VERSION = / {print $2}' < lib/sift/version.rb)
34
+ all_versions=$(gem list -r -e --all sift --no-verbose)
35
+ if [[ $all_versions != *"$version"* ]]; then
36
+ echo "Gem version does not exist on RubyGems. Building and pushing!"
37
+ gem build sift.gemspec
38
+ gem push sift-$version.gem
39
+ rm -rf $HOME/.gem
40
+ ls -la $HOME/
41
+ else
42
+ echo "Gem version $version exists on RubyGems"
43
+ 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
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,10 @@
1
+ === 4.3.0 2023-08-21
2
+ - PSP Merchant Management API
3
+
4
+ === 4.2.0 2023-06-20
5
+ - Verification API support [Verification API](https://sift.com/developers/docs/curl/verification-api/overview)
6
+ - Support for score percentiles (only applicable for the accounts with the feature enabled)
7
+
1
8
  === 4.1.0 2022-06-22
2
9
  - Add return_route_info query param
3
10
 
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"
@@ -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"
data/lib/sift/client.rb CHANGED
@@ -219,6 +219,7 @@ module Sift
219
219
  return_route_info = opts[:return_route_info]
220
220
  force_workflow_run = opts[:force_workflow_run]
221
221
  abuse_types = opts[:abuse_types]
222
+ include_score_percentiles = opts[:include_score_percentiles]
222
223
 
223
224
  raise("event must be a non-empty string") if (!event.is_a? String) || event.empty?
224
225
  raise("properties cannot be empty") if properties.empty?
@@ -231,6 +232,9 @@ module Sift
231
232
  query["return_route_info"] = "true" if return_route_info
232
233
  query["force_workflow_run"] = "true" if force_workflow_run
233
234
  query["abuse_types"] = abuse_types.join(",") if abuse_types
235
+ if include_score_percentiles == "true"
236
+ query["fields"] = "SCORE_PERCENTILES"
237
+ end
234
238
 
235
239
  options = {
236
240
  :body => MultiJson.dump(delete_nils(properties).merge({"$type" => event,
@@ -716,6 +720,176 @@ module Sift
716
720
  handle_response(apply_decision(configs))
717
721
  end
718
722
 
723
+ def build_default_headers_post(api_key)
724
+ {
725
+ "Authorization" => "Basic #{Base64.encode64(api_key+":")}",
726
+ "User-Agent" => "SiftScience/v#{@version} sift-ruby/#{VERSION}",
727
+ "Content-Type" => "application/json"
728
+ }
729
+ end
730
+
731
+ def verification_send(properties = {}, opts = {})
732
+ api_key = opts[:api_key] || @api_key
733
+ version = opts[:version] || @version
734
+ timeout = opts[:timeout] || @timeout
735
+
736
+ raise("properties cannot be empty") if properties.empty?
737
+ raise("api_key cannot be empty") if api_key.empty?
738
+
739
+
740
+ options = {
741
+ :body => MultiJson.dump(delete_nils(properties)),
742
+ :headers => build_default_headers_post(api_key)
743
+ }
744
+ options.merge!(:timeout => timeout) unless timeout.nil?
745
+
746
+ response = self.class.post(Sift.verification_api_send_path(@version), options)
747
+ Response.new(response.body, response.code, response.response)
748
+ end
749
+
750
+ def verification_resend(properties = {}, opts = {})
751
+ api_key = opts[:api_key] || @api_key
752
+ version = opts[:version] || @version
753
+ timeout = opts[:timeout] || @timeout
754
+
755
+ raise("properties cannot be empty") if properties.empty?
756
+ raise("api_key cannot be empty") if api_key.empty?
757
+
758
+
759
+ options = {
760
+ :body => MultiJson.dump(delete_nils(properties)),
761
+ :headers => build_default_headers_post(api_key)
762
+ }
763
+ options.merge!(:timeout => timeout) unless timeout.nil?
764
+
765
+ response = self.class.post(Sift.verification_api_resend_path(@version), options)
766
+ Response.new(response.body, response.code, response.response)
767
+ end
768
+
769
+ def verification_check(properties = {}, opts = {})
770
+ api_key = opts[:api_key] || @api_key
771
+ version = opts[:version] || @version
772
+ timeout = opts[:timeout] || @timeout
773
+
774
+ raise("properties cannot be empty") if properties.empty?
775
+ raise("api_key cannot be empty") if api_key.empty?
776
+
777
+
778
+ options = {
779
+ :body => MultiJson.dump(delete_nils(properties)),
780
+ :headers => build_default_headers_post(api_key)
781
+ }
782
+ options.merge!(:timeout => timeout) unless timeout.nil?
783
+
784
+ response = self.class.post(Sift.verification_api_check_path(@version), options)
785
+ Response.new(response.body, response.code, response.response)
786
+ end
787
+
788
+ def create_psp_merchant_profile(properties = {}, opts = {})
789
+ # Create a new PSP Merchant profile
790
+ # Args:
791
+ # properties: A dict of merchant profile data.
792
+ # Returns
793
+ # A sift.client.Response object if the call succeeded, else raises an ApiException
794
+
795
+ account_id = opts[:account_id] || @account_id
796
+ api_key = opts[:api_key] || @api_key
797
+ timeout = opts[:timeout] || @timeout
798
+
799
+ raise("api_key cannot be empty") if api_key.empty?
800
+ raise("account_id cannot be empty") if account_id.empty?
801
+ raise("properties cannot be empty") if properties.empty?
802
+
803
+ options = {
804
+ :body => MultiJson.dump(delete_nils(properties)),
805
+ :headers => { "User-Agent" => user_agent, "Content-Type" => "application/json" },
806
+ :basic_auth => { :username => api_key, :password => "" }
807
+ }
808
+ options.merge!(:timeout => timeout) unless timeout.nil?
809
+ response = self.class.post(API_ENDPOINT + Sift.psp_merchant_api_path(account_id), options)
810
+ Response.new(response.body, response.code, response.response)
811
+ end
812
+
813
+ def update_psp_merchant_profile(merchant_id, properties = {}, opts = {})
814
+ # Update an existing PSP Merchant profile
815
+ # Args:
816
+ # merchant_id: id of merchant
817
+ # properties: A dict of merchant profile data.
818
+ # Returns
819
+ # A sift.client.Response object if the call succeeded, else raises an ApiException
820
+
821
+ account_id = opts[:account_id] || @account_id
822
+ api_key = opts[:api_key] || @api_key
823
+ timeout = opts[:timeout] || @timeout
824
+
825
+ raise("api_key cannot be empty") if api_key.empty?
826
+ raise("account_id cannot be empty") if account_id.empty?
827
+ raise("merchant_id cannot be empty") if merchant_id.empty?
828
+ raise("properties cannot be empty") if properties.empty?
829
+
830
+ options = {
831
+ :body => MultiJson.dump(delete_nils(properties)),
832
+ :headers => { "User-Agent" => user_agent, "Content-Type" => "application/json" },
833
+ :basic_auth => { :username => api_key, :password => "" }
834
+ }
835
+ options.merge!(:timeout => timeout) unless timeout.nil?
836
+ response = self.class.put(API_ENDPOINT + Sift.psp_merchant_id_api_path(account_id, merchant_id), options)
837
+ Response.new(response.body, response.code, response.response)
838
+ end
839
+
840
+ def get_a_psp_merchant_profile(merchant_id, opts = {})
841
+ # Gets a PSP merchant profile using merchant id.
842
+ # Args:
843
+ # merchant_id: id of merchant
844
+ # Returns
845
+ # A sift.client.Response object if the call succeeded, else raises an ApiException
846
+
847
+ account_id = opts[:account_id] || @account_id
848
+ api_key = opts[:api_key] || @api_key
849
+ timeout = opts[:timeout] || @timeout
850
+
851
+ raise("api_key cannot be empty") if api_key.empty?
852
+ raise("account_id cannot be empty") if account_id.empty?
853
+ raise("merchant_id cannot be empty") if merchant_id.empty?
854
+
855
+ options = {
856
+ :headers => { "User-Agent" => user_agent, "Content-Type" => "application/json" },
857
+ :basic_auth => { :username => api_key, :password => "" }
858
+ }
859
+ options.merge!(:timeout => timeout) unless timeout.nil?
860
+ response = self.class.get(API_ENDPOINT + Sift.psp_merchant_id_api_path(account_id, merchant_id), options)
861
+ Response.new(response.body, response.code, response.response)
862
+ end
863
+
864
+ def get_psp_merchant_profiles(batch_size = nil, batch_token = nil, opts = {})
865
+ # Get all PSP merchant profiles.
866
+ # Args:
867
+ # batch_size : Batch or page size of the paginated sequence.
868
+ # batch_token : Batch or page position of the paginated sequence.
869
+ # Returns
870
+ # A sift.client.Response object if the call succeeded, else raises an ApiException
871
+
872
+ account_id = opts[:account_id] || @account_id
873
+ api_key = opts[:api_key] || @api_key
874
+ timeout = opts[:timeout] || @timeout
875
+
876
+ raise("api_key cannot be empty") if api_key.empty?
877
+ raise("account_id cannot be empty") if account_id.empty?
878
+
879
+ query = {}
880
+ query["batch_size"] = batch_size if batch_size
881
+ query["batch_token"] = batch_token if batch_token
882
+
883
+ options = {
884
+ :headers => { "User-Agent" => user_agent, "Content-Type" => "application/json" },
885
+ :basic_auth => { :username => api_key, :password => "" },
886
+ :query => query
887
+ }
888
+ options.merge!(:timeout => timeout) unless timeout.nil?
889
+ response = self.class.get(API_ENDPOINT + Sift.psp_merchant_api_path(account_id), options)
890
+ Response.new(response.body, response.code, response.response)
891
+ end
892
+
719
893
  private
720
894
 
721
895
  def handle_response(response)
data/lib/sift/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Sift
2
- VERSION = "4.1.0"
2
+ VERSION = "4.3.0"
3
3
  API_VERSION = "205"
4
4
  end
data/lib/sift.rb CHANGED
@@ -9,6 +9,21 @@ module Sift
9
9
  "/v#{version}/events"
10
10
  end
11
11
 
12
+ # Returns the path for the specified API version
13
+ def self.verification_api_send_path(version=API_VERSION)
14
+ "/v#{version}/verification/send"
15
+ end
16
+
17
+ # Returns the path for the specified API version
18
+ def self.verification_api_resend_path(version=API_VERSION)
19
+ "/v#{version}/verification/resend"
20
+ end
21
+
22
+ # Returns the path for the specified API version
23
+ def self.verification_api_check_path(version=API_VERSION)
24
+ "/v#{version}/verification/check"
25
+ end
26
+
12
27
  # Returns the Score API path for the specified user ID and API version
13
28
  def self.score_api_path(user_id, version=API_VERSION)
14
29
  "/v#{version}/score/#{ERB::Util.url_encode(user_id)}/"
@@ -56,6 +71,18 @@ module Sift
56
71
  "/content/#{ERB::Util.url_encode(content_id)}/decisions"
57
72
  end
58
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
+
59
86
  # Module-scoped public API key
60
87
  class << self
61
88
  attr_accessor :api_key
@@ -0,0 +1,117 @@
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 valid_transaction_properties
11
+ {
12
+ :$type => "$add_item_to_cart",
13
+ :$user_id => "haneeshv@exalture.com",
14
+ :$session_id => "gigtleqddo84l8cm15qe4il",
15
+ :$item => {
16
+ :$item_id => "B004834GQO",
17
+ :$product_title => "The Slanket Blanket-Texas Tea",
18
+ :$price => 39990000,
19
+ :$currency_code => "USD",
20
+ :$upc => "6786211451001",
21
+ :$sku => "004834GQ",
22
+ :$brand => "Slanket",
23
+ :$manufacturer => "Slanket",
24
+ :$category => "Blankets & Throws",
25
+ :$tags => [
26
+ "Awesome",
27
+ "Wintertime specials"
28
+ ],
29
+ :$color => "Texas Tea",
30
+ :$quantity => 16
31
+ },
32
+ :$brand_name => "sift",
33
+ :$site_domain => "sift.com",
34
+ :$site_country => "US",
35
+ :$browser => {
36
+ :$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",
37
+ :$accept_language => "en-US",
38
+ :$content_language => "en-GB"
39
+ }
40
+ }
41
+ end
42
+
43
+ def percentile_response_json
44
+ {
45
+ :user_id => 'haneeshv@exalture.com',
46
+ :latest_labels => {},
47
+ :workflow_statuses => [],
48
+ :scores => {
49
+ :account_abuse => {
50
+ :score => 0.32787917675535705,
51
+ :reasons => [{
52
+ :name => 'Latest item product title',
53
+ :value => 'The Slanket Blanket-Texas Tea'
54
+ }],
55
+ :percentiles => {
56
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
57
+ }
58
+ },
59
+ :acontent_abuse => {
60
+ :score => 0.28056292905897995,
61
+ :reasons => [{
62
+ :name => 'timeSinceFirstEvent',
63
+ :value => '13.15 minutes'
64
+ }],
65
+ :percentiles => {
66
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
67
+ }
68
+ },
69
+ :payment_abuse => {
70
+ :score => 0.28610507028376797,
71
+ :reasons => [{
72
+ :name => 'Latest item currency code',
73
+ :value => 'USD'
74
+ }, {
75
+ :name => 'Latest item item ID',
76
+ :value => 'B004834GQO'
77
+ }, {
78
+ :name => 'Latest item product title',
79
+ :value => 'The Slanket Blanket-Texas Tea'
80
+ }],
81
+ :percentiles => {
82
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
83
+ }
84
+ },
85
+ :promotion_abuse => {
86
+ :score => 0.05731508921450917,
87
+ :percentiles => {
88
+ :last_7_days => -1.0, :last_1_days => -1.0, :last_10_days => -1.0, :last_5_days => -1.0
89
+ }
90
+ }
91
+ },
92
+ :status => 0,
93
+ :error_message => 'OK'
94
+ }
95
+ end
96
+
97
+ it "Successfully submits a v205 event with SCORE_PERCENTILES" do
98
+ response_json =
99
+ { :status => 0, :error_message => "OK", :score_response => percentile_response_json}
100
+ stub_request(:post, "https://api.siftscience.com/v205/events?fields=SCORE_PERCENTILES&return_score=true").
101
+ with { | request|
102
+ parsed_body = JSON.parse(request.body)
103
+ expect(parsed_body).to include("$api_key" => "overridden")
104
+ }.to_return(:status => 200, :body => MultiJson.dump(response_json), :headers => {})
105
+
106
+ api_key = "foobar"
107
+ event = "$transaction"
108
+ properties = valid_transaction_properties
109
+
110
+ response = Sift::Client.new(:api_key => api_key, :version => "205")
111
+ .track(event, properties, :api_key => "overridden", :include_score_percentiles => "true", :return_score => "true")
112
+ expect(response.ok?).to eq(true)
113
+ expect(response.api_status).to eq(0)
114
+ expect(response.api_error_message).to eq("OK")
115
+ expect(response.body["score_response"]["scores"]["account_abuse"]["percentiles"]["last_7_days"]).to eq(-1.0)
116
+ end
117
+ end
@@ -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
@@ -0,0 +1,91 @@
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 valid_send_properties
11
+ {
12
+ :$user_id => 'billy_jones_301',
13
+ :$send_to => 'billy_jones_301@gmail.com',
14
+ :$verification_type => '$email',
15
+ :$brand_name => 'MyTopBrand',
16
+ :$language => 'en',
17
+ :$event => {
18
+ :$session_id => '09f7f361575d11ff',
19
+ :$verified_event => '$login',
20
+ :$reason => '$automated_rule',
21
+ :$ip => '192.168.1.1',
22
+ :$browser => {
23
+ :$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'
24
+ }
25
+ }
26
+ }
27
+ end
28
+
29
+ def valid_resend_properties
30
+ {
31
+ :$user_id => 'billy_jones_301',
32
+ :$verified_event => '$login'
33
+ }
34
+ end
35
+
36
+ def valid_check_properties
37
+ {
38
+ :$user_id => 'billy_jones_301',
39
+ :$code => '123456'
40
+ }
41
+ end
42
+
43
+ it "Successfully calls send" do
44
+ api_key = "foobar1"
45
+ user_id = "foobar2"
46
+
47
+ response_json = { :status => 0, :error_message => "OK"}
48
+
49
+ stub_request(:post, "https://foobar1:@api.siftscience.com/v1.1/verification/send")
50
+ .to_return(:status => 200, :body => MultiJson.dump(response_json))
51
+
52
+ response = Sift::Client.new(:api_key => api_key,:user_id => user_id,:version=>1.1).verification_send(valid_send_properties,:version => 205)
53
+ expect(response.ok?).to eq(true)
54
+ expect(response.api_status).to eq(0)
55
+ expect(response.api_error_message).to eq("OK")
56
+
57
+ end
58
+
59
+ it "Successfully calls resend" do
60
+ api_key = "foobar1"
61
+ user_id = "foobar2"
62
+
63
+ response_json = { :status => 0, :error_message => "OK"}
64
+
65
+ stub_request(:post, "https://foobar1:@api.siftscience.com/v1.1/verification/resend")
66
+ .to_return(:status => 200, :body => MultiJson.dump(response_json))
67
+
68
+ response = Sift::Client.new(:api_key => api_key,:user_id => user_id,:version=>1.1).verification_resend(valid_resend_properties,:version => 205)
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
+
73
+ end
74
+
75
+ it "Successfully calls check" do
76
+ api_key = "foobar1"
77
+ user_id = "foobar2"
78
+
79
+ response_json = { :status => 0, :error_message => "OK"}
80
+
81
+ stub_request(:post, "https://foobar1:@api.siftscience.com/v1.1/verification/check")
82
+ .to_return(:status => 200, :body => MultiJson.dump(response_json))
83
+
84
+ response = Sift::Client.new(:api_key => api_key,:user_id => user_id,:version=>1.1).verification_check(valid_check_properties,:version => 205)
85
+ expect(response.ok?).to eq(true)
86
+ expect(response.api_status).to eq(0)
87
+ expect(response.api_error_message).to eq("OK")
88
+
89
+ end
90
+
91
+ end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sift
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 4.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Sadaghiani
8
8
  - Yoav Schatzberg
9
9
  - Jacob Burnim
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-07-11 00:00:00.000000000 Z
13
+ date: 2023-08-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -124,13 +124,17 @@ extensions: []
124
124
  extra_rdoc_files: []
125
125
  files:
126
126
  - ".circleci/config.yml"
127
+ - ".github/pull_request_template.md"
128
+ - ".github/workflows/publishing_sift_ruby.yml"
127
129
  - ".gitignore"
128
130
  - Gemfile
129
131
  - HISTORY
130
132
  - LICENSE
131
133
  - README.md
132
134
  - Rakefile
135
+ - examples/psp_merchant_management_apis.rb
133
136
  - examples/simple.rb
137
+ - examples/validation_apis.rb
134
138
  - lib/sift.rb
135
139
  - lib/sift/client.rb
136
140
  - lib/sift/client/decision.rb
@@ -148,15 +152,18 @@ files:
148
152
  - spec/unit/client/decision/apply_to_spec.rb
149
153
  - spec/unit/client/decision_spec.rb
150
154
  - spec/unit/client_203_spec.rb
155
+ - spec/unit/client_205_spec.rb
151
156
  - spec/unit/client_label_spec.rb
157
+ - spec/unit/client_psp_merchant_spec.rb
152
158
  - spec/unit/client_spec.rb
159
+ - spec/unit/client_validationapi_spec.rb
153
160
  - spec/unit/router_spec.rb
154
161
  - spec/unit/validate/decision_spec.rb
155
162
  - spec/unit/validate/primitive_spec.rb
156
163
  homepage: http://siftscience.com
157
164
  licenses: []
158
165
  metadata: {}
159
- post_install_message:
166
+ post_install_message:
160
167
  rdoc_options: []
161
168
  require_paths:
162
169
  - lib
@@ -171,19 +178,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
178
  - !ruby/object:Gem::Version
172
179
  version: '0'
173
180
  requirements: []
174
- rubygems_version: 3.1.4
175
- signing_key:
181
+ rubygems_version: 3.1.6
182
+ signing_key:
176
183
  specification_version: 4
177
184
  summary: Sift Science Ruby API Gem
178
- test_files:
179
- - spec/fixtures/fake_responses.rb
180
- - spec/integration/sift_spec.rb
181
- - spec/spec_helper.rb
182
- - spec/unit/client/decision/apply_to_spec.rb
183
- - spec/unit/client/decision_spec.rb
184
- - spec/unit/client_203_spec.rb
185
- - spec/unit/client_label_spec.rb
186
- - spec/unit/client_spec.rb
187
- - spec/unit/router_spec.rb
188
- - spec/unit/validate/decision_spec.rb
189
- - spec/unit/validate/primitive_spec.rb
185
+ test_files: []