signifyd 0.1.5

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.
@@ -0,0 +1,4 @@
1
+ module Signifyd
2
+ class APIConnectionError < SignifydError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Signifyd
2
+ class APIError < SignifydError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Signifyd
2
+ class AuthenticationError < SignifydError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Signifyd
2
+ class InvalidRequestError < SignifydError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Signifyd
2
+ class NotImplementedError < SignifydError
3
+ end
4
+ end
@@ -0,0 +1,20 @@
1
+ module Signifyd
2
+ class SignifydError < StandardError
3
+ attr_reader :message
4
+ attr_reader :http_status
5
+ attr_reader :http_body
6
+ attr_reader :json_body
7
+
8
+ def initialize(message=nil, http_status=nil, http_body=nil, json_body=nil)
9
+ @message = message
10
+ @http_status = http_status
11
+ @http_body = http_body
12
+ @json_body = json_body
13
+ end
14
+
15
+ def to_s
16
+ status_string = @http_status.nil? ? "" : "(Status #{@http_status}) "
17
+ "#{status_string}#{@message}"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Signifyd
2
+ class Resource < SignifydObject
3
+ def self.class_name
4
+ self.name.split('::')[-1]
5
+ end
6
+
7
+ def self.url
8
+ raise NotImplementedError.new('APIResource is an abstract class. You should perform actions on its subclasses (Case).') if self == Resource
9
+ "#{Signifyd.api_version}/#{CGI.escape(class_name.downcase)}s"
10
+ end
11
+
12
+ def url
13
+ unless id = self['id']
14
+ raise InvalidRequestError.new("Could not determine which URL to request: #{self.class} instance has invalid ID: #{id.inspect}", 'id')
15
+ end
16
+ "#{self.class.url}/#{CGI.escape(id)}"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,151 @@
1
+ module Signifyd
2
+ class SignifydObject
3
+ include Enumerable
4
+
5
+ attr_accessor :api_key
6
+ @@permanent_attributes = Set.new([:api_key, :id])
7
+
8
+ if method_defined?(:id)
9
+ undef :id
10
+ end
11
+
12
+ def initialize(id=nil, api_key=nil)
13
+ if id.kind_of?(Hash)
14
+ @retrieve_options = id.dup
15
+ @retrieve_options.delete(:id)
16
+ id = id[:id]
17
+ else
18
+ @retrieve_options = {}
19
+ end
20
+
21
+ @api_key = api_key
22
+ @values = {}
23
+ @unsaved_values = Set.new
24
+ @transient_values = Set.new
25
+ self.id = id if id
26
+ end
27
+
28
+ def self.construct_from(values, api_key=nil)
29
+ obj = self.new(values[:id], api_key)
30
+ obj.refresh_from(values, api_key)
31
+ obj
32
+ end
33
+
34
+ def to_s(*args)
35
+ Signifyd::JSON.dump(@values, :pretty => true)
36
+ end
37
+
38
+ def inspect
39
+ id_string = (self.respond_to?(:id) && !self.id.nil?) ? " id=#{self.id}" : ""
40
+ "#<#{self.class}:0x#{self.object_id.to_s(16)}#{id_string}> JSON: " + Signifyd::JSON.dump(@values, :pretty => true)
41
+ end
42
+
43
+ def refresh_from(values, api_key, partial=false)
44
+ @api_key = api_key
45
+
46
+ removed = partial ? Set.new : Set.new(@values.keys - values.keys)
47
+ added = Set.new(values.keys - @values.keys)
48
+
49
+ instance_eval do
50
+ remove_accessors(removed)
51
+ add_accessors(added)
52
+ end
53
+ removed.each do |k|
54
+ @values.delete(k)
55
+ @transient_values.add(k)
56
+ @unsaved_values.delete(k)
57
+ end
58
+ values.each do |k, v|
59
+ @values[k] = Util.convert_to_signifyd_object(v, api_key)
60
+ @transient_values.delete(k)
61
+ @unsaved_values.delete(k)
62
+ end
63
+ end
64
+
65
+ def [](k)
66
+ k = k.to_sym if k.kind_of?(String)
67
+ @values[k]
68
+ end
69
+
70
+ def []=(k, v)
71
+ send(:"#{k}=", v)
72
+ end
73
+
74
+ def keys
75
+ @values.keys
76
+ end
77
+
78
+ def values
79
+ @values.values
80
+ end
81
+
82
+ def to_json(*a)
83
+ JSON.dump(@values)
84
+ end
85
+
86
+ def as_json(*a)
87
+ @values.as_json(*a)
88
+ end
89
+
90
+ def to_hash
91
+ @values
92
+ end
93
+
94
+ def each(&blk)
95
+ @values.each(&blk)
96
+ end
97
+
98
+ protected
99
+
100
+ def metaclass
101
+ class << self; self; end
102
+ end
103
+
104
+ def remove_accessors(keys)
105
+ metaclass.instance_eval do
106
+ keys.each do |k|
107
+ next if @@permanent_attributes.include?(k)
108
+ k_eq = :"#{k}="
109
+ remove_method(k) if method_defined?(k)
110
+ remove_method(k_eq) if method_defined?(k_eq)
111
+ end
112
+ end
113
+ end
114
+
115
+ def add_accessors(keys)
116
+ metaclass.instance_eval do
117
+ keys.each do |k|
118
+ next if @@permanent_attributes.include?(k)
119
+ k_eq = :"#{k}="
120
+ define_method(k) { @values[k] }
121
+ define_method(k_eq) do |v|
122
+ @values[k] = v
123
+ @unsaved_values.add(k)
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ def method_missing(name, *args)
130
+ if name.to_s.end_with?('=')
131
+ attr = name.to_s[0...-1].to_sym
132
+ @values[attr] = args[0]
133
+ @unsaved_values.add(attr)
134
+ add_accessors([attr])
135
+ return
136
+ else
137
+ return @values[name] if @values.has_key?(name)
138
+ end
139
+
140
+ begin
141
+ super
142
+ rescue NoMethodError => e
143
+ if @transient_values.include?(name)
144
+ raise NoMethodError.new(e.message + ". The '#{name}' attribute was set in the past, however. The attributes currently available on this object are: #{@values.keys.join(', ')}")
145
+ else
146
+ raise
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,94 @@
1
+ module Signifyd
2
+ class Util
3
+ def self.objects_to_ids(h)
4
+ case h
5
+ when Resource
6
+ h.id
7
+ when Hash
8
+ res = {}
9
+ h.each { |k, v| res[k] = objects_to_ids(v) unless v.nil? }
10
+ res
11
+ when Array
12
+ h.map { |v| objects_to_ids(v) }
13
+ else
14
+ h
15
+ end
16
+ end
17
+
18
+ def self.file_readable(file)
19
+ begin
20
+ File.open(file) { |f| }
21
+ rescue
22
+ false
23
+ else
24
+ true
25
+ end
26
+ end
27
+
28
+ def self.symbolize_names(object)
29
+ case object
30
+ when Hash
31
+ new = {}
32
+ object.each do |key, value|
33
+ key = (key.to_sym rescue key) || key
34
+ new[key] = symbolize_names(value)
35
+ end
36
+ new
37
+ when Array
38
+ object.map { |value| symbolize_names(value) }
39
+ else
40
+ object
41
+ end
42
+ end
43
+
44
+ def self.url_encode(key)
45
+ URI.escape(key.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
46
+ end
47
+
48
+ def self.flatten_params(params, parent_key=nil)
49
+ result = []
50
+ params.each do |key, value|
51
+ calculated_key = parent_key ? "#{parent_key}[#{url_encode(key)}]" : url_encode(key)
52
+ if value.is_a?(Hash)
53
+ result += flatten_params(value, calculated_key)
54
+ elsif value.is_a?(Array)
55
+ result += flatten_params_array(value, calculated_key)
56
+ else
57
+ result << [calculated_key, value]
58
+ end
59
+ end
60
+ result
61
+ end
62
+
63
+ def self.flatten_params_array(value, calculated_key)
64
+ result = []
65
+ value.each do |elem|
66
+ if elem.is_a?(Hash)
67
+ result += flatten_params(elem, calculated_key)
68
+ elsif elem.is_a?(Array)
69
+ result += flatten_params_array(elem, calculated_key)
70
+ else
71
+ result << ["#{calculated_key}[]", elem]
72
+ end
73
+ end
74
+ result
75
+ end
76
+
77
+ def self.encode(value, key = nil)
78
+ case value
79
+ when Hash then value.map { |k,v| encode(v, append_key(key,k)) }.join('&')
80
+ when Array then value.map { |v| encode(v, "#{key}[]") }.join('&')
81
+ when nil then ''
82
+ else
83
+ "#{key}=#{CGI.escape(value.to_s)}"
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def self.append_key(root_key, key)
90
+ root_key.nil? ? key : "#{root_key}[#{key.to_s}]"
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,3 @@
1
+ module Signifyd
2
+ VERSION = '0.1.5'
3
+ end
@@ -0,0 +1,123 @@
1
+ class SignifydRequests
2
+ class << self
3
+ def valid_case
4
+ email = Faker::Internet.email
5
+ full_name = "#{Faker::Name.first_name} #{Faker::Name.last_name}"
6
+ street_address = Faker::Address.street_address
7
+ username = Faker::Internet.user_name
8
+ phone_number = Faker::PhoneNumber.phone_number
9
+
10
+ {
11
+ "attackMethod" => "STOLEN_CC",
12
+ "purchase" => {
13
+ "browserIpAddress" => "50.141.59.109",
14
+ "createdAt" => "2013-02-21T18:37:35-05:00",
15
+ "currency" => "CAD",
16
+ "totalPrice" => "495.00",
17
+ "shippingPrice" => "20.00",
18
+ "products" => [
19
+ {
20
+ "itemId" => (rand * 1000000).ceil,
21
+ "itemName" => Faker::Company.catch_phrase,
22
+ "itemQuantity" => (rand * 10).ceil,
23
+ "itemPrice" => "#{(rand * 60).round(2)}",
24
+ "itemWeight" => (rand * 10).ceil
25
+ }
26
+ ]
27
+ },
28
+ "recipient"=> {
29
+ "fullName"=>full_name,
30
+ "confirmationEmail"=>nil,
31
+ "deliveryAddress"=> {
32
+ "streetAddress"=>street_address,
33
+ "unit"=>nil,
34
+ "city"=>"Palo Alto",
35
+ "provinceCode"=>"CA",
36
+ "postalCode"=>"94306",
37
+ "countryCode"=>"US",
38
+ "latitude"=>"37.4248",
39
+ "longitude"=>"-122.148"
40
+ }
41
+ },
42
+ "card"=> {
43
+ "cardHolderName"=>full_name,
44
+ "bin"=>nil,
45
+ "billingAddress"=> {
46
+ "streetAddress"=>street_address,
47
+ "unit"=>nil,
48
+ "city"=>"Palo Alto",
49
+ "provinceCode"=>"CA",
50
+ "postalCode"=>"94306",
51
+ "countryCode"=>"US",
52
+ "latitude"=>"37.4248",
53
+ "longitude"=>"-122.148"
54
+ }
55
+ },
56
+ "userAccount"=>{
57
+ "email"=>email,
58
+ "username"=>username,
59
+ "phone"=>phone_number,
60
+ "createdDate"=>nil,
61
+ "accountNumber"=>nil,
62
+ "lastOrderId"=>nil,
63
+ "aggregateOrderCount"=>nil,
64
+ "aggregateOrderDollars"=>nil,
65
+ "lastUpdateDate"=>nil
66
+ },
67
+ "seller"=> {
68
+ "name"=> "Amazon",
69
+ "domain"=> "amazon.com",
70
+ "shipFromAddress"=> {
71
+ "streetAddress"=> "1850 Mercer Rd",
72
+ "unit"=> nil,
73
+ "city"=> "Lexington",
74
+ "provinceCode"=> "KY",
75
+ "postalCode"=> "40511",
76
+ "countryCode"=> "US",
77
+ "latitude"=> nil,
78
+ "longitude"=> nil
79
+ },
80
+ "corporateAddress"=> {
81
+ "streetAddress"=> "410 Terry Ave",
82
+ "unit"=> "3L",
83
+ "city"=> "Seattle",
84
+ "provinceCode"=> "WA",
85
+ "postalCode"=> "98109",
86
+ "countryCode"=> "US",
87
+ "latitude"=> nil,
88
+ "longitude"=> nil
89
+ }
90
+ }
91
+ }
92
+ end
93
+
94
+ # systematic: example of correctly formatted json
95
+ def correct_case_json
96
+ "{\"attackMethod\":\"STOLEN_CC\",\"purchase\":{\"browserIpAddress\":\"50.141.59.109\",\"createdAt\":\"2013-02-21T18:37:35-05:00\",\"currency\":\"CAD\",\"totalPrice\":\"495.00\",\"shippingPrice\":\"20.00\",\"products\":[{\"itemId\":272111,\"itemName\":\"Intuitive 4th generation Graphic Interface\",\"itemQuantity\":5,\"itemPrice\":\"59.53\",\"itemWeight\":7}]},\"recipient\":{\"fullName\":\"Courtney Cruickshank\",\"confirmationEmail\":null,\"deliveryAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"card\":{\"cardHolderName\":\"Courtney Cruickshank\",\"bin\":null,\"billingAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"userAccount\":{\"email\":\"[email protected]\",\"username\":\"tamia\",\"phone\":\"(715)038-1226\",\"createdDate\":null,\"accountNumber\":null,\"lastOrderId\":null,\"aggregateOrderCount\":null,\"aggregateOrderDollars\":null,\"lastUpdateDate\":null},\"seller\":{\"name\":\"Amazon\",\"domain\":\"amazon.com\",\"shipFromAddress\":{\"streetAddress\":\"1850 Mercer Rd\",\"unit\":null,\"city\":\"Lexington\",\"provinceCode\":\"KY\",\"postalCode\":\"40511\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null},\"corporateAddress\":{\"streetAddress\":\"410 Terry Ave\",\"unit\":\"3L\",\"city\":\"Seattle\",\"provinceCode\":\"WA\",\"postalCode\":\"98109\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null}}}"
97
+ end
98
+
99
+ # synopsis: Removed ":" between attackMethod and STOLEN_CC - should be attackMethod:STOLEN_CC
100
+ def invalid_case_bad_json_01
101
+ "{\"attackMethod\" \"STOLEN_CC\",\"purchase\":{\"browserIpAddress\":\"50.141.59.109\",\"createdAt\":\"2013-02-21T18:37:35-05:00\",\"currency\":\"CAD\",\"totalPrice\":\"495.00\",\"shippingPrice\":\"20.00\",\"products\":[{\"itemId\":272111,\"itemName\":\"Intuitive 4th generation Graphic Interface\",\"itemQuantity\":5,\"itemPrice\":\"59.53\",\"itemWeight\":7}]},\"recipient\":{\"fullName\":\"Courtney Cruickshank\",\"confirmationEmail\":null,\"deliveryAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"card\":{\"cardHolderName\":\"Courtney Cruickshank\",\"bin\":null,\"billingAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"userAccount\":{\"email\":\"[email protected]\",\"username\":\"tamia\",\"phone\":\"(715)038-1226\",\"createdDate\":null,\"accountNumber\":null,\"lastOrderId\":null,\"aggregateOrderCount\":null,\"aggregateOrderDollars\":null,\"lastUpdateDate\":null},\"seller\":{\"name\":\"Amazon\",\"domain\":\"amazon.com\",\"shipFromAddress\":{\"streetAddress\":\"1850 Mercer Rd\",\"unit\":null,\"city\":\"Lexington\",\"provinceCode\":\"KY\",\"postalCode\":\"40511\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null},\"corporateAddress\":{\"streetAddress\":\"410 Terry Ave\",\"unit\":\"3L\",\"city\":\"Seattle\",\"provinceCode\":\"WA\",\"postalCode\":\"98109\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null}}}"
102
+ end
103
+
104
+ # synopsis: Removed "," between STOLEN_CC and purchase - should be STOLEN_CC, purchase
105
+ def invalid_case_bad_json_02
106
+ "{\"attackMethod\":\"STOLEN_CC\" \"purchase\":{\"browserIpAddress\":\"50.141.59.109\",\"createdAt\":\"2013-02-21T18:37:35-05:00\",\"currency\":\"CAD\",\"totalPrice\":\"495.00\",\"shippingPrice\":\"20.00\",\"products\":[{\"itemId\":272111,\"itemName\":\"Intuitive 4th generation Graphic Interface\",\"itemQuantity\":5,\"itemPrice\":\"59.53\",\"itemWeight\":7}]},\"recipient\":{\"fullName\":\"Courtney Cruickshank\",\"confirmationEmail\":null,\"deliveryAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"card\":{\"cardHolderName\":\"Courtney Cruickshank\",\"bin\":null,\"billingAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"userAccount\":{\"email\":\"[email protected]\",\"username\":\"tamia\",\"phone\":\"(715)038-1226\",\"createdDate\":null,\"accountNumber\":null,\"lastOrderId\":null,\"aggregateOrderCount\":null,\"aggregateOrderDollars\":null,\"lastUpdateDate\":null},\"seller\":{\"name\":\"Amazon\",\"domain\":\"amazon.com\",\"shipFromAddress\":{\"streetAddress\":\"1850 Mercer Rd\",\"unit\":null,\"city\":\"Lexington\",\"provinceCode\":\"KY\",\"postalCode\":\"40511\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null},\"corporateAddress\":{\"streetAddress\":\"410 Terry Ave\",\"unit\":\"3L\",\"city\":\"Seattle\",\"provinceCode\":\"WA\",\"postalCode\":\"98109\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null}}}"
107
+ end
108
+
109
+ # synopsis: All json here will be of standard, the date will just be in wrong format for the SignifydPlatform API
110
+ def invalid_case_bad_formatted_date_01
111
+ "{\"attackMethod\":\"STOLEN_CC\",\"purchase\":{\"browserIpAddress\":\"50.141.59.109\",\"createdAt\":\"2013-02-afdadafasdf:77:35-05:00\",\"currency\":\"CAD\",\"totalPrice\":\"495.00\",\"shippingPrice\":\"20.00\",\"products\":[{\"itemId\":272111,\"itemName\":\"Intuitive 4th generation Graphic Interface\",\"itemQuantity\":5,\"itemPrice\":\"59.53\",\"itemWeight\":7}]},\"recipient\":{\"fullName\":\"Courtney Cruickshank\",\"confirmationEmail\":null,\"deliveryAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"card\":{\"cardHolderName\":\"Courtney Cruickshank\",\"bin\":null,\"billingAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"userAccount\":{\"email\":\"[email protected]\",\"username\":\"tamia\",\"phone\":\"(715)038-1226\",\"createdDate\":null,\"accountNumber\":null,\"lastOrderId\":null,\"aggregateOrderCount\":null,\"aggregateOrderDollars\":null,\"lastUpdateDate\":null},\"seller\":{\"name\":\"Amazon\",\"domain\":\"amazon.com\",\"shipFromAddress\":{\"streetAddress\":\"1850 Mercer Rd\",\"unit\":null,\"city\":\"Lexington\",\"provinceCode\":\"KY\",\"postalCode\":\"40511\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null},\"corporateAddress\":{\"streetAddress\":\"410 Terry Ave\",\"unit\":\"3L\",\"city\":\"Seattle\",\"provinceCode\":\"WA\",\"postalCode\":\"98109\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null}}}"
112
+ end
113
+
114
+ # synopsis: All json here will be of standard, the date will just be in wrong format for the SignifydPlatform API
115
+ def invalid_case_bad_formatted_date_02
116
+ "{\"attackMethod\":\"STOLEN_CC\",\"purchase\":{\"browserIpAddress\":\"50.141.59.109\",\"createdAt\":\"2013-02-:z\",\"currency\":\"CAD\",\"totalPrice\":495.00\",\"shippingPrice\":\"20.00\",\"products\":[{\"itemId\":272111,\"itemName\":\"Intuitive 4th generation Graphic Interface\",\"itemQuantity\":5,\"itemPrice\":\"59.53\",\"itemWeight\":7}]},\"recipient\":{\"fullName\":\"Courtney Cruickshank\",\"confirmationEmail\":null,\"deliveryAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"card\":{\"cardHolderName\":\"Courtney Cruickshank\",\"bin\":null,\"billingAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"userAccount\":{\"email\":\"[email protected]\",\"username\":\"tamia\",\"phone\":\"(715)038-1226\",\"createdDate\":null,\"accountNumber\":null,\"lastOrderId\":null,\"aggregateOrderCount\":null,\"aggregateOrderDollars\":null,\"lastUpdateDate\":null},\"seller\":{\"name\":\"Amazon\",\"domain\":\"amazon.com\",\"shipFromAddress\":{\"streetAddress\":\"1850 Mercer Rd\",\"unit\":null,\"city\":\"Lexington\",\"provinceCode\":\"KY\",\"postalCode\":\"40511\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null},\"corporateAddress\":{\"streetAddress\":\"410 Terry Ave\",\"unit\":\"3L\",\"city\":\"Seattle\",\"provinceCode\":\"WA\",\"postalCode\":\"98109\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null}}}"
117
+ end
118
+
119
+ def invalid_case_non_existent_key
120
+ "{\"attackMethod\":\"STOLEN_CC\",\"purchase\":{\"browserIpAddress\":\"50.141.59.109\",\"createdAt\":\"2013-02-21T18:37:35-05:00\",\"hotDogs\":\"with ketchup\",\"currency\":\"CAD\",\"totalPrice\":\"495.00\",\"shippingPrice\":\"20.00\",\"products\":[{\"itemId\":272111,\"itemName\":\"Intuitive 4th generation Graphic Interface\",\"itemQuantity\":5,\"itemPrice\":\"59.53\",\"itemWeight\":7}]},\"recipient\":{\"fullName\":\"Courtney Cruickshank\",\"confirmationEmail\":null,\"deliveryAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"card\":{\"cardHolderName\":\"Courtney Cruickshank\",\"bin\":null,\"billingAddress\":{\"streetAddress\":\"22660 Greenholt Camp\",\"unit\":null,\"city\":\"Palo Alto\",\"provinceCode\":\"CA\",\"postalCode\":\"94306\",\"countryCode\":\"US\",\"latitude\":\"37.4248\",\"longitude\":\"-122.148\"}},\"userAccount\":{\"email\":\"[email protected]\",\"username\":\"tamia\",\"phone\":\"(715)038-1226\",\"createdDate\":null,\"accountNumber\":null,\"lastOrderId\":null,\"aggregateOrderCount\":null,\"aggregateOrderDollars\":null,\"lastUpdateDate\":null},\"seller\":{\"name\":\"Amazon\",\"domain\":\"amazon.com\",\"shipFromAddress\":{\"streetAddress\":\"1850 Mercer Rd\",\"unit\":null,\"city\":\"Lexington\",\"provinceCode\":\"KY\",\"postalCode\":\"40511\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null},\"corporateAddress\":{\"streetAddress\":\"410 Terry Ave\",\"unit\":\"3L\",\"city\":\"Seattle\",\"provinceCode\":\"WA\",\"postalCode\":\"98109\",\"countryCode\":\"US\",\"latitude\":null,\"longitude\":null}}}"
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,126 @@
1
+ require 'spec_helper'
2
+
3
+ describe Signifyd::Case do
4
+ let(:hash) { SignifydRequests.valid_case }
5
+ let(:json) { JSON.dump(hash) }
6
+ let(:case_id) { (rand * 1000).ceil }
7
+ let(:order_id) { 'unique_id'}
8
+ let(:investigation) { "{\"investigationId\":#{case_id}}" }
9
+ let(:retrieved_case) {"{\"orderId\":#{case_id}}" }
10
+
11
+ context '.create' do
12
+ context 'when creating a case with a valid API key' do
13
+ context 'and passing the correct parameters' do
14
+ before {
15
+ Signifyd.api_key = SIGNIFYD_API_KEY
16
+
17
+ stub_request(:post, "https://#{Signifyd.api_key}@api.signifyd.com/v2/cases").
18
+ with(:body => json, :headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'Content-Length'=>json.size, 'Content-Type'=>'application/json', 'User-Agent'=>'Signifyd Ruby v2'}).
19
+ to_return(:status => 201, :body => investigation, :headers => {})
20
+ }
21
+
22
+ after {
23
+ Signifyd.api_key = nil
24
+ }
25
+
26
+ subject {
27
+ Signifyd::Case.create(hash)
28
+ }
29
+
30
+ it { should be_true }
31
+ it { should_not be_nil }
32
+ it { expect(subject[:code]).to eq(201) }
33
+ it { expect(subject[:body][:investigationId]).to eq(JSON.parse(investigation)[:investigationId]) }
34
+ end
35
+
36
+ context 'and passing incorrect or nil parameters' do
37
+ before {
38
+ Signifyd.api_key = SIGNIFYD_API_KEY
39
+ }
40
+
41
+ after {
42
+ Signifyd.api_key = nil
43
+ }
44
+
45
+ it { lambda { Signifyd::Case.create() }.should raise_error }
46
+ end
47
+ end
48
+
49
+ context 'when creating a case with an invalid API key' do
50
+ it { lambda { Signifyd::Case.create(hash) }.should raise_error }
51
+ end
52
+ end
53
+
54
+ context '.update' do
55
+ context 'when updating a case' do
56
+ context 'and the proper case_id and parameters have been sent' do
57
+ before {
58
+ Signifyd.api_key = SIGNIFYD_API_KEY
59
+
60
+ stub_request(:put, "https://#{Signifyd.api_key}@api.signifyd.com/v2/cases/#{case_id}").
61
+ with(:body => json, :headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'Content-Length'=>json.size, 'Content-Type'=>'application/json', 'User-Agent'=>'Signifyd Ruby v2'}).
62
+ to_return(:status => 200, :body => investigation, :headers => {})
63
+ }
64
+
65
+ after {
66
+ Signifyd.api_key = nil
67
+ }
68
+
69
+ subject {
70
+ Signifyd::Case.update(case_id, hash)
71
+ }
72
+
73
+ it { should be_true }
74
+ it { should_not be_nil }
75
+ it { expect(subject[:code]).to eq(200) }
76
+ it { expect(subject[:body][:investigationId]).to eq(JSON.parse(investigation)[:investigationId]) }
77
+ end
78
+
79
+ context 'and incorrect parameters have been passed' do
80
+ before {
81
+ Signifyd.api_key = SIGNIFYD_API_KEY
82
+ }
83
+
84
+ after {
85
+ Signifyd.api_key = nil
86
+ }
87
+
88
+ it { lambda { Signifyd::Case.update(case_id, {}) }.should raise_error }
89
+ end
90
+ end
91
+ end
92
+
93
+ describe '#find' do
94
+ before :each do
95
+ Signifyd.api_key = SIGNIFYD_API_KEY
96
+ end
97
+ after :each do
98
+ Signifyd.api_key = nil
99
+ end
100
+ context 'when case with orderId exists' do
101
+ it 'should return case in hash format' do
102
+ stub_request(:get, "https://#{Signifyd.api_key}@api.signifyd.com/v2/orders/#{order_id}/case").
103
+ with(:body => {}, :headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'Content-Length'=>2, 'Content-Type'=>'application/json', 'User-Agent'=>'Signifyd Ruby v2'}).
104
+ to_return(:status => 200, :body => retrieved_case, :headers => {})
105
+
106
+ subject = Signifyd::Case.find({order_id: order_id})
107
+ expect(subject).to be_true
108
+ expect(subject[:code]).to eq(200)
109
+ expect(subject[:body][:orderId]).to eq(JSON.parse(retrieved_case)[:orderId])
110
+ end
111
+ end
112
+ context 'when case with orderID does not exist' do
113
+ it 'should raise exception' do
114
+ exception = RestClient::ExceptionWithResponse.new('test')
115
+ exception.should_receive(:http_code).and_return(400)
116
+ exception.should_receive(:http_body).and_return('as')
117
+ stub_request(:get, "https://#{Signifyd.api_key}@api.signifyd.com/v2/orders/#{order_id}/case").
118
+ with(:body => {}, :headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'Content-Length'=>2, 'Content-Type'=>'application/json', 'User-Agent'=>'Signifyd Ruby v2'}).
119
+ to_raise(exception)
120
+
121
+ expect {Signifyd::Case.find({order_id: order_id})}.to raise_error(Signifyd::InvalidRequestError)
122
+ end
123
+ end
124
+ end
125
+
126
+ end
OSZAR »