Gap Analysis: Stage 6 (Bank Verification) & Stage 7 (Liveness / Face Match)

Generated: 2026-04-01 | Old: BankRepository.cs, NRIBankRepository.cs, BankAPI.cs, FundTransferAPI.cs, LivePhotoAPI.cs + SPs | New: BankVerificationService.cs, LivenessService.cs, ExternalProviders/Bank/*, ExternalProviders/Liveness/*, ExternalProviders/Face/*

Executive Summary

Stage 6 (Bank): Core flow (IFSC lookup with cache + DB + fallback, penny drop via Karza provider, reverse penny drop initiate/complete, name match with STP/NON_STP/DROPPED scoring, attempt limits, penny drop rate limit, bank data cleanup on retry, provider config resolution) is PRESENT in new code. Key gaps: YesBank IMPS penny drop, YPP SDK flow, NRI bank flow, bank proof OCR, closed account handling, multi-provider name match, IndusInd no-penny update, MICR-by-branch lookup.

Stage 7 (Liveness): Core flow (geolocation, vendor selection, liveness callback, face match, STP scoring, S3 selfie storage, Aadhaar photo deletion, max attempts + CS hold) is PRESENT. Key gaps: HyperVerge liveness provider, AiNXT short-link, IPV status check, branch IPV fallback, NRI bypass, live photo/geolocation config flags.

Stage 6: Bank Verification

#Old Function / LogicOld FileNew EquivalentStatusGap Details
1IFSC lookup via SP (USP_GETBANKLIST_BY_IFSC_SJET) returns BANKLISTDETAILS + BANKLISTFLAG BankRepository.cs:54-141 BankVerificationService.LookupIfscAsync → DB bank_ifsc_master + in-memory BankCodeMap fallback + Redis cache PRESENTNew uses EF query on BankIfscMaster table instead of SP. Falls back to static map of 20 major banks. BANKLISTFLAG second table not replicated.
2MICR code lookup by IFSC (USP_GET_MICR_BASED_ON_IFSC_SJET) BankRepository.cs:313-458 BankVerificationService.LookupIfscAsync returns MicrCode from BankIfscMaster or GenerateMicr() PRESENTMICR returned as part of IFSC lookup. Synthetic MICR generation from hash is placeholder; old SP returned real RBI MICR.
3MICR lookup by bank name + branch (USP_GET_MICR_BASED_ON_BANKBRANCH_SJET) BankRepository.cs:460-508 N/A MISSINGOld allowed branch-based MICR lookup when IFSC unknown. New only supports IFSC-based lookup.
4Bank list dropdown (USP_GETBANKLIST_SJET) BankRepository.cs:511-547 N/A (IFSC-first UX) N/AOld returned full bank list for dropdown. New uses IFSC-first approach; bank list not needed.
5Config-driven penny drop toggle: GetSettingValuePennydrop("PENNYDROP_API") returns YESBANK or KARZA BankAPI.cs:137-141 BankVerificationService.ResolveProviderFromConfigAsync reads provider_configurations table PARTIALNew resolves from provider_configurations by priority. But old toggle switched between YesBank IMPS vs Karza as distinct code paths; new only has Karza + Setu + YesBank providers without the if/else toggle pattern.
6YesBank IMPS penny drop (SOAP XML, X509 cert auth, separate hosting) BankAPI.cs:437-838 YesBankImpsProvider.cs (stub) PARTIALProvider file exists but SOAP XML, X509 cert, IBM headers, COMPLETED/SOCKETTIMEOUT parsing not implemented.
7Karza penny drop API (REST, x-karza-key header, statusCode 101 parse, bankTxnStatus) BankAPI.cs:939-1040 KarzaBankProvider.VerifyBankAccountAsync PRESENTKarzaBankProvider exists with proper REST integration. Maps to IBankVerificationProvider interface.
8Karza dedup check (USP_KARZA_DEDUP_CHECK_SJET) before re-calling Karza BankAPI.cs:847-857 BankVerificationService checks pennyDropAttemptsForAccount count PARTIALOld did SP-level dedup by accno+ifsc to avoid re-calling Karza. New checks attempt count but not exact Karza-specific dedup.
9Penny drop rate limit (USP_ALLOW_PENNYDROP_SJET + USP_ALLOW_KARZA_PENNYDROP_SJET) BankAPI.cs:139,178 BankVerificationService: pennyDropAttemptsForAccount >= 10 PRESENTNew checks max 10 attempts per account hash. Old had separate SPs for YesBank vs Karza limits.
10Bank name match: multi-provider (SP=1, AMAZONAWS=2, PYTHONLOGIC=3, AINXT=5) BankAPI.cs:236-303 BankRepository.cs:1340-1397 NameMatchService.CalculateScore (single algorithm) PARTIALOld had 4 switchable name match providers. New uses single service. AiNXT %-based scoring, AMAZONAWS, PYTHONLOGIC not available.
11STP flag insert with percentage (InsertUpdateSTPFlagPER) for AiNXT name match BankRepository.cs:1385-1388 BankVerificationService stores NameMatchScore + StpBankFlag on BankAccount entity PARTIALNew stores score+flag on entity. Old SP had separate percentage-based threshold logic in DB. The threshold evaluation is now in EvaluateNameMatchResult (code-side).
12Bank name empty handling: delete bank data + return error (USP_DELETE_BANK_DATA_NAMENOTFOUND_SJET) BankRepository.cs:1312-1333 BankVerificationService: if bankResult.AccountHolderName is null/empty, returns error PARTIALNew returns error but does not delete the bank data record. Old called USP_DELETE_BANK_DATA_NAMENOTFOUND_SJET to clean up.
13Delete bank data on name mismatch (USP_DELETE_BANK_DATA_NAMEMISMATCH_SJET) USP_DELETE_BANK_DATA_NAMEMISMATCH_SJET BankVerificationService.CleanupPreviousBankDataAsync resets StpBankFlag on old records PARTIALNew resets STP flag but does not delete. Old physically deleted bank data rows on name mismatch.
14Closed/rejected bank account handling (KC07 status → USP_DELETE_CLOSED_BANK_DATA_SJET) BankRepository.cs:1275-1293 N/A MISSINGOld detected Karza KC07 (closed account) and deleted bank data + returned specific error. New does not handle closed account status codes from provider.
15Invalid account exists check (USP_INVALID_ACCOUNT_EXISTS_SJET) on YesBank penny drop failure BankRepository.cs:1196-1257 N/A MISSINGOld checked if invalid account already exists and rolled back bank details. Not present in new code.
16Reverse penny drop: HyperVerge token generation (auth API, workflowId, bank alliance flag) BankRepository.cs:1664-1801 InitiateReversePennyAsync + HypervergeRpdProvider PARTIALNew generates SDK token + caches session. Old called HyperVerge auth API, selected workflowId by app version, checked BankAlliance flag. Auth token flow not fully replicated.
17Reverse penny drop: save bank details + alliance validation SP BankRepository.cs:1805-1860 CompleteReversePennyAsync → VerifyBankAccountAsync PARTIALNew reuses VerifyBankAccountAsync. Old had separate alliance validation SP. Alliance flag check missing.
18YPP SDK: bank list fetch (GET_UPI_BANK_LIST) with RSA encryption BankRepository.cs:845-1073 N/A MISSINGEntire YPP flow: RSA encrypted req/resp, partner key per app, bank list fetch + DB cache. Not in new code.
19YPP SDK: bank account fetch (GET_BANK_ACCOUNT_LIST) BankRepository.cs:600-843 N/A MISSINGYPP account details with encryption, decryption, USP_INSERT_YPP_ACCOUNTDETAILS. Not in new code.
20YPP SDK log insert + response (USP_INSERT_YPPTOKEN_SDK_LOG, USP_INSERT_YPPTOKEN_RESPONSE_LOG_SJET) BankRepository.cs:201-310 N/A MISSINGYPP token logging. Dependent on YPP flow (item 18/19).
21GetBankDetails: penny flag + standalone penny drop + get details SP (USP_GET_BANK_DETAILS_SJET) BankRepository.cs:1502-1662 GetBankDetailsAsync returns BankAccount entity PARTIALOld: call penny flag SP, trigger penny drop, IndusInd update, then get BANKDETAILS+BANKPROOFDETAILS+AnnualIncome. New returns single entity.
22IndusInd no-penny-drop PAN name update (USP_UPDATE_BANKPENNYDETAILS_INDUSIND_SJET) BankRepository.cs:1537-1548 N/A MISSINGOld updated bank penny details with PAN name for IndusInd when CALLNOPENNYAPI=1. Not in new code.
23IMPS status check (GET_IMPS_STATUS) after bank insert to update PENNYDROPFAIL flag BankRepository.cs:1436-1455 N/A MISSINGOld checked IMPS verification status post-insert and updated PENNYDROPFAIL flag on response. New does not have this check.
24Delete bank proof (USP_DELETE_BANK_DETAILS_SJET) + cheque proof deletion on new account BankRepository.cs:143-198 N/A (no cheque proof concept) MISSINGOld deleted bank proof and cheque image on re-submit. New has no bank proof upload/delete concept.
25Bank proof OCR via AiNXT (USP_AINXT_BANKPROOFOCR_RESPONSE_SJET) USP_AINXT_BANKPROOFOCR_RESPONSE_SJET AinxtBankOcrProvider.cs + DigitapOcrProvider.cs (stubs exist) PARTIALProvider files exist but service-level integration (cheque scan, OCR result save) not wired in BankVerificationService.
26NRI bank flow: NRO/NRE insert/update/get with PIS, SWIFT, beneficiary NRIBankRepository.cs:36-214 N/A MISSINGEntire NRI bank flow (NRO/NRE, PIS permission, RBI ref, SWIFT, beneficiary names, 6-table get, NRI MICR) not in new code.
27Fund transfer (Razorpay + Epay) for reverse penny FundTransferAPI.cs:237-332 N/A N/APost-account-opening fund transfer, not eKYC bank verification. Out of scope.
28PANSITE bank name check (USP_CHECK_PANSITE_BANK_NAME_SJET) when already verified BankAPI.cs:164-175,207-219 N/A MISSINGOld called this SP when penny drop was already done to re-check PAN name against bank name. Not in new code.
29Reverse penny input logging (INSERT_REVERSEPENNY_INPUT_LOGS_SJET) INSERT_REVERSEPENNY_INPUT_LOGS_SJET BankVerificationService logs to journey tracker + stage events PARTIALNew logs via RecordStageEventAsync. Old had dedicated SP for rev penny input log. Audit trail covered differently.

Stage 7: Liveness & Face Match

#Old Function / LogicOld FileNew EquivalentStatusGap Details
1AiNXT liveness token request API (faceLivelinessRequestId, refId, sourceCode) LivePhotoAPI.cs:1395-1459 LivenessService.InitiateLivenessAsync + AinxtLivenessProvider.RequestTokenAsync PRESENTAinxtLivenessProvider exists. Service generates session ID and selects vendor. Token request flow mapped.
2AiNXT short link liveness request (AINXTRequestAPI_ShortLink) LivePhotoAPI.cs:1461-1523 N/A MISSINGOld had a short-link variant for desktop/web flows. Not replicated; new assumes mobile SDK-based flow only.
3AiNXT get image API (unique_id → image content, lat/lng/city/state/country) LivePhotoAPI.cs:1525-1632 AinxtLivenessProvider.GetLiveImageAsync + LivenessService callback PARTIALNew has GetLiveImageAsync interface. But old code also did OpenCage reverse geocoding inline when city/state/country missing from AiNXT response + inserted opencage log SP. New handles geocoding separately in ResolveGeolocationAsync.
4OpenCage reverse geocoding (when AiNXT returns lat/lng but no city/state) LivePhotoAPI.cs:1559-1600 LivenessService.ResolveGeolocationAsync + OpenCageProvider (in ExternalProviders/Geocoding/) PRESENTOpenCageProvider exists. New also has AinxtGeocodingProvider. Coordinate-based city fallback also present.
5AiNXT live photo response save (USP_AINXT_LIVEPHOTO_RESPONSE_DETAILS_SJET) with image, coords, status USP_AINXT_LIVEPHOTO_RESPONSE_DETAILS_SJET LivenessService saves to LivenessVerification entity (GeolocationCity/Country/Lat/Lng, SelfieS3Key) PARTIALNew stores in EF entity. Old SP stored image content, ip_address, transactionIdHV. Image stored in S3 in new (not DB). IP address not tracked.
6HyperVerge liveness token generation (appId, appKey, expiry=600) LivePhotoAPI.cs:1698-1773 LivenessService selects HYPERVERGE vendor; actual token via ILivenessProvider PARTIALVendor selection present (DetermineLivenessVendor). But no dedicated HypervergeLivenessProvider in ExternalProviders/Liveness/ (only AinxtLivenessProvider). HyperVerge token generation API call missing.
7HyperVerge liveness log SP (USP_EKYC_HV_LIVEPHOTO_LOG_SJET) USP_EKYC_HV_LIVEPHOTO_LOG_SJET ApiAuditLogger (generic audit) + RecordStageEventAsync PARTIALNew uses generic audit logging. Old had HV-specific log SP. Fields like TOKEN stored in old; new logs via events.
8HyperVerge live photo response insert (TOKEN, TranId, FileData, Score, Live, ToBeReviewed, AttemptsCount) LivePhotoAPI.cs:1775-1803 LivenessService.ProcessLivenessCallbackAsync stores on LivenessVerification entity PARTIALNew stores LivenessPassed, FaceMatchScore, LivenessAttempts, SelfieS3Key. Old stored Score, Live flag, ToBeReviewed flag, raw FileData. ToBeReviewed not tracked in new.
9Geolocation boundary check (India lat/lng validation) LivePhotoAPI.cs:1559-1600 USP_GET_GEOLOCATION_FLAG_SJET LivenessService.ResolveGeolocationAsync: lat 6-37, lng 68-98 check PRESENTCoordinate-based India check present. Old also had USP_GET_GEOLOCATION_FLAG_SJET for DB-driven flag; new uses hardcoded bounds + geocoding provider.
10Location exception whitelist (PAN-based bypass for users outside India) TBL_LIVE_PHOTO_LOCATION_EXCEPTION LivenessService.InitiateLivenessAsync: LocationExceptionWhitelist table check PRESENTNew checks LocationExceptionWhitelist by PanHash. Matches old TBL_LIVE_PHOTO_LOCATION_EXCEPTION concept.
11City whitelist validation (TBL_LIVEPHOTO_LOCATION_DETAILS_CITYLIST) Implicit in geolocation flow LivenessService: CityMaster check in ResolveGeolocationAsync PRESENTNew checks city_master table. Non-blocking (logs warning). Old used city list for validation.
12Face match via AiNXT Face API (USP_INSERT_AINXT_FACEAPI_REQUEST_SJET, USP_INSERT_AINXT_FACEAPI_RESPONSE_SJET) USP_INSERT_AINXT_FACEAPI_REQUEST_SJET + USP_INSERT_AINXT_FACEAPI_RESPONSE_SJET AinxtFaceMatchProvider.MatchFacesAsync + IFaceMatchProvider interface PRESENTAinxtFaceMatchProvider + HypervergeFaceMatchProvider + DigioFaceMatchProvider all exist. Request/response logging via ApiAuditLogger.
13Face match STP/NON_STP threshold scoring Implicit in SPs and service logic LivenessService.PerformFaceMatchAsync: score >= _faceMatchStpMin (70) = STP, >= 1 = NON_STP, 0 on attempt 2 = DROPPED PRESENTConfig-driven threshold (Journey:FaceMatchStpMinScore=70). Three-tier scoring: STP, NON_STP, DROPPED.
14Face match service selection SP (USP_GET_FACE_MATCH_SERVICE_SJET) USP_GET_FACE_MATCH_SERVICE_SJET ProviderChainExecutor resolves provider by priority from provider_configurations PARTIALNew uses provider_configurations + circuit breaker. Old SP returned specific face match service per user. Config-per-user granularity missing.
15IPV status check (USP_CHECK_IPV_STATUS_SJET) USP_CHECK_IPV_STATUS_SJET N/A MISSINGIn-Person Verification status check not present. Old checked if IPV was already completed to skip liveness.
16Live photo flag from config (USP_GET_LIVEPHOTO_FLAG_SJET) USP_GET_LIVEPHOTO_FLAG_SJET N/A (liveness always required) MISSINGOld had config flag to enable/disable live photo requirement per user/segment. New always requires liveness.
17Other option (branch IPV) flag (USP_GET_OTHEROPTION_LIVEPHOTO_FLAG_SJET) LivePhotoAPI.cs:1676-1696 N/A MISSINGOld showed "other option" (visit branch for IPV) when live photo failed. ISSHOWOTHERPHOTOUPLOADOPTION flag. Not in new code.
18NRI liveness bypass Implicit in journey flow N/A MISSINGOld NRI flow could bypass liveness for certain NRI categories. New has no NRI-specific bypass.
19Selfie photo storage (image_content in DB via SP) USP_AINXT_LIVEPHOTO_RESPONSE_DETAILS_SJET LivenessService.StoreSelfieToS3 (S3 storage) PRESENTNew stores in S3 (better). Old stored base64 image_content in DB.
20Aadhaar photo deletion post face match Implicit in service logic LivenessService: DeleteAadhaarPhotoFromS3 + sets AadhaarPhotoDeletedAt PRESENTNew properly deletes from S3 and timestamps. Good privacy compliance.
21Multiple liveness attempt handling (AttemptsCount tracked per user) LivePhotoAPI.cs:1775 (AttemptsCount param) LivenessService: LivenessAttempts + FaceMatchAttempts tracked, max limits enforced, CS hold on exhaustion PRESENTNew tracks separately: liveness attempts (max 3) and face match attempts (max 2). Better than old single counter.
22Geolocation flag SP (USP_GET_GEOLOCATION_FLAG_SJET) for per-user geo requirement USP_GET_GEOLOCATION_FLAG_SJET N/A (geolocation always checked) MISSINGOld had per-user flag to skip geolocation check. New always validates geolocation.
23AiNXT liveness request logging SP (USP_INSERT_AINXT_LIVEPHOTO_REQUEST) LivePhotoAPI.cs:1446 ApiAuditLogger + RecordStageEventAsync PARTIALNew uses generic audit. Old had specific SP with faceLivelinessRequestId, refId, sourceCode fields.
24OpenCage geocoding log (USP_INSERT_OPENCAGE_LOG_SJET) LivePhotoAPI.cs:1596 ApiAuditLogger logs geocoding calls PARTIALNew uses generic audit logging. Old had dedicated SP for OpenCage lat/lng/city/state/country/district.

Summary

Stage 6 Counts

PRESENT: 4 | PARTIAL: 10 | MISSING: 10 | N/A: 2 (of 29 items). Net coverage: ~48%

Stage 7 Counts

PRESENT: 8 | PARTIAL: 7 | MISSING: 6 | N/A: 0 (of 24 items). Net coverage: ~63%

Critical Gaps — Fix Status

#StageGapPriorityStatus
1S6NRI bank flow (SWIFT-based, no penny drop)HIGHFIXED — HandleNriBankVerificationAsync validates SWIFT code, stores with NRI_MANUAL method
2S6YesBank IMPS penny dropN/AEXCLUDED per product decision
3S6YPP SDK bank list/account flowMEDIUMOPEN — UPI-based path can be added later. Penny drop + RPD cover primary flows.
4S6Closed/rejected bank account handling (KC07)HIGHFIXED — Detects CLOSED/FROZEN accounts, deletes bank data, returns BANK_ACCOUNT_CLOSED
5S6Bank proof OCR (cheque scan)MEDIUMOPEN — Provider exists but not wired. Low priority since penny drop is primary path.
6S6Multi-provider name matchMEDIUMOPEN — Single Levenshtein algo. Can wire AiNXT name match API later via middleware vendor switch.
7S6Bank Alliance flagLOWOPEN — Alliance vertical out of scope
8S7HyperVerge liveness providerHIGHOPEN — Provider stub exists. Will be wired via middleware vendor switch config.
9S7IPV status checkMEDIUMFIXED — Checks existing LivenessVerification PASS record, skips re-initiation
10S7Branch IPV fallbackMEDIUMFIXED — CS hold with CS_LIVENESS_EXHAUSTED + BRANCH_IPV_FALLBACK on max attempts
11S7NRI liveness bypassHIGHFIXED — NRI routed to NRI_BRANCH_IPV, state set to LIVENESS_DONE
12S7Geolocation config flagLOWFIXED — ENABLE_GEOLOCATION_CHECK toggle via application_config
13S7HyperVerge ToBeReviewed flagLOWOPEN — Will be addressed when HyperVerge provider is implemented
+S6Bank data cleanup on name mismatchMEDIUMFIXED — Deletes bank records on DROPPED due to name mismatch
+S6Account number format validationMEDIUMFIXED — Validates 9-18 numeric digits before penny drop
+S7MOSL employee liveness bypassMEDIUMFIXED — Employee PAN detected, routes to EMPLOYEE_LIVENESS_BYPASS