sift 4.1.0 → 4.3.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: 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: []