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
47 changes: 37 additions & 10 deletions lib/checkout_sdk/api_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ def invoke_put(path, authorization, request, headers = nil)
invoke(:put, path, authorization, request, nil, params: nil, extra_headers: headers)
end

def invoke_patch(path, authorization, request = nil)
invoke(:patch, path, authorization, request, nil, params: nil)
def invoke_patch(path, authorization, request = nil, headers = nil)
invoke(:patch, path, authorization, request, nil, params: nil, extra_headers: headers)
end

def invoke_delete(path, authorization)
Expand Down Expand Up @@ -66,18 +66,45 @@ def default_headers(authorization)
Authorization: authorization.authorization_header }
end

# Map a typed headers container (e.g. {CheckoutSdk::Common::Headers}) onto the underlying
# HTTP header hash. Each attribute that's set is emitted as the corresponding
# canonical HTTP header.
# Attribute name to HTTP header name, for every typed headers container the SDK supports.
#
# The header names are case sensitive in the spec: return-encrypted-cvv is lower case where a
# naive conversion would produce Return-Encrypted-Cvv.
#
# The values are Strings, not Symbols, and that is load bearing. Faraday::Utils::Headers
# preserves a String key verbatim but rewrites a Symbol key as
# `key.to_s.split('_').map(&:capitalize).join('-')`, so :'return-encrypted-cvv' would reach
# the wire as Return-encrypted-cvv and :'Encryption-Key' as Encryption-key. Strings are the
# only way to send the spelling the spec asks for. As a side effect this also stops If-Match
# being sent as If-match, which it was before.
EXTRA_HEADER_NAMES = {
if_match: 'If-Match',
accept: 'Accept',
return_encrypted_cvv: 'return-encrypted-cvv',
encryption_key: 'Encryption-Key'
}.freeze
private_constant :EXTRA_HEADER_NAMES

# Map a typed headers container (e.g. {CheckoutSdk::Common::Headers},
# {CheckoutSdk::Issuing::CardUpdateHeaders}) onto the underlying HTTP header hash. Each
# attribute that is set is emitted as the corresponding HTTP header.
#
# Previously a hand-written if/return chain. That shape had a latent trap: it ended with
# `return unless extra_headers.respond_to?(:accept) && extra_headers.accept`, so any header
# handled after that point was dead code for every container without an `accept` attribute.
# Iterating an explicit map removes the trap and keeps the existing If-Match and Accept
# behaviour byte for byte.
def apply_extra_headers(http_headers, extra_headers)
return if extra_headers.nil?

if extra_headers.respond_to?(:if_match) && extra_headers.if_match
http_headers[:'If-Match'] = extra_headers.if_match
end
return unless extra_headers.respond_to?(:accept) && extra_headers.accept
EXTRA_HEADER_NAMES.each do |attribute, header_name|
next unless extra_headers.respond_to?(attribute)

value = extra_headers.public_send(attribute)
next if value.nil? || value.to_s.empty?

http_headers[:Accept] = extra_headers.accept
http_headers[header_name] = value
end
end

def append_params(path, input_params)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class AddressDocumentVerificationClient < Client
ANONYMIZE = 'anonymize'
ATTEMPTS = 'attempts'
PDF_REPORT = 'pdf-report'
private_constant :ADDRESS_DOCUMENT_VERIFICATIONS, :ANONYMIZE, :ATTEMPTS, :PDF_REPORT
ASSETS = 'assets'
private_constant :ADDRESS_DOCUMENT_VERIFICATIONS, :ANONYMIZE, :ATTEMPTS, :PDF_REPORT, :ASSETS

# @param [ApiClient] api_client
# @param [CheckoutConfiguration] configuration
Expand Down Expand Up @@ -49,11 +50,19 @@ def create_address_document_verification_attempt(address_document_verification_i
)
end

