Skip to content

Commit 05b0d86

Browse files
authored
Merge pull request #98 from maxmind/nlogan/report-no-ip
Make IP address optional when reporting transactions
2 parents 7499837 + b611cf6 commit 05b0d86

File tree

6 files changed

+128
-11
lines changed

6 files changed

+128
-11
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## v2.6.0
4+
5+
* Updated the validation for the Report Transactions API to make the
6+
`ip_address` parameter optional. Now the `tag` and at least one of the
7+
following parameters must be supplied: `ip_address`, `maxmind_id`,
8+
`minfraud_id`, `transaction_id`.
9+
* Updated the validation for the Report Transactions API to check that
10+
`ip_address`, `maxmind_id`, and `minfraud_id` contain valid values.
11+
312
## v2.5.0 (2024-04-16)
413

514
* Equivalent domain names are now normalized when `hash_address` is used.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,9 @@ channel is used to improve the accuracy of their fraud detection
208208
algorithms.
209209

210210
To use the Report Transaction API, create a
211-
`Minfraud::Components::Report::Transaction` object. An IP address and a
212-
valid tag are required arguments for this API. Additional parameters may be
213-
set, as shown below.
211+
`Minfraud::Components::Report::Transaction` object. A valid tag and at least
212+
one of the following are required parameters: ip_address, maxmind_id,
213+
minfraud_id, transaction_id. Additional parameters may be set, as shown below.
214214

215215
If the report is successful, nothing is returned. If the report fails, an
216216
exception will be thrown.

lib/minfraud/components/report/transaction.rb

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ module Report
88
# @see https://dev.maxmind.com/minfraud/report-a-transaction?lang=en
99
class Transaction < Base
1010
include ::Minfraud::Enum
11+
include ::Minfraud::Validates
1112

1213
# The IP address of the customer placing the order. This should be
13-
# passed as a string like "152.216.7.110".
14+
# passed as a string like "152.216.7.110". This field is not required
15+
# if you provide at least one of the transaction's minfraud_id,
16+
# maxmind_id, or transaction_id. You are encouraged to provide it, if
17+
# possible.
1418
#
1519
# @return [String, nil]
1620
attr_accessor :ip_address
@@ -34,16 +38,19 @@ class Transaction < Base
3438

3539
# A unique eight character string identifying a minFraud Standard or
3640
# Premium request. These IDs are returned in the maxmindID field of a
37-
# response for a successful minFraud request. This field is not
38-
# required, but you are encouraged to provide it, if possible.
41+
# response for a successful minFraud request. This field is not required
42+
# if you provide at least one of the transaction's ip_address,
43+
# minfraud_id, or transaction_id. You are encouraged to provide it, if
44+
# possible.
3945
#
4046
# @return [String, nil]
4147
attr_accessor :maxmind_id
4248

4349
# A UUID that identifies a minFraud Score, minFraud Insights, or
4450
# minFraud Factors request. This ID is returned at /id in the response.
45-
# This field is not required, but you are encouraged to provide it if
46-
# the request was made to one of these services.
51+
# This field is not required if you provide at least one of the
52+
# transaction's ip_address, maxmind_id, or transaction_id. You are
53+
# encouraged to provide it, if possible.
4754
#
4855
# @return [String, nil]
4956
attr_accessor :minfraud_id
@@ -56,9 +63,10 @@ class Transaction < Base
5663
# @return [String, nil]
5764
attr_accessor :notes
5865

