feat(kyc): verify seller PAN and compare name with Tradhox Document Verification service
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 37s

This commit is contained in:
vickytechkey 2026-10-15 21:58:28 +05:30
parent 517563b9e5
commit 518dc812b9

View file

@ -2057,76 +2057,107 @@ class UploadEAadhaarView(APIView):
return Response({'error': 'Internal error verifying Aadhaar'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
class VerifyPANView(APIView):
permission_classes = [IsAuthenticated]
"""
POST /api/v1/profile/kyc/verify-pan/
Verifies seller PAN via the Tradhox Document Verification microservice,
compares seller's full legal name with the PAN cardholder name,
pulls all active GSTINs linked to this PAN, and updates the database.
Supports both onboarding sellers and authenticated users.
"""
permission_classes = [AllowAny]
def post(self, request):
pan_number = request.data.get('id_number')
if not pan_number:
return Response({'error': 'id_number is required'}, status=status.HTTP_400_BAD_REQUEST)
user = request.user
surepass_token = os.environ.get('SUREPASS_JWT_TOKEN')
if not surepass_token:
logger.warning("Surepass token not configured. Skipping actual PAN verification.")
# Mock success for local dev without token
mock_success_data = {
"pan_number": pan_number.upper(),
"full_name": "MOCK USER NAME",
"dob": "1990-01-01",
"gender": "M",
"status": "valid",
"aadhaar_linked": True,
}
kyc, _ = SellerKYC.objects.update_or_create(
supplier=user,
defaults={
'pan_number': mock_success_data['pan_number'],
'pan_full_name': mock_success_data['full_name'],
'pan_dob': mock_success_data['dob'],
'pan_status': mock_success_data['status'],
'pan_aadhaar_linked': mock_success_data['aadhaar_linked'],
'pan_verification_response': {"mock": True, "data": mock_success_data}
}
)
return Response({'success': True, 'kyc_data': mock_success_data})
url = "https://kyc-api.surepass.io/api/v1/pan/pan-with-details-v3"
headers = {
'Authorization': f'Bearer {surepass_token}',
'Content-Type': 'application/json'
}
payload = {
"id_number": pan_number
}
pan_number = request.data.get('pan_number') or request.data.get('pan') or request.data.get('id_number')
seller_name = request.data.get('seller_name') or request.data.get('full_name') or ''
entered_gstin = request.data.get('gstin', '')
try:
response = requests.request("POST", url, headers=headers, json=payload)
resp_json = response.json()
if response.status_code == 200 and resp_json.get('success'):
data = resp_json.get('data', {})
kyc, _ = SellerKYC.objects.update_or_create(
if not pan_number:
return Response({'error': 'pan_number is required'}, status=status.HTTP_400_BAD_REQUEST)
pan_number = pan_number.strip().upper()
user = request.user if getattr(request, 'user', None) and request.user.is_authenticated else None
if not seller_name and user:
seller_name = f"{user.first_name} {user.last_name}".strip() or user.username
# Target Microservice: Tradhox Document Verification Engine
doc_verify_urls = [
os.environ.get('DOC_VERIFICATION_URL', 'http://127.0.0.1:8092/api/verify/seller/'),
'https://beta-documentverification.tradhox.com/api/verify/seller/'
]
resp_json = None
resp_status = None
for endpoint in doc_verify_urls:
try:
resp = requests.post(
endpoint,
json={
'seller_name': seller_name,
'pan': pan_number,
'gstin': entered_gstin,
},
timeout=15,
)
resp_status = resp.status_code
resp_json = resp.json()
break
except Exception as e:
logger.warning(f"Could not reach document verification endpoint {endpoint}: {e}")
continue
if resp_json and resp_status == 200 and resp_json.get('is_success'):
data = resp_json.get('data', {})
pan_details = data.get('pan_details', {})
verified_name = data.get('verified_pan_name') or seller_name
# 1. Save response in SellerKYC and SupplierProfile database record if user is authenticated
if user:
SellerKYC.objects.update_or_create(
supplier=user,
defaults={
'pan_number': data.get('pan_number'),
'pan_full_name': data.get('full_name'),
'pan_dob': data.get('dob'),
'pan_status': data.get('status'),
'pan_aadhaar_linked': data.get('aadhaar_linked', False),
'pan_verification_response': resp_json
'pan_number': pan_number,
'pan_full_name': verified_name,
'pan_dob': pan_details.get('dob') or pan_details.get('date_of_birth', ''),
'pan_status': pan_details.get('status', 'valid'),
'pan_aadhaar_linked': pan_details.get('aadhaar_seeding_status') == 'LINKED',
'pan_verification_response': resp_json,
}
)
return Response({'success': True, 'kyc_data': data})
else:
return Response({
'success': False,
'error': resp_json.get('message', 'PAN Verification failed')
}, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
except Exception as e:
logger.error(f"Error calling Surepass PAN API: {e}")
return Response({'error': 'Internal error verifying PAN'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
profile, _ = SupplierProfile.objects.get_or_create(user=user)
if data.get('primary_gstin'):
profile.gstin = data['primary_gstin']
profile.is_gstin_verified = True
elif entered_gstin:
profile.gstin = entered_gstin
profile.is_gstin_verified = data.get('gstin_matched', False)
if verified_name:
profile.legal_entity_name = verified_name
profile.save()
return Response({
'success': True,
'name_matched': data.get('name_matched', True),
'match_score': data.get('match_score', 100.0),
'verified_pan_name': verified_name,
'seller_name': seller_name,
'pan_number': pan_number,
'gst_records': data.get('gst_records', []),
'primary_gstin': data.get('primary_gstin'),
'reference_id': resp_json.get('reference_id'),
'kyc_data': pan_details,
})
elif resp_json:
error_msg = resp_json.get('error_message') or 'PAN verification or name matching failed'
return Response({
'success': False,
'name_matched': resp_json.get('name_matched', False),
'error': error_msg,
'data': resp_json.get('data', {})
}, status=resp_status if resp_status in [400, 422] else status.HTTP_422_UNPROCESSABLE_ENTITY)
else:
return Response({'error': 'Document verification service unavailable'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)
class ProductSearchView(APIView):