# Get the details of all attempts for a specific address document verification.
#
# Results are paginated. Beta.
#
# @param [String] address_document_verification_id
def get_address_document_verification_attempts(address_document_verification_id)
# @param [Hash, CheckoutSdk::Identities::IdvAttemptsQueryFilter, nil] query pagination
# query parameters; supports :skip (Integer, default: 0) and :limit (Integer, default: 10)
# @return [OpenStruct] the paginated attempt list
def get_address_document_verification_attempts(address_document_verification_id, query = nil)
api_client.invoke_get(
build_path(ADDRESS_DOCUMENT_VERIFICATIONS, address_document_verification_id, ATTEMPTS),
sdk_authorization
sdk_authorization,
query
)
end

Expand All @@ -73,6 +82,26 @@ def get_address_document_verification_pdf_report(address_document_verification_i
sdk_authorization
)
end

# Get the assets (the document image) uploaded for a address document verification attempt.
#
# Results are paginated. Beta.
#
# @param [String] address_document_verification_id
# @param [String] attempt_id
# @param [Hash, CheckoutSdk::Identities::IdvAttemptAssetsQueryFilter, nil] query pagination
# query parameters; supports :skip (Integer, default: 0) and :limit (Integer, default: 10)
# @return [OpenStruct] the paginated asset list
def get_address_document_verification_attempt_assets(address_document_verification_id,
attempt_id,
query = nil)
api_client.invoke_get(
build_path(ADDRESS_DOCUMENT_VERIFICATIONS, address_document_verification_id,
ATTEMPTS, attempt_id, ASSETS),
sdk_authorization,
query
)
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,21 @@ module AddressDocumentVerification
# Request body for POST /address-document-verifications.
#
# @!attribute applicant_id
# @return [String] The applicant's unique identifier. [Required] Pattern: ^aplt_\w+$
# The applicant's unique identifier.
# [Required]
# ^aplt_\w+$
# @return [String]
# @!attribute user_journey_id
# @return [String] Your configuration ID. [Required] Pattern: ^usj_[a-z2-7]{26}$
# Your configuration ID.
# [Required]
# ^usj_[a-z2-7]{26}$
# @return [String]
# @!attribute declared_data
# @return [IdvDeclaredData, Hash] The personal details provided by the applicant. [Optional]
# The personal details provided by the applicant. The address document verification
# request takes the narrower two field IdvDeclaredData shape, not the identity
# verification one.
# [Optional]
# @return [CheckoutSdk::Identities::IdentityVerification::IdvDeclaredData]
class AddressDocumentVerificationRequest
attr_accessor :applicant_id,
:user_journey_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,22 @@ module FaceAuthentication
# Request body for POST /face-authentications/{id}/attempts.
#
# @!attribute redirect_url
# @return [String] URL to redirect the applicant after the attempt.
# The URL to redirect the applicant to after the attempt.
# [Required]
# Format: uri
# @return [String]
# @!attribute phone_number
# The applicant's mobile phone number, if sharing the attempt URL via SMS.
# [Optional]
# @return [CheckoutSdk::Identities::IdvPhoneNumber]
# @!attribute client_information
# The applicant's details. The face authentication attempt takes the narrower
# FavClientInformation shape, which declares neither document field, so this is
# deliberately the parent class and not IdvIdentityClientInformation.
# [Optional]
# @return [CheckoutSdk::Identities::IdentityVerification::IdvClientInformation]
class FaceAuthenticationAttemptRequest
attr_accessor :redirect_url, :client_information
attr_accessor :redirect_url, :phone_number, :client_information
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,19 @@ def create_face_authentication_attempt(face_authentication_id, attempt_request)
)
end

# Get the details of all attempts for a specific face authentication.
#
# Results are paginated. Beta.
#
# @param [String] face_authentication_id
def get_face_authentication_attempts(face_authentication_id)
# @param [Hash, CheckoutSdk::Identities::IdvAttemptsQueryFilter, nil] query pagination
# query parameters; supports :skip (Integer, default: 0) and :limit (Integer, default: 10)
# @return [OpenStruct] the paginated attempt list
def get_face_authentication_attempts(face_authentication_id, query = nil)
api_client.invoke_get(
build_path(FACE_AUTHENTICATIONS, face_authentication_id, ATTEMPTS),
sdk_authorization
sdk_authorization,
query
)
end