59-
# The transaction ID you originally passed to minFraud. This field is
60-
# not required, but you are encouraged to provide it or the
61-
# transaction's maxmind_id or minfraud_id.
66+
# The transaction ID you originally passed to minFraud. This field
67+
# is not required if you provide at least one of the transaction's
68+
# ip_address, maxmind_id, or minfraud_id. You are encouraged to
69+
# provide it, if possible.
6270
#
6371
# @return [String, nil]
6472
attr_accessor :transaction_id
@@ -73,6 +81,30 @@ def initialize(params = {})
7381
@notes = params[:notes]
7482
@transaction_id = params[:transaction_id]
7583
self.tag = params[:tag]
84+
85+
validate
86+
end
87+
88+
private
89+
90+
def validate
91+
return if !Minfraud.enable_validation
92+
93+
validate_ip('ip_address', @ip_address)
94+
validate_string('maxmind_id', 8, @maxmind_id)
95+
validate_uuid('minfraud_id', @minfraud_id)
96+
97+
if ip_address.nil? &&
98+
(minfraud_id.nil? || empty_uuid(minfraud_id)) &&
99+
(maxmind_id.nil? || maxmind_id.empty?) &&
100+
(transaction_id.nil? || transaction_id.empty?)
101+
raise ArgumentError, 'At least one of the following is required: ip_address, minfraud_id, maxmind_id, transaction_id.'
102+
end
103+
end
104+
105+
def empty_uuid(value)
106+
stripped_value = value.to_s.gsub('-', '')
107+
stripped_value == '0' * 32
76108
end
77109
end
78110
end

lib/minfraud/validates.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@ def validate_md5(field, value)
2424
end
2525
end
2626

27+
def validate_uuid(field, value)
28+
return if !value
29+
30+
stripped_value = value.to_s.gsub('-', '')
31+
32+
# Define a regex pattern for a valid UUID without dashes
33+
uuid_regex = /\A[0-9a-f]{32}\z/i
34+
35+
unless uuid_regex.match(stripped_value)
36+
raise InvalidInputError, "The #{field} value is not valid. It must be a UUID string."
37+
end
38+
end
39+
2740
def validate_subdivision_code(field, value)
2841
return if !value
2942

spec/components/general_spec.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
end
1515

1616
describe Minfraud::Components::Report::Transaction do
17+
before do
18+
Minfraud.configure { |c| c.enable_validation = false }
19+
end
1720
describe '#initialize' do
1821
it { is_expected.to be_an_instance_of described_class }
1922
it { is_expected.to respond_to :to_json }

spec/components/report/transaction_spec.rb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
describe Minfraud::Components::Report::Transaction do
66
describe '#initialize' do
7+
before do
8+
Minfraud.configure { |c| c.enable_validation = false }
9+
end
710
context 'with an invalid type' do
811
it 'raises an exception' do
912
expect do
@@ -42,4 +45,61 @@
4245
end
4346
end
4447
end
48+
49+
describe 'validation' do
50+
before do
51+
Minfraud.configure { |c| c.enable_validation = true }
52+
end
53+
context 'missing required identifier field' do
54+
it 'raises an exception' do
55+
expect do
56+
described_class.new(tag: :suspected_fraud)
57+
end.to raise_exception(ArgumentError)
58+
end
59+
end
60+
context 'with tag + ip_address' do
61+
it 'does not raise an exception' do
62+
report = described_class.new(
63+
ip_address: '1.2.3.4',
64+
tag: :suspected_fraud
65+
)
66+
67+
expect(report.ip_address).to eq '1.2.3.4'
68+
expect(report.tag).to eq :suspected_fraud
69+
end
70+
end
71+
context 'with tag + maxmind_id' do
72+
it 'does not raise an exception' do
73+
report = described_class.new(
74+
tag: :suspected_fraud,
75+
maxmind_id: '12345678'
76+
)
77+
78+
expect(report.tag).to eq :suspected_fraud
79+
expect(report.maxmind_id).to eq '12345678'
80+
end
81+
end
82+
context 'with tag + minfraud_id' do
83+
it 'does not raise an exception' do
84+
report = described_class.new(
85+
tag: :suspected_fraud,
86+
minfraud_id: '58fa38d8-4b87-458b-a22b-f00eda1aa20d'
87+
)
88+
89+
expect(report.tag).to eq :suspected_fraud
90+
expect(report.minfraud_id).to eq '58fa38d8-4b87-458b-a22b-f00eda1aa20d'
91+
end
92+
end
93+
context 'with tag + transaction_id' do
94+
it 'does not raise an exception' do
95+
report = described_class.new(
96+
tag: :suspected_fraud,
97+
transaction_id: '1FA254yZ'
98+
)
99+
100+
expect(report.tag).to eq :suspected_fraud
101+
expect(report.transaction_id).to eq '1FA254yZ'
102+
end
103+
end
104+
end
45105
end

0 commit comments

Comments
 (0)