Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/jobs/resolution_proofing_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def perform(

if IdentityConfig.store.idv_socure_shadow_mode_enabled
SocureShadowModeProofingJob.perform_later(
document_capture_session_result_id: document_capture_session.result_id,
document_capture_session_result_id: document_capture_session&.result_id,
encrypted_arguments:,
service_provider_issuer:,
user_email: user_email_for_proofing(user),
Expand Down
22 changes: 11 additions & 11 deletions app/services/proofing/resolution/plugins/aamva_plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ class AamvaPlugin
def call(
applicant_pii:,
current_sp:,
instant_verify_state_id_address_result:,
state_id_address_resolution_result:,
ipp_enrollment_in_progress:,
timer:
)
should_proof = should_proof_state_id_with_aamva?(
should_proof = should_proof_state_id?(
applicant_pii:,
instant_verify_state_id_address_result:,
state_id_address_resolution_result:,
ipp_enrollment_in_progress:,
)

Expand Down Expand Up @@ -85,37 +85,37 @@ def same_address_as_id?(applicant_pii)
applicant_pii[:same_address_as_id].to_s == 'true'
end

def should_proof_state_id_with_aamva?(
def should_proof_state_id?(
applicant_pii:,
instant_verify_state_id_address_result:,
state_id_address_resolution_result:,
ipp_enrollment_in_progress:
)
return false unless aamva_supports_state_id_jurisdiction?(applicant_pii)
# If the user is in in-person-proofing and they have changed their address then
# they are not eligible for get-to-yes
if !ipp_enrollment_in_progress || same_address_as_id?(applicant_pii)
user_can_pass_after_state_id_check?(instant_verify_state_id_address_result:)
user_can_pass_after_state_id_check?(state_id_address_resolution_result:)
else
instant_verify_state_id_address_result.success?
state_id_address_resolution_result.success?
end
end

def user_can_pass_after_state_id_check?(
instant_verify_state_id_address_result:
state_id_address_resolution_result:
)
return true if instant_verify_state_id_address_result.success?
return true if state_id_address_resolution_result.success?

# For failed IV results, this method validates that the user is eligible to pass if the
# failed attributes are covered by the same attributes in a successful AAMVA response
# aka the Get-to-Yes w/ AAMVA feature.
if !instant_verify_state_id_address_result.
if !state_id_address_resolution_result.
failed_result_can_pass_with_additional_verification?
return false
end

attributes_aamva_can_pass = [:address, :dob, :state_id_number]
attributes_requiring_additional_verification =
instant_verify_state_id_address_result.attributes_requiring_additional_verification
state_id_address_resolution_result.attributes_requiring_additional_verification
results_that_cannot_pass_aamva =
attributes_requiring_additional_verification - attributes_aamva_can_pass

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

module Proofing
module Resolution
module Plugins
class ResidentialAddressPlugin
attr_reader :proofer, :sp_cost_token

def initialize(
proofer:,
sp_cost_token:
)
@proofer = proofer
@sp_cost_token = sp_cost_token
end

def call(
applicant_pii:,
current_sp:,
ipp_enrollment_in_progress:,
timer:
)
return residential_address_unnecessary_result unless ipp_enrollment_in_progress

timer.time('residential address') do
proofer.proof(applicant_pii)
end.tap do |result|
Db::SpCost::AddSpCost.call(
current_sp,
:lexis_nexis_resolution,
transaction_id: result.transaction_id,
)
end
end

def residential_address_unnecessary_result
Proofing::Resolution::Result.new(
success: true, errors: {}, exception: nil, vendor_name: 'ResidentialAddressNotRequired',
)
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
module Proofing
module Resolution
module Plugins
class InstantVerifyStateIdAddressPlugin
class StateIdAddressPlugin
attr_reader :proofer, :sp_cost_token

SECONDARY_ID_ADDRESS_MAP = {
identity_doc_address1: :address1,
identity_doc_address2: :address2,
Expand All @@ -12,18 +14,26 @@ class InstantVerifyStateIdAddressPlugin
identity_doc_zipcode: :zipcode,
}.freeze

def initialize(
proofer:,
sp_cost_token:
)
@proofer = proofer
@sp_cost_token = sp_cost_token
end

def call(
applicant_pii:,
current_sp:,
instant_verify_residential_address_result:,
residential_address_resolution_result:,
ipp_enrollment_in_progress:,
timer:
)
if same_address_as_id?(applicant_pii) && ipp_enrollment_in_progress
return instant_verify_residential_address_result
return residential_address_resolution_result
end

return resolution_cannot_pass unless instant_verify_residential_address_result.success?
return resolution_cannot_pass unless residential_address_resolution_result.success?

applicant_pii_with_state_id_address =
if ipp_enrollment_in_progress
Expand All @@ -43,25 +53,6 @@ def call(
end
end

def proofer
@proofer ||=
case IdentityConfig.store.idv_resolution_default_vendor
when :instant_verify
Proofing::LexisNexis::InstantVerify::Proofer.new(
instant_verify_workflow: IdentityConfig.store.lexisnexis_instant_verify_workflow,
account_id: IdentityConfig.store.lexisnexis_account_id,
base_url: IdentityConfig.store.lexisnexis_base_url,
username: IdentityConfig.store.lexisnexis_username,
password: IdentityConfig.store.lexisnexis_password,
hmac_key_id: IdentityConfig.store.lexisnexis_hmac_key_id,
hmac_secret_key: IdentityConfig.store.lexisnexis_hmac_secret_key,
request_mode: IdentityConfig.store.lexisnexis_request_mode,
)
when :mock
Proofing::Mock::ResolutionMockClient.new
end
end

def resolution_cannot_pass
Proofing::Resolution::Result.new(
success: false, errors: {}, exception: nil, vendor_name: 'ResolutionCannotPass',
Expand Down
104 changes: 92 additions & 12 deletions app/services/proofing/resolution/progressive_proofer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@ module Resolution
# 2. The user has only provided one address for their residential and identity document
# address or separate residential and identity document addresses
class ProgressiveProofer
class InvalidProofingVendorError; end

attr_reader :aamva_plugin,
:instant_verify_residential_address_plugin,
:instant_verify_state_id_address_plugin,
:threatmetrix_plugin

PROOFING_VENDOR_SP_COST_TOKENS = {
mock: :mock_resolution,
instant_verify: :lexis_nexis_resolution,
socure_kyc: :socure_resolution,
}.freeze

def initialize
@aamva_plugin = Plugins::AamvaPlugin.new
@instant_verify_residential_address_plugin =
Plugins::InstantVerifyResidentialAddressPlugin.new
@instant_verify_state_id_address_plugin =
Plugins::InstantVerifyStateIdAddressPlugin.new
@threatmetrix_plugin = Plugins::ThreatMetrixPlugin.new
end

Expand Down Expand Up @@ -50,40 +52,118 @@ def proof(
user_email:,
)

instant_verify_residential_address_result = instant_verify_residential_address_plugin.call(
residential_address_resolution_result = residential_address_plugin.call(
applicant_pii:,
current_sp:,
ipp_enrollment_in_progress:,
timer:,
)

instant_verify_state_id_address_result = instant_verify_state_id_address_plugin.call(
state_id_address_resolution_result = state_id_address_plugin.call(
applicant_pii:,
current_sp:,
instant_verify_residential_address_result:,
residential_address_resolution_result:,
ipp_enrollment_in_progress:,
timer:,
)

state_id_result = aamva_plugin.call(
applicant_pii:,
current_sp:,
instant_verify_state_id_address_result:,
state_id_address_resolution_result:,
ipp_enrollment_in_progress:,
timer:,
)

ResultAdjudicator.new(
device_profiling_result: device_profiling_result,
ipp_enrollment_in_progress: ipp_enrollment_in_progress,
resolution_result: instant_verify_state_id_address_result,
resolution_result: state_id_address_resolution_result,
should_proof_state_id: aamva_plugin.aamva_supports_state_id_jurisdiction?(applicant_pii),
state_id_result: state_id_result,
residential_resolution_result: instant_verify_residential_address_result,
residential_resolution_result: residential_address_resolution_result,
same_address_as_id: applicant_pii[:same_address_as_id],
applicant_pii: applicant_pii,
)
end

def proofing_vendor
@proofing_vendor ||= begin
default_vendor = IdentityConfig.store.idv_resolution_default_vendor
alternate_vendor = IdentityConfig.store.idv_resolution_alternate_vendor
alternate_vendor_percent = IdentityConfig.store.idv_resolution_alternate_vendor_percent

if alternate_vendor == :none
return default_vendor
end

if (rand * 100) <= alternate_vendor_percent
alternate_vendor
else
default_vendor
end
end
end

def residential_address_plugin
@residential_address_plugin ||= Plugins::ResidentialAddressPlugin.new(
proofer: create_proofer,
sp_cost_token:,
)
end

def state_id_address_plugin
@state_id_address_plugin ||= Plugins::StateIdAddressPlugin.new(
proofer: create_proofer,
sp_cost_token:,
)
end

def create_proofer
case proofing_vendor
when :instant_verify then create_instant_verify_proofer
when :mock then create_mock_proofer
when :socure_kyc then create_socure_proofer
else
raise InvalidProofingVendorError, "#{proofing_vendor} is not a valid proofing vendor"
end
end

def create_instant_verify_proofer
Proofing::LexisNexis::InstantVerify::Proofer.new(
instant_verify_workflow: IdentityConfig.store.lexisnexis_instant_verify_workflow,
account_id: IdentityConfig.store.lexisnexis_account_id,
base_url: IdentityConfig.store.lexisnexis_base_url,
username: IdentityConfig.store.lexisnexis_username,
password: IdentityConfig.store.lexisnexis_password,
hmac_key_id: IdentityConfig.store.lexisnexis_hmac_key_id,
hmac_secret_key: IdentityConfig.store.lexisnexis_hmac_secret_key,
request_mode: IdentityConfig.store.lexisnexis_request_mode,
)
end

def create_mock_proofer
Proofing::Mock::ResolutionMockClient.new
end

def create_socure_proofer
Proofing::Socure::IdPlus::Proofer.new(
Proofing::Socure::IdPlus::Config.new(
api_key: IdentityConfig.store.socure_idplus_api_key,
base_url: IdentityConfig.store.socure_idplus_base_url,
timeout: IdentityConfig.store.socure_idplus_timeout_in_seconds,
),
)
end

def sp_cost_token
PROOFING_VENDOR_SP_COST_TOKENS[proofing_vendor].tap do |token|
if !token.present?
raise InvalidProofingVendorError,
"No cost token present for proofing vendor #{proofing_vendor}"
end
end
end
end
end
end
Loading