Expand All @@ -67,8 +75,8 @@ def get_face_authentication_attempt(face_authentication_id, attempt_id)
# Retrieve the assets (face images and videos) captured during a face authentication attempt.
# @param [String] face_authentication_id
# @param [String] attempt_id
# @param [Hash, nil] query pagination query parameters; supports :skip (Integer, default: 0)
# and :limit (Integer, default: 10)
# @param [Hash, CheckoutSdk::Identities::IdvAttemptAssetsQueryFilter, nil] query pagination
# query parameters; supports :skip (Integer, default: 0) and :limit (Integer, default: 10)
def get_face_authentication_attempt_assets(face_authentication_id, attempt_id, query = nil)
api_client.invoke_get(
build_path(FACE_AUTHENTICATIONS, face_authentication_id, ATTEMPTS, attempt_id, ASSETS),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,33 @@ module Identities
module FaceAuthentication
# Request body for POST /face-authentications.
#
# Realigned with the spec on 2026-09-21. This class omitted user_journey_id, which
# FavFaceAuthentication declares and requires, and declared external_reference and
# redirect_url, which it does not. The two invented attributes are retained rather than
# removed, so no caller breaks, and are scheduled for removal in a future major; the API
# ignores them.
#
# @!attribute applicant_id
# The applicant's unique identifier.
# [Required]
# ^aplt_\w+$
# @return [String]
# @!attribute user_journey_id
# Your configuration ID.
# [Required]
# ^usj_[a-z2-7]{26}$
# @return [String]
# @!attribute external_reference
# @deprecated Not declared by FavFaceAuthentication. Never sent by the API and ignored if
# supplied. Scheduled for removal in a future major.
# @return [String]
# @!attribute redirect_url
# @deprecated Not declared by FavFaceAuthentication. The redirect URL belongs on the
# attempt request, not the face authentication. Scheduled for removal in a future major.
# @return [String]
class FaceAuthenticationRequest
attr_accessor :applicant_id,
:user_journey_id,
:external_reference,
:redirect_url
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class IdDocumentVerificationClient < Client
ANONYMIZE = 'anonymize'
ATTEMPTS = 'attempts'
PDF_REPORT = 'pdf-report'
private_constant :ID_DOCUMENT_VERIFICATIONS, :ANONYMIZE, :ATTEMPTS, :PDF_REPORT
ASSETS = 'assets'
private_constant :ID_DOCUMENT_VERIFICATIONS, :ANONYMIZE, :ATTEMPTS, :PDF_REPORT, :ASSETS

# @param [ApiClient] api_client
# @param [CheckoutConfiguration] configuration
Expand Down Expand Up @@ -47,11 +48,19 @@ def create_id_document_verification_attempt(id_document_verification_id, attempt
)
end

# Get the details of all attempts for a specific ID document verification.
#
# Results are paginated. Beta.
#
# @param [String] id_document_verification_id
def get_id_document_verification_attempts(id_document_verification_id)
# @param [Hash, CheckoutSdk::Identities::IdvAttemptsQueryFilter, nil] query pagination
# query parameters; supports :skip (Integer, default: 0) and :limit (Integer, default: 10)
# @return [OpenStruct] the paginated attempt list
def get_id_document_verification_attempts(id_document_verification_id, query = nil)
api_client.invoke_get(
build_path(ID_DOCUMENT_VERIFICATIONS, id_document_verification_id, ATTEMPTS),
sdk_authorization
sdk_authorization,
query
)
end

Expand All @@ -71,6 +80,27 @@ def get_id_document_verification_pdf_report(id_document_verification_id)
sdk_authorization
)
end

# Get the assets (the front and back images of the document) uploaded for an ID document
# verification attempt.
#
# Results are paginated. Beta.
#
# @param [String] id_document_verification_id
# @param [String] attempt_id
# @param [Hash, CheckoutSdk::Identities::IdvAttemptAssetsQueryFilter, nil] query pagination
# query parameters; supports :skip (Integer, default: 0) and :limit (Integer, default: 10)
# @return [OpenStruct] the paginated asset list
def get_id_document_verification_attempt_assets(id_document_verification_id,
attempt_id,
query = nil)
api_client.invoke_get(
build_path(ID_DOCUMENT_VERIFICATIONS, id_document_verification_id,
ATTEMPTS, attempt_id, ASSETS),
sdk_authorization,
query
)
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,48 @@ module Identities
module IdDocumentVerification
# Request body for POST /id-document-verifications.
#
# Realigned with the spec on 2026-09-21. This class previously declared
# external_reference, document_type, country and redirect_url, none of which
# IddvIdDocumentVerification declares, and omitted user_journey_id and declared_data, which
# it does. The four invented attributes are retained rather than removed, so no caller
# breaks, and are scheduled for removal in a future major; the API ignores them.
#
# @!attribute applicant_id
# The applicant's unique identifier.
# [Required]
# ^aplt_\w+$
# @return [String]
# @!attribute user_journey_id
# Your configuration ID.
# [Optional]
# ^usj_[a-z2-7]{26}$
# @return [String]
# @!attribute declared_data
# The personal details provided by the applicant. The ID document verification request
# takes the narrower two field IdvDeclaredData shape.
# [Optional]
# @return [CheckoutSdk::Identities::IdentityVerification::IdvDeclaredData]
# @!attribute external_reference
# @deprecated Not declared by IddvIdDocumentVerification. Never sent by the API and
# ignored if supplied. Scheduled for removal in a future major.
# @return [String]
# @!attribute document_type
# @deprecated Not declared by IddvIdDocumentVerification. The document type is chosen by
# the applicant during the attempt and returned on the response, not sent on the
# request. Scheduled for removal in a future major.
# @return [String]
# @!attribute country
# @deprecated Not declared by IddvIdDocumentVerification. Scheduled for removal in a
# future major.
# @return [String]
# @!attribute redirect_url
# @deprecated Not declared by IddvIdDocumentVerification. The redirect URL belongs on the
# attempt request, not the verification. Scheduled for removal in a future major.
# @return [String]
class IdDocumentVerificationRequest
attr_accessor :applicant_id,
:user_journey_id,
:declared_data,
:external_reference,
:document_type,
:country,
Expand Down
8 changes: 8 additions & 0 deletions lib/checkout_sdk/identities/identities.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# frozen_string_literal: true

# Shared identities types
require 'checkout_sdk/identities/idv_phone_number'
require 'checkout_sdk/identities/idv_address'
require 'checkout_sdk/identities/idv_attempts_query_filter'
require 'checkout_sdk/identities/idv_attempt_assets_query_filter'

# Applicants
require 'checkout_sdk/identities/applicants/create_applicant_request'
require 'checkout_sdk/identities/applicants/update_applicant_request'
Expand All @@ -21,7 +27,9 @@

# Identity Verification
require 'checkout_sdk/identities/identity_verification/idv_declared_data'
require 'checkout_sdk/identities/identity_verification/idv_identity_declared_data'
require 'checkout_sdk/identities/identity_verification/idv_client_information'
require 'checkout_sdk/identities/identity_verification/idv_identity_client_information'
require 'checkout_sdk/identities/identity_verification/identity_verification_attempt_request'
require 'checkout_sdk/identities/identity_verification/identity_verification_request'
require 'checkout_sdk/identities/identity_verification/identity_verification_client'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,21 @@ module IdentityVerification
# Request body for POST /identity-verifications/{id}/attempts.
#
# @!attribute redirect_url
# @return [String] URL to redirect the applicant after the attempt.
# The URL to redirect the applicant to after the attempt.
# [Required]
# Format: uri
# @return [String]
# @!attribute phone_number
# The applicant's mobile phone number, if sharing the attempt URL via SMS.
# [Optional]
# @return [CheckoutSdk::Identities::IdvPhoneNumber]
# @!attribute client_information
# @return [IdvClientInformation]
# The applicant's details. The identity verification attempt accepts the wider
# IdvClientInformation shape, unlike the face authentication attempt.
# [Optional]
# @return [IdvIdentityClientInformation]
class IdentityVerificationAttemptRequest
attr_accessor :redirect_url, :client_information
attr_accessor :redirect_url, :phone_number, :client_information
end
end
end
Expand Down
Loading
Loading