cms
Showing
7 changed files
with
254 additions
and
5 deletions
... | @@ -1626,4 +1626,60 @@ CA_COMPARE_FIELD = { | ... | @@ -1626,4 +1626,60 @@ CA_COMPARE_FIELD = { |
1626 | DL_EN: (DL_OCR_FIELD, CA_DL_COMPARE_LOGIC, False), | 1626 | DL_EN: (DL_OCR_FIELD, CA_DL_COMPARE_LOGIC, False), |
1627 | } | 1627 | } |
1628 | 1628 | ||
1629 | # ------------------CMS-------------------------------------- | ||
1630 | BANK_INFO_MAP = ( | ||
1631 | ('accountNo', 'bankAccountDetails.accountNo'), | ||
1632 | ('bankName', 'bankAccountDetails.bankName'), | ||
1633 | ('accountHolderName', 'bankAccountDetails.accountHolderName'), | ||
1634 | ) | ||
1635 | |||
1636 | VEHICLE_INFO_MAP = ( | ||
1637 | ('vehicleStatus', 'vehicleStatus'), | ||
1638 | ('vinNo', 'vehicleInformation.vinNo'), | ||
1639 | ('dealer', 'dealerName'), | ||
1640 | ('vehicleTransactionAmount', 'totalFinanceAmount'), | ||
1641 | ) | ||
1642 | |||
1643 | CORPORATE_INFO_MAP = ( | ||
1644 | ('firstIdType', ), | ||
1645 | ('firstIdNo', ), | ||
1646 | ('companyName', ), | ||
1647 | ('legalRepName', ), | ||
1648 | ('businessLicenseNo', ), | ||
1649 | ('organizationCreditCode', ), | ||
1650 | ('taxRegistrationCertificateNo', ), | ||
1651 | ('establishmentDate', ), | ||
1652 | ('businessLicenseDueDate', ), | ||
1653 | ) | ||
1654 | |||
1655 | INDIVIDUAL_INFO_MAP = ( | ||
1656 | ('applicantType', 'applicantInformation.applicantType'), | ||
1657 | ('customerType', 'applicantInformation.customersubType'), | ||
1658 | |||
1659 | ('idType', 'applicantInformation.IDInformation.idType'), | ||
1660 | ('customerName', 'applicantInformation.name'), | ||
1661 | ('idNum', 'applicantInformation.IDInformation.idNum'), | ||
1662 | ('dateOfBirth', 'applicantInformation.dateOfBirth'), | ||
1663 | ('idExpiryDate', 'applicantInformation.IDInformation.idExpiryDate'), | ||
1664 | ('hukouProvince', ), | ||
1665 | ('hukouCity', ), | ||
1629 | 1666 | ||
1667 | ('secondIdType', 'applicantInformation.IDInformation.idType'), | ||
1668 | ('secondIdNum', 'applicantInformation.IDInformation.idNum'), | ||
1669 | |||
1670 | ('companyName', ), | ||
1671 | ('registeredCapital', ), | ||
1672 | ('selfEmployedSubType', ), | ||
1673 | ) | ||
1674 | |||
1675 | CMS_TO_POS = [ | ||
1676 | ('bank_info', BANK_INFO_MAP), | ||
1677 | ('vehicle_info', VEHICLE_INFO_MAP), | ||
1678 | ('corporate_cus_info', CORPORATE_INFO_MAP), | ||
1679 | ('individual_cus_info', INDIVIDUAL_INFO_MAP), | ||
1680 | ] | ||
1681 | |||
1682 | TENANT_MAP = { | ||
1683 | AFC_PREFIX: 1, | ||
1684 | HIL_PREFIX: 2, | ||
1685 | } | ||
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -13,9 +13,14 @@ class OCR2Exception(Exception): | ... | @@ -13,9 +13,14 @@ class OCR2Exception(Exception): |
13 | class OCR4Exception(Exception): | 13 | class OCR4Exception(Exception): |
14 | pass | 14 | pass |
15 | 15 | ||
16 | |||
16 | class LTGTException(Exception): | 17 | class LTGTException(Exception): |
17 | pass | 18 | pass |
18 | 19 | ||
19 | 20 | ||
20 | class GCAPException(Exception): | 21 | class GCAPException(Exception): |
21 | pass | 22 | pass |
23 | |||
24 | |||
25 | class CMSException(Exception): | ||
26 | pass | ... | ... |
src/apps/doc/ocr/cms.py
0 → 100644
1 | import requests | ||
2 | from settings import conf | ||
3 | from common.redis_cache import redis_handler as rh | ||
4 | from apps.doc.exceptions import CMSException | ||
5 | |||
6 | |||
7 | class CMS: | ||
8 | |||
9 | def __init__(self): | ||
10 | self.oauth_url = conf.CMS_OAUTH_URL | ||
11 | self.url = conf.CMS_URL | ||
12 | self.oauth_payload = { | ||
13 | 'grant_type': 'client_credentials', | ||
14 | 'client_id': conf.CMS_OAUTH_ID, | ||
15 | 'client_secret': conf.CMS_OAUTH_SECRET, | ||
16 | 'scope': conf.CMS_OAUTH_SCOPE | ||
17 | } | ||
18 | self.token_type = 'bearer' | ||
19 | self.token = None | ||
20 | self.token_key = 'access_token' | ||
21 | self.expires_key = 'expires_in' | ||
22 | self.token_type_key = 'token_type' | ||
23 | |||
24 | def update_token(self): | ||
25 | response = requests.post(self.oauth_url, data=self.oauth_payload, files=[]) | ||
26 | if response.status_code != 200: | ||
27 | raise CMSException('CMS Oauth response with code: {0}'.format(response.status_code)) | ||
28 | token = response.json().get(self.token_key) | ||
29 | if not isinstance(token, str): | ||
30 | raise CMSException('CMS Oauth can not get token: {0}'.format(response.json())) | ||
31 | self.token = token | ||
32 | self.token_type = response.json().get(self.token_type_key, self.token_type) | ||
33 | expires = response.json().get(self.expires_key, 3600) | ||
34 | rh.set_cms_token(self.token, expires) | ||
35 | |||
36 | def get_token(self): | ||
37 | if self.token is None: | ||
38 | self.token = rh.get_cms_token() | ||
39 | if self.token is None: | ||
40 | self.update_token() | ||
41 | return self.token | ||
42 | |||
43 | def send(self, payload): | ||
44 | token = self.get_token() | ||
45 | headers = { | ||
46 | 'Authorization': '{0} {1}'.format(self.token_type.capitalize(), token), | ||
47 | 'Content-Type': 'application/json', | ||
48 | } | ||
49 | response = requests.post(self.url, headers=headers, json=payload) | ||
50 | if response.status_code != 200: | ||
51 | raise CMSException('CMS Oauth response with code: {0}'.format(response.status_code)) | ||
52 | return response.json() | ||
53 | |||
54 | |||
55 | cms = CMS() | ||
56 | |||
57 | |||
58 | |||
59 |
... | @@ -1092,6 +1092,7 @@ class SECMSView(GenericView): | ... | @@ -1092,6 +1092,7 @@ class SECMSView(GenericView): |
1092 | @use_args(se_cms_args, location='data') | 1092 | @use_args(se_cms_args, location='data') |
1093 | def post(self, request, args): | 1093 | def post(self, request, args): |
1094 | 1094 | ||
1095 | |||
1095 | # 触发比对 | 1096 | # 触发比对 |
1096 | compare.apply_async((application_id, business_type, uniq_seq, None, False, True), | 1097 | compare.apply_async((application_id, business_type, uniq_seq, None, False, True), |
1097 | queue='queue_compare') | 1098 | queue='queue_compare') | ... | ... |
... | @@ -25,6 +25,7 @@ from apps.doc.models import ( | ... | @@ -25,6 +25,7 @@ from apps.doc.models import ( |
25 | ) | 25 | ) |
26 | from apps.doc import consts | 26 | from apps.doc import consts |
27 | from apps.doc.ocr.gcap import gcap | 27 | from apps.doc.ocr.gcap import gcap |
28 | from apps.doc.ocr.cms import cms | ||
28 | from apps.doc.exceptions import GCAPException | 29 | from apps.doc.exceptions import GCAPException |
29 | from apps.doc.named_enum import RequestTeam, RequestTrigger, ProcessName, ErrorType | 30 | from apps.doc.named_enum import RequestTeam, RequestTrigger, ProcessName, ErrorType |
30 | from common.tools.comparison import cp | 31 | from common.tools.comparison import cp |
... | @@ -35,6 +36,27 @@ empty_str = '' | ... | @@ -35,6 +36,27 @@ empty_str = '' |
35 | empty_error_type = 1000 | 36 | empty_error_type = 1000 |
36 | 37 | ||
37 | 38 | ||
39 | class FakePOS: | ||
40 | |||
41 | def __init__(self, | ||
42 | application_id, | ||
43 | first_submmison_date, | ||
44 | application_version, | ||
45 | customer_type, | ||
46 | individual_cus_info, | ||
47 | corporate_cus_info, | ||
48 | vehicle_info, | ||
49 | bank_info): | ||
50 | self.application_id = application_id | ||
51 | self.first_submmison_date = first_submmison_date | ||
52 | self.application_version = application_version | ||
53 | self.customer_type = customer_type | ||
54 | self.individual_cus_info = individual_cus_info | ||
55 | self.corporate_cus_info = corporate_cus_info | ||
56 | self.vehicle_info = vehicle_info | ||
57 | self.bank_info = bank_info | ||
58 | |||
59 | |||
38 | def name_check(ocr_res_dict, second_ocr_field, second_compare_list, second_id_num, name): | 60 | def name_check(ocr_res_dict, second_ocr_field, second_compare_list, second_id_num, name): |
39 | id_field = second_compare_list[1][1] | 61 | id_field = second_compare_list[1][1] |
40 | name_field = second_compare_list[0][1] | 62 | name_field = second_compare_list[0][1] |
... | @@ -881,7 +903,7 @@ def get_se_compare_info(last_obj, application_entity, detect_list): | ... | @@ -881,7 +903,7 @@ def get_se_compare_info(last_obj, application_entity, detect_list): |
881 | return compare_info, is_gsyh | 903 | return compare_info, is_gsyh |
882 | 904 | ||
883 | 905 | ||
884 | def cms_get_se_compare_info(last_obj, application_entity, detect_list): | 906 | def rebuild_compare_info(last_obj): |
885 | # { | 907 | # { |
886 | # "content": { | 908 | # "content": { |
887 | # "financeCompany": "宝马汽车金融有限公司", | 909 | # "financeCompany": "宝马汽车金融有限公司", |
... | @@ -982,7 +1004,15 @@ def cms_get_se_compare_info(last_obj, application_entity, detect_list): | ... | @@ -982,7 +1004,15 @@ def cms_get_se_compare_info(last_obj, application_entity, detect_list): |
982 | # } | 1004 | # } |
983 | # } | 1005 | # } |
984 | # } | 1006 | # } |
985 | pass | 1007 | |
1008 | return FakePOS(application_id, | ||
1009 | first_submmison_date, | ||
1010 | application_version, | ||
1011 | customer_type, | ||
1012 | individual_cus_info, | ||
1013 | corporate_cus_info, | ||
1014 | vehicle_info, | ||
1015 | bank_info) | ||
986 | 1016 | ||
987 | 1017 | ||
988 | def se_compare_license(license_en, ocr_res_dict, field_list): | 1018 | def se_compare_license(license_en, ocr_res_dict, field_list): |
... | @@ -1205,8 +1235,7 @@ def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res | ... | @@ -1205,8 +1235,7 @@ def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res |
1205 | start_time = datetime.now() | 1235 | start_time = datetime.now() |
1206 | detect_list = se_result_detect(ocr_res_dict) | 1236 | detect_list = se_result_detect(ocr_res_dict) |
1207 | if is_cms: | 1237 | if is_cms: |
1208 | compare_info, is_gsyh = cms_get_se_compare_info(last_obj, application_entity, detect_list) | 1238 | last_obj = rebuild_compare_info(last_obj) |
1209 | else: | ||
1210 | compare_info, is_gsyh = get_se_compare_info(last_obj, application_entity, detect_list) | 1239 | compare_info, is_gsyh = get_se_compare_info(last_obj, application_entity, detect_list) |
1211 | compare_result, total_fields, failed_count, successful_at_this_level, failure_reason_str = se_compare_process( | 1240 | compare_result, total_fields, failed_count, successful_at_this_level, failure_reason_str = se_compare_process( |
1212 | compare_info, ocr_res_dict, is_gsyh) | 1241 | compare_info, ocr_res_dict, is_gsyh) |
... | @@ -1264,7 +1293,30 @@ def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res | ... | @@ -1264,7 +1293,30 @@ def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res |
1264 | traceback.format_exc())) | 1293 | traceback.format_exc())) |
1265 | 1294 | ||
1266 | # cms结果发送 | 1295 | # cms结果发送 |
1267 | 1296 | if is_cms: | |
1297 | try: | ||
1298 | application_link = '{0}/showList/showList?entity={1}&scheme={2}&case_id={3}'.format( | ||
1299 | conf.BASE_URL, application_entity, consts.COMPARE_DOC_SCHEME_LIST[1], application_id) | ||
1300 | data = { | ||
1301 | "SubtenantId": consts.TENANT_MAP[application_entity], | ||
1302 | "Data": { | ||
1303 | "Result_Message": "Pass" if successful_at_this_level else "Fail", | ||
1304 | "Failure_Reason": failure_reason_str, | ||
1305 | "Application_Number": application_id, | ||
1306 | "Bank_Statement": "", | ||
1307 | "Link_URL": application_link, | ||
1308 | "OCR_Version": 1, | ||
1309 | "Origin": consts.INFO_SOURCE[1] | ||
1310 | } | ||
1311 | } | ||
1312 | response = cms.send(data) | ||
1313 | except Exception as e: | ||
1314 | compare_log.error('{0} [SE] [cms error] [entity={1}] [id={2}] [ocr_res_id={3}] ' | ||
1315 | '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, | ||
1316 | traceback.format_exc())) | ||
1317 | else: | ||
1318 | compare_log.info('{0} [SE] [cms success] [entity={1}] [id={2}] [ocr_res_id={3}] [response={4}]'.format( | ||
1319 | log_base, application_entity, application_id, ocr_res_id, response)) | ||
1268 | 1320 | ||
1269 | @app.task | 1321 | @app.task |
1270 | def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True, is_cms=False): | 1322 | def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True, is_cms=False): | ... | ... |
... | @@ -36,6 +36,7 @@ class RedisHandler: | ... | @@ -36,6 +36,7 @@ class RedisHandler: |
36 | self.common_queue_key = '{0}:common_queue'.format(self.prefix) | 36 | self.common_queue_key = '{0}:common_queue'.format(self.prefix) |
37 | self.priority_queue_key = '{0}:priority_queue'.format(self.prefix) | 37 | self.priority_queue_key = '{0}:priority_queue'.format(self.prefix) |
38 | self.session_id_key = '{0}:session_id'.format(self.prefix) | 38 | self.session_id_key = '{0}:session_id'.format(self.prefix) |
39 | self.cms_token_key = '{0}:cms_token'.format(self.prefix) | ||
39 | 40 | ||
40 | def enqueue(self, tasks, is_priority=False): | 41 | def enqueue(self, tasks, is_priority=False): |
41 | # 1 | 42 | # 1 |
... | @@ -57,3 +58,9 @@ class RedisHandler: | ... | @@ -57,3 +58,9 @@ class RedisHandler: |
57 | def get_session_id(self): | 58 | def get_session_id(self): |
58 | return self.redis.get(self.session_id_key) | 59 | return self.redis.get(self.session_id_key) |
59 | 60 | ||
61 | def get_cms_token(self): | ||
62 | return self.redis.get(self.cms_token_key) | ||
63 | |||
64 | def set_cms_token(self, token, expires=None): | ||
65 | return self.redis.set(self.cms_token_key, token, expires) | ||
66 | ... | ... |
src/common/tools/3des.py
0 → 100644
1 | from Crypto.Cipher import DES3 | ||
2 | from Crypto.Hash import MD5 | ||
3 | import struct | ||
4 | import base64 | ||
5 | import codecs | ||
6 | |||
7 | |||
8 | def mds_hash(target_str): | ||
9 | h = MD5.new() | ||
10 | h.update(target_str.encode('utf-8')) | ||
11 | return h.digest() | ||
12 | |||
13 | |||
14 | def des_pad(data): | ||
15 | data = data.encode('utf-8') | ||
16 | e = len(data) | ||
17 | x = (e + 4) % 8 | ||
18 | y = 0 if x == 0 else 8 - x | ||
19 | size_byte = struct.pack('>I', e) | ||
20 | result_byte = list(range(len(size_byte) + e + y)) | ||
21 | result_byte[0:4] = size_byte | ||
22 | result_byte[4:4 + e] = data | ||
23 | for i in range(0, y): | ||
24 | result_byte[e + 4 + i] = 0 | ||
25 | result_str = bytearray(result_byte).decode('utf-8') | ||
26 | return result_str | ||
27 | |||
28 | |||
29 | # DES3加密数据 | ||
30 | def encode_des(to_encode_str, des_key): | ||
31 | """ | ||
32 | DES3加密数据 | ||
33 | Args: | ||
34 | to_encode_str(str): 要被加密的原字符串,这里的字符串需要被des_pad一下 | ||
35 | des_key(str): 加密的key | ||
36 | Returns: | ||
37 | |||
38 | """ | ||
39 | key = mds_hash(des_key) | ||
40 | des3 = DES3.new(key, DES3.MODE_ECB) | ||
41 | data = des3.encrypt(des_pad(to_encode_str)) | ||
42 | data = codecs.encode(data, 'hex') | ||
43 | return data | ||
44 | |||
45 | |||
46 | def un_des_pad(data): | ||
47 | result_byte = data[0:4] | ||
48 | e = struct.unpack('>I', result_byte)[0] | ||
49 | x = (e + 4) % 8 | ||
50 | y = 0 if x == 0 else 8 - x | ||
51 | return data[4:] if y == 0 else data[4:-y] | ||
52 | |||
53 | |||
54 | def decode_des(to_decode_str, des_key): | ||
55 | """ | ||
56 | 解密数据 | ||
57 | Args: | ||
58 | to_decode_str(str): 要解密的原字符串 | ||
59 | des_key(str): 解密的key | ||
60 | Returns: | ||
61 | |||
62 | """ | ||
63 | key = mds_hash(des_key) | ||
64 | des3 = DES3.new(key, DES3.MODE_ECB) | ||
65 | param = base64.b64decode(to_decode_str) | ||
66 | |||
67 | param = des3.decrypt(param) | ||
68 | param = un_des_pad(param).decode('utf-8') | ||
69 | return param |
-
Please register or sign in to post a